11

用junit测试drools规则的最佳实践是什么?

到目前为止,我们使用 junit 和 dbunit 来测试规则。我们有放入 hsqldb 的样本数据。我们有几个规则包,到项目结束时,很难做出好的测试输入来测试某些规则而不触发其他规则。

所以确切的问题是,我如何将 junit 中的测试限制为一个或多个特定的测试规则?

4

5 回答 5

7

我个人使用单元测试来测试孤立的规则。我认为这并没有什么太大的问题,只要您不会因为孤立的规则在起作用而误以为您的知识库正在起作用,从而产生错误的安全感。测试整个知识库更为重要。

您可以使用AgendaFilter和 StatelessSession编写隔离测试

StatelessSession session = ruleBase.newStatelessSesssion();

session.setAgendaFilter( new RuleNameMatches("<regexp to your rule name here>") );

List data = new ArrayList();
... // create your test data here (probably built from some external file)

StatelessSessionResult result == session.executeWithResults( data );

// check your results here.

代码来源:http ://blog.athico.com/2007/07/my-rules-dont-work-as-expected-what-c​​an.html

于 2010-10-11T08:57:52.733 回答
5

不要试图将规则执行限制为测试的单个规则。与 OO 类不同,单个规则并不独立于其他规则,因此以与使用单元测试测试单个类相同的方式单独测试规则是没有意义的。换句话说,要测试单个规则,请测试它与其他规则组合是否具有正确的效果。

相反,在所有规则上使用少量数据运行测试,即在规则会话中使用最少数量的事实,并测试结果并可能触发特定规则。结果实际上与您的想法并没有太大不同,因为一组最小的测试数据可能只会激活一个或两个规则。

至于样本数据,我更喜欢使用静态数据,并为每个测试定义最少的测试数据。有多种方法可以做到这一点,但在 Java 中以编程方式创建事实对象可能就足够了。

于 2010-10-06T07:58:20.157 回答
5

我创建了一个简单的库来帮助为 Drools 编写单元测试。其中一项功能正是您所需要的:声明要用于单元测试的特定 drl 文件:

@RunWith(DroolsJUnitRunner.class)
@DroolsFiles(value = "helloworld.drl", location = "/drl/")
public class AppTest {

    @DroolsSession
    StatefulSession session;

    @Test
    public void should_set_discount() {
        Purchase purchase = new Purchase(new Customer(17));

        session.insert(purchase);
        session.fireAllRules();

        assertTrue(purchase.getTicket().hasDiscount());
    }
}

有关更多详细信息,请查看博客文章:https ://web.archive.org/web/20140612080518/http://maciejwalkowiak.pl/blog/2013/11/24/jboss-drools-unit-testing-with- junit 流口水/

于 2013-11-26T10:14:26.663 回答
4

使用 DBUnit 进行单元测试并没有真正起作用。使用 DBUnit 进行集成测试。原因如下: - 单元测试应该很快。-- DBUnit 数据库恢复很慢。轻松花 30 秒。-- 一个真实的应用程序有许多非空列。因此,为单个特征隔离的数据仍然很容易使用数据库的一半表。- 应该隔离单元测试。-- 为每个测试恢复 dbunit 数据库以保持它们隔离有缺点: --- 运行所有测试需要几个小时(尤其是随着应用程序的增长),所以没有人运行它们,所以它们经常中断,所以它们被禁用,所以有没有测试,所以你的应用程序充满了错误。---为每个单元测试创​​建半个数据库是大量的创建工作,大量的维护工作,很容易变得无效(关于验证哪个数据库模式不'

相反,使用 DBunit 编写集成测试: - 一个 DBunit,所有测试都相同。仅加载一次(即使您运行 500 次测试)。-- 将每个测试包装在一个事务中,并在每次测试后回滚数据库。无论如何,大多数方法都使用所需的传播。仅当传播为 requires_new 时才将 testdata 设置为脏(如果有下一个测试,则在下一个测试中将其重置)。- 用极端案例填充该数据库。不要添加比测试业务规则严格需要的更多常见案例,因此通常只有 2 个常见案例(能够测试“一对多”)。- 编写面向未来的测试: - 不要测试激活规则的数量或插入事实的数量。-- 相反,测试结果中是否存在某个插入的事实。

于 2010-10-11T08:56:09.350 回答
0

单元测试是关于获取最少的代码并测试定义规范的所有可能的用例。通过集成测试,您的目标不是所有可能的用例,而是集成多个协同工作的单元。对规则做同样的事情。按业务意义和目的划分规则。最简单的“待测单元”可以是具有单一或高内聚规则集的文件,以及它工作所需的内容(如果有的话),如常见的 dsl 定义文件和决策表。对于集成测试,您可以采用有意义的子集或系统的所有规则。

使用这种方法,您将拥有许多独立的单元测试和很少的集成测试,它们使用有限的公共输入数据来重现和测试常见场景。添加新规则不会影响大多数单元测试,但很少会影响集成测试,并将反映新规则如何影响常见数据流。

考虑可能适合这种方法的JUnit测试库

于 2015-02-25T15:24:47.850 回答