38、Jess Java API 与自动化测试框架介绍

Jess Java API 与自动化测试框架介绍

1. Jess 简化 Java API 概述

Jess 库包含约 75 个公共类,但很多类 Jess 程序员很少使用。本部分仅列出最重要类的最重要方法,有助于初学者快速上手 Jess 库。以下是主要类及其方法介绍:

1.1 jess.Context

该类代表函数的执行上下文。若用 Java 编写 Jess 函数, call 方法会传入 Context 对象,通过它可访问函数执行所在的 Rete 对象及相关变量的值。
- public Rete getEngine() :返回与调用代码相关的 Rete 对象。
- public Value getVariable(String name) :返回变量的值,参数为不带 ? $ 前缀的变量名,可用于获取 defglobal 的当前值。
- public void setVariable(String name, Value value) :设置变量的值,第一个参数为不带 ? $ 前缀的变量名。

1.2 jess.Fact

Fact 类代表 Jess 工作内存中的一个条目,是 ValueVector 的子类。
- public Fact(String name, Rete engine) :向 Rete 对象请求指定名称的模板,若不存在则创建一个有序模板,这是最常用的构造函数。
- public Deftemplate getDeftemplate() :返回 Fact Deftemplate ,可获取 Fact 的名称、槽数量和槽名称。
- public int getFactId() :返回 Fact 的数字标识符,每个 Fact 都有一个。
- public int getShadowMode() :若不是影子事实,返回 Fact.NO ;否则根据影子事实类型返回 Fact.DYNAMIC Fact.STATIC
- public Value getSlotValue(String name) :返回指定名称槽的值,有序事实有一个名为 __data 的单槽,包含一个项目列表。
- public void setSlotValue(String name, Value value) :按名称设置槽的值,不要对当前在 Jess 工作内存中的 Fact 调用此方法。

1.3 jess.Funcall

Funcall 是代表函数调用的特殊列表。若需从 Java 多次调用 Jess 函数且变化不大,构建 Funcall 对象并调用 execute 方法通常更高效。
- public Funcall(String name, Rete engine) :接受要调用的函数名称,函数在创建时不必已定义,只要在调用 execute 时已定义即可。
- public Funcall arg(Value v) :向 Funcall 追加一个参数,此方法返回修改后的 Funcall 对象,可链式调用。
- public Value execute(Context context) :使用给定的 Context 执行 Funcall ,若没有 Context ,可调用 Rete.getGlobalContext() 获取。

1.4 jess.Jesp

Jesp 是 Jess 解析器,若想让 Jess 从网络流或其他不寻常源读取输入,可使用此类。
- public Jesp(java.io.Reader reader, Rete engine) :接受一个 Reader 对象作为输入源,Jess 代码流将被执行并应用于给定的 Rete 对象。
- public Value parse(boolean prompt) :进行解析,返回最后一个表达式求值的结果。若 prompt true ,在读取每个表达式前会将 Jess> 提示符打印到 WSTDOUT 路由器。

1.5 jess.JessEvent

使用 Rete 类的 setEventMask 方法请求后,Jess 在某些事情发生时会发送 JessEvent 对象作为通知。每个 JessEvent 都有一个类型表示发生的事情,以及一个提供更多信息的对象。

类型 对象类型 描述
ACTIVATION jess.Activation 一个 defrule 被激活或停用
CLEAR jess.Rete 执行了 (clear)
DEFCLASS defclass 的名称 一个 defclass 被添加或移除
DEFFACT jess.Deffacts 一个 deffacts 被添加或移除
DEFGLOBAL jess.Defglobal 一个 defglobal 被添加或移除
DEFINSTANCE JavaBean 一个 definstance 被添加或移除
DEFRULE jess.Defrule 一个 defrule 被添加或移除
DEFRULE_FIRED jess.Activation 一个 defrule 被触发
DEFTEMPLATE jess.Deftemplate 一个 deftemplate 被添加或移除
FACT jess.Fact 一个事实被断言或撤销
FOCUS 模块名称 模块焦点已更改
HALT jess.Rete 执行了 (run)
RESET jess.Rete 执行了 (reset)
RUN jess.Rete 执行了 (run)
USERFUNCTION jess.Userfunction 一个 Userfunction 被添加或移除
USERFUNCTION_CALLED jess.Userfunction 一个 Userfunction 被调用
USERPACKAGE jess.Userpackage 一个 Userpackage 被添加或移除
  • public int getType() :返回事件类型,是上表中的常量之一。
  • public Object getObject() :返回与事件相关的数据。
  • public Object getSource() :返回事件的源,即生成它的 Rete 对象。
1.6 jess.JessListener

若想接收 JessEvent ,需实现此接口,其工作方式与 java.awt.event 包中的事件监听器类似。
- public void eventHappened(JessEvent je) throws JessException :处理事件类型的事件,这是此接口中唯一的处理方法,处理程序应测试 JessEvent 中的 getType() 方法来决定采取什么行动。

1.7 jess.PrettyPrinter

此类知道如何格式化许多 Jess 构造,使其对人类读者更友好。它使用访问者模式,有许多名为 visitXXX 的方法,但通常不需要使用。
- public PrettyPrinter(Visitable v) :参数可以是实现 Visitable 接口的任何 Jess 类的实例,包括 Deffacts Deffunction Defglobal Defquery Defrule Deftemplate
- public String toString() :返回作为构造函数参数传入的构造的格式化版本。

1.8 jess.Rete

Rete 类是 Jess 最重要部分的外观类,有管理工作内存、议程、规则库等的方法。以下是一些重要方法:
- public Rete(Object appObject) :构造一个新的 Rete 对象,参数的 ClassLoader 用于加载 new call defclass 等命令使用的任何类。
- public Rete() :使用 this 作为应用程序对象。

1.8.1 处理事件
  • public void addJessListener(JessListener jel) :注册一个 JessListener 以接收事件。
  • public void removeJessListener(JessListener jel) :注销一个 JessListener ,使其不再接收事件。
  • public int getEventMask() :获取当前事件掩码的值。
  • public void setEventMask(int mask) :设置事件掩码,通常应使用 | 运算符将此值与 getEventMask 返回的值组合。
1.8.2 与 Jess 语言代码交换 Java 值
  • public void clearStorage() :清除存储区域,使 store 对任何名称都返回 null
  • public Value fetch(java.lang.String name) :检索之前使用 store 存储的对象。
  • public Value store(java.lang.String name, java.lang.Object val) :以给定名称存储一个对象,对象在存储前会包装在 Value 对象中。
  • public Value store(java.lang.String name, Value val) :以给定名称存储一个 Value
1.8.3 导入表
  • public java.lang.Class findClass(String clazz) :根据类名,使用导入表得出完全限定名,若传入 "String" 作为参数,返回 java.lang.String Class
  • public void importClass(String clazz) :将完全限定类名添加到导入表。
  • public void importPackage(String pack) :通过将包名添加到导入表来导入包中的每个类。
1.8.4 查找事物

有一组方法可从引擎中检索 Defrule Deffacts 等构造的实例,都接受构造的名称作为参数,若名称不包含模块名,则使用当前模块的名称。
- public Fact findFactByFact(Fact f) :快速查找,可用于快速确定给定事实是否在事实列表中,若存在则获取其引用,参数是与要查找的事实相同的 Fact
- public Fact findFactByID(int id) :根据数字标识符查找事实,此方法非常慢,除非必要否则不要使用。
- public Iterator listXXX() :许多方法返回 java.util.Iterators 遍历 Jess 构造的集合,包括 listActivations listDeffacts listDefglobals 等。

1.8.5 等待规则触发
  • public Object getActivationSemaphore() :返回此引擎的激活信号量,每当有激活出现时,激活信号量的监视器会被通知,因此可在此对象上调用 wait() ,只有当 Jess 准备触发规则时, wait() 调用才会返回。
  • public void waitForActivations() :直到议程上有规则准备触发才返回。
1.9 jess.RU

RU 代表 Rete Utilities ,是一个包含一些有用常量的通用类,大多数常量枚举了 Value.getType 允许的返回值,即不同类型的 Value 对象。最重要的常量有(均为静态、最终的 int 变量): ATOM (符号)、 EXTERNAL_ADDRESS FACT FLOAT FUNCALL INTEGER LIST LONG MULTIVARIABLE STRING VARIABLE
- public static String gensym(String prefix) :返回以给定前缀开头的唯一符号,若 Java 代码自动生成 Jess 规则、变量或其他实体,且需要生成唯一名称,此方法很有用。

1.10 jess.Token

Token 类代表一组事实在 Jess 的 Rete 网络中一起传播的情况。 Rete.runQuery() 返回的迭代器或 Jess 中的 run-query 函数返回一系列 Token 对象,否则通常不需要处理此类。
- public Fact getFact(int index) :从 Token 中返回单个 Fact ,与规则中第一个模式匹配的事实索引为 0。
- public int size() :返回 Token 中的事实数量。
- public Fact topFact() :相当于 token.getFact(token.size() - 1)

1.11 jess.Value

这是一个重要的类,因为通过 Jess 传输的每个信息(数字、字符串、Java 对象)都包装在 jess.Value 实例或其子类中。
- public Value(boolean b) :构造一个布尔值对象( TRUE FALSE 符号之一)。
- public Value(double d, int type) :构造一个数值,类型可以是 INTEGER FLOAT
- public Value(int value, int type) :构造一个数值,类型可以是 INTEGER FLOAT ,使用 LongValue 类构造 LONG 类型的 Value
- public Value(java.lang.Object o) :构造一个包含 Java 对象的 Value (类型为 EXTERNAL_ADDRESS )。
- public Value(java.lang.String s, int type) :构造一个词法值,类型可以是 STRING ATOM
- public Value(Value v) :复制一个值。
- public Value(ValueVector f, int type) :构造一个 LIST 类型的值。
- public int type() :返回此变量的类型,是 RU 中的常量之一。
- public Value resolveValue(Context c) :给定一个评估上下文,返回此 Value 的真实值,对于变量,指变量的值;对于包含函数调用对象的 Value 对象,调用函数并提供返回值。
- public String atomValue(Context c) :以符号形式返回此值的内容。
- public Object externalAddressValue(Context c) :以 Java 对象形式返回此值的内容。
- public Fact factValue(Context c) :以事实形式返回此值的内容。
- public double floatValue(Context c) :以数字形式返回此值的内容。
- public Funcall funcallValue(Context c) :以函数调用形式返回此值的内容。
- public int intValue(Context c) :以整数形式返回此值的内容。
- public ValueVector listValue(Context c) :以列表形式返回此值的内容。
- public long longValue(Context c) :以长整数形式返回此值的内容。
- public double numericValue(Context c) :以数字形式返回此值的内容。
- public String stringValue(Context c) :以字符串形式返回此值的内容。
- public String variableValue(Context c) :以字符串形式返回此值的内容(变量名)。

1.12 jess.ValueVector

ValueVector Value 对象的列表,此类既可以直接使用,也可作为 Fact 和其他重要 Jess 类的基类,与 java.util.Vector java.util.ArrayList 类非常相似,有容量和大小的概念。
- public ValueVector() :构造一个默认容量为 10 的 ValueVector
- public ValueVector(int size) :构造一个具有给定容量的 ValueVector
- public ValueVector add(Value val) :在 ValueVector 末尾添加一个新元素。
- public Value get(int i) :获取列表中位置 i 的条目。
- public ValueVector remove(int i) :从列表中移除给定索引处的项,将所有编号较高的元素下移。
- public ValueVector set(Value val, int i) :将位置 i 的条目设置为 val
- public ValueVector setLength(int i) :设置列表的大小,此索引及以上的 Value 对象不再是列表的一部分。
- public int size() :返回 ValueVector Value 对象的数量。

2. Jess 自动化测试框架

在迭代开发中,自动化测试能让你确信每次添加或修改不会给先前正常工作的程序引入错误。修改代码后运行测试,可立即知道更改是否破坏了现有代码。拥有一套快速便捷的自动化测试套件有助于更快地编写更好的代码,这对于基于规则的编程和其他类型的编程同样适用。

2.1 架构

Jess 测试框架基于 Bourne shell 脚本,在类 UNIX 系统上易于使用,也可通过安装 Cygwin 等 UNIX 仿真工具包在 Windows 系统上使用,当然,也可以使用批处理文件编写自己的测试框架。

测试框架的整体架构使用一个顶级 tests 目录,包含几个模板子目录和每个测试的一个额外子目录。要添加测试,复制一个模板目录并编辑其中的文件。每个目录(包括顶级目录)都包含一个 Makefile 和一个名为 runtest.sh 的 shell 脚本,测试目录还包含其他文件。以下是添加任何测试之前框架的目录结构:

tests/
├── template1/
│   ├── Makefile
│   └── runtest.sh
├── template2/
│   ├── Makefile
│   └── runtest.sh
└── ...

综上所述,Jess 的 Java API 提供了丰富的功能和方法,可用于开发基于 Jess 的应用程序,而自动化测试框架则有助于保证代码的质量和稳定性。在实际开发中,可以根据具体需求选择合适的 API 方法和测试框架来提高开发效率和代码质量。后续,我们可以进一步探讨如何结合这些 API 和测试框架进行更复杂的应用开发。

Jess Java API 与自动化测试框架介绍

3. 操作步骤与示例
3.1 使用 Jess Java API 的操作步骤
  • 创建 Rete 对象
    • 若需要指定应用对象的 ClassLoader ,可使用 public Rete(Object appObject) 构造函数。示例代码如下:
import jess.Rete;
public class JessExample {
    public static void main(String[] args) {
        Object appObject = new Object();
        Rete engine = new Rete(appObject);
    }
}
- 若使用当前对象作为应用程序对象,可使用 `public Rete()` 构造函数。示例代码如下:
import jess.Rete;
public class JessExample {
    public static void main(String[] args) {
        Rete engine = new Rete();
    }
}
  • 注册事件监听器
    • 首先实现 JessListener 接口。示例代码如下:
import jess.JessEvent;
import jess.JessListener;
import jess.JessException;
public class MyJessListener implements JessListener {
    @Override
    public void eventHappened(JessEvent je) throws JessException {
        int type = je.getType();
        Object object = je.getObject();
        System.out.println("Event type: " + type + ", Object: " + object);
    }
}
- 然后使用 `addJessListener` 方法注册监听器。示例代码如下:
import jess.Rete;
import jess.JessListener;
public class JessExample {
    public static void main(String[] args) {
        Rete engine = new Rete();
        JessListener listener = new MyJessListener();
        engine.addJessListener(listener);
    }
}
  • 存储和检索 Java 值
    • 存储值使用 store 方法。示例代码如下:
import jess.Rete;
import jess.Value;
public class JessExample {
    public static void main(String[] args) {
        Rete engine = new Rete();
        String name = "myObject";
        Object val = new Object();
        engine.store(name, val);
    }
}
- 检索值使用 `fetch` 方法。示例代码如下:
import jess.Rete;
import jess.Value;
public class JessExample {
    public static void main(String[] args) {
        Rete engine = new Rete();
        String name = "myObject";
        Value value = engine.fetch(name);
    }
}
  • 查找类
    • 使用 findClass 方法根据类名查找类。示例代码如下:
import jess.Rete;
import java.lang.Class;
public class JessExample {
    public static void main(String[] args) {
        Rete engine = new Rete();
        String clazz = "String";
        Class<?> foundClass = engine.findClass(clazz);
    }
}
  • 等待规则触发
    • 使用 waitForActivations 方法等待规则触发。示例代码如下:
import jess.Rete;
public class JessExample {
    public static void main(String[] args) {
        Rete engine = new Rete();
        try {
            engine.waitForActivations();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
3.2 添加 Jess 测试的操作步骤
  • 复制模板目录 :从顶级 tests 目录下选择一个模板目录进行复制。例如,复制 template1 目录:
cp -r tests/template1 tests/myTest
  • 编辑文件 :进入复制后的目录 tests/myTest ,编辑 Makefile runtest.sh 文件以满足测试需求。
  • 运行测试 :在 tests/myTest 目录下运行 runtest.sh 脚本。
cd tests/myTest
./runtest.sh
4. 总结与展望

Jess 的 Java API 为开发者提供了强大的工具,能够方便地与 Jess 进行交互,实现基于规则的应用开发。通过使用这些 API 方法,可以管理工作内存、议程、规则库等,还能与 Java 代码进行数据交换。同时,自动化测试框架的存在保证了代码的质量和稳定性,让开发者在迭代开发中更加自信。

在未来的开发中,可以进一步探索如何更深入地利用 Jess Java API 实现复杂的规则引擎应用,例如结合机器学习算法进行规则的自动生成和优化。此外,还可以对自动化测试框架进行扩展,增加更多的测试用例和测试场景,以提高代码的健壮性。

以下是 Jess Java API 使用和测试框架操作的流程图:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px

    A([开始]):::startend --> B(使用 Jess Java API):::process
    B --> C(创建 Rete 对象):::process
    C --> D(注册事件监听器):::process
    D --> E(存储和检索 Java 值):::process
    E --> F(查找类):::process
    F --> G(等待规则触发):::process
    G --> H(使用自动化测试框架):::process
    H --> I(复制模板目录):::process
    I --> J(编辑文件):::process
    J --> K(运行测试):::process
    K --> L([结束]):::startend

Jess Java API 和自动化测试框架为开发者提供了丰富的功能和便利,合理利用它们可以提高开发效率和代码质量,为基于规则的应用开发带来更多的可能性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值