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

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

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

有帮助吗?

解决方案

我个人使用单元测试来测试孤立的规则。我认为这没有什么太大的问题,只要你不陷入一种错误的安全感,即你的知识库正在发挥作用,因为孤立的规则正在发挥作用。测试整个知识库更为重要。

您可以使用以下命令编写隔离测试 议程过滤器 和无状态会话

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

其他提示

我创建简单的库,有助于写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());
    }
}

有关详细信息,对博客文章一看:的 http://maciejwalkowiak.pl/blog/2013/11/24/jboss-drools-unit-testing-with-junit-drools/

不要试图限制规则执行一种用于测试单个规则。不像OO类,单一规则都不是独立的其他规则,所以它没有任何意义以同样的方式,你会使用单元测试测试一个类来测试规则隔离。换句话说,测试单个规则,测试,它在组合与其他规则的权利的效果。

相反,运行测试数据对所有规则少量,即用最少数量的规则会话的事实,以及测试结果,也许这一个特定规则被解雇了。其结果是不实际,从你心里有什么,因为一组测试数据的最小可能只激活一个或两个规则非常不同。

作为用于样本数据,我更喜欢使用的静态数据和为每个测试限定最小的测试数据。在Java中这样做,但以编程方式创建事实对象可能是足够好的的各种方法。

用DbUnit单元测试并不真正的工作。用DbUnit的集成测试一样。这是因为: - 单元测试要快。 - 一个DBUnit的数据库恢复是缓慢的。容易需要30秒。 - 一个真实世界的应用程序有许多不为空栏。所以数据,隔离单功能,仍然可以轻松地使用数据库的一半表。 - 一个单元测试应予以隔离。 - 恢复的DbUnit数据库每一个测试,让他们孤立也有缺点: ---运行所有测试需要时间(尤其是在应用程序的增长),所以没有一个运行他们,因此他们不断突破,所以他们是残疾人,所以没有测试,所以你的应用是完全错误的。 ---创建半个数据库为每个单元测试了很多创作的工作,很多维修工作中,很容易成为无效的(至于验证其数据库架构的不支持,请参阅Hibernate验证)和ussually没有坏表示现实的工作。

相反,写入集成测试用DbUnit: - 一个DBUnit的,同样为所有测试。加载它只有一次(即使您运行500个测试)。 - 总结每个测试在一个事务中,每个测试后回滚数据库。大多数方法使用反正传播所需。设置TESTDATA脏只(将其重置用于下一次检查是否存在下一个测试)仅当传播是REQUIRES_NEW。 - 装满角落案件数据库。不要添加超过严格需要测试您的业务规则更常见的情况,所以ussually只有2通常情况下(要能测试“一对多”)。 - 写面向未来的测试: - 不测试的激活规则的数目或插入的事实的数量。 - 相反,如果测试在一定插入的事实是存在于该结果。过滤上的特定属性设置为X(从该属性的共同值不同)的结果和测试与该属性设置为X插入事实的数目。

为什么不选择与 Java 代码相同的方法来进行单元测试和集成测试呢?单元测试是关于采用最少的代码并测试定义规范的所有可能的用例。通过集成测试,您的目标不是所有可能的用例,而是集成多个协同工作的单元。对规则也做同样的事情。按业务含义和目的分隔规则。最简单的“测试单元”可以是带有单个或 高凝聚力 一组规则及其工作所需的内容(如果有),例如通用 dsl 定义文件和决策表。对于集成测试,您可以采用系统的有意义的子集或所有规则。

通过这种方法,您将拥有许多独立的单元测试,这些测试不会受到影响,并且在添加新规则时不需要支持,因为您将拥有一组独立的业务规则以及输入数据子集来测试相应的业务场景。而且您将进行很少的集成测试,使用有限数量的常见输入数据来重现和测试“常见场景”。向集成测试添加新规则将需要更新测试输出,并将反映新规则如何影响公共数据流。

考虑 JUnit测试规则 这使您可以以声明方式加载资源并断言实际触发的规则。它将保留内部断言失败并报告任何触发不匹配的规则,让您一目了然地提示出了什么问题。日志记录揭示了事件之间的因果关系。与 SpringRunner.class 用于弹簧集成测试。

例子:

@DroolsSession(resources = {
        "classpath*:/org/droolsassert/rules.drl",
        "classpath*:/com/company/project/*/{regex:.*.(drl|dsl|xlsx|gdst)}",
        "classpath*:/com/company/project/*/ruleUnderTest.rdslr" },
        ignoreRules = { "before", "after" })
public class DroolsAssertTest {

    @Rule
    public DroolsAssert drools = new DroolsAssert();

    @Test
    @AssertRules("atomic int rule")
    public void testInt() {
        drools.insertAndFire(new AtomicInteger());
        assertEquals(1, drools.getObject(AtomicInteger.class).get());
    }
}

规则.drl
更多的: https://github.com/droolsassert/droolsassert

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top