使用junit进行Drools测试

使用junit进行Drools测试,junit,drools,rule-engine,drools-flow,jboss-rules,Junit,Drools,Rule Engine,Drools Flow,Jboss Rules,用junit测试drools规则的最佳实践是什么 到目前为止,我们使用junit和dbunit来测试规则。我们已经将样本数据放入了hsqldb。我们有两个规则包,到项目结束时,很难做出一个好的测试输入来测试某些规则而不触发其他规则 因此,确切的问题是,如何将junit中的测试限制为一个或多个特定的测试规则?不要试图将规则执行限制为一个测试的单个规则。与OO类不同,单个规则并不独立于其他规则,因此,以与使用单元测试单个类相同的方式单独测试规则是没有意义的。换言之,要测试单个规则,请测试它与其他规则

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

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


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

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

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


至于示例数据,我更喜欢使用静态数据,并为每个测试定义最小的测试数据。有多种方法可以做到这一点,但是用Java编程创建事实对象可能已经足够了。

使用DBUnit进行单元测试并不能真正起作用。使用DBUnit进行集成测试。原因如下: -单元测试应该是快速的。 --DBUnit数据库还原速度很慢。30秒很容易。 --实际应用程序有许多非空列。因此,对于单个功能而言,数据是孤立的,但仍然可以轻松地使用数据库中一半的表。 -单元测试应该是隔离的。 --为每个测试恢复dbunit数据库以使其保持隔离有缺点: ---运行所有测试需要几个小时(特别是随着应用程序的增长),所以没有人运行它们,所以它们经常中断,所以它们被禁用,所以没有测试,所以应用程序充满了bug。 ---为每个单元测试创建半个数据库需要大量的创建工作和维护工作,很容易变得无效(关于数据库模式不支持的验证,请参阅Hibernate Validator),并且通常在表示现实方面做得很差

相反,使用DBunit编写集成测试: -一个DBunit,所有测试相同。只加载一次(即使运行500个测试)。 --在事务中包装每个测试,并在每个测试后回滚数据库。大多数方法都使用所需的传播。仅当传播是新的时,才设置testdata dirty only(如果有下一个测试,则在下一个测试中重置它)。 -用角落的箱子填满数据库。不要添加比测试业务规则严格需要的更多的常见案例,因此通常只有2个常见案例(能够测试“一对多”)。 -编写未来验证测试: --不要测试激活规则的数量或插入事实的数量。
--相反,测试结果中是否存在某个插入的事实。过滤设置为X的某个属性的结果(与该属性的公共值不同),并测试该属性设置为X时插入的事实数。

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

您可以使用和无状态会话编写隔离测试

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.
StatelessSession=ruleBase.newstatelesssession();
session.setAgendaFilter(新的RuleNameMatches(“”);
列表数据=新的ArrayList();
... // 在这里创建测试数据(可能是从一些外部文件构建的)
无状态SessionResult==session.executeWithResults(数据);
//在这里检查您的结果。

代码源:

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

@RunWith(DroolsJUnitRunner.class)
@DroolsFiles(value=“helloworld.drl”,location=“/drl/”)
公共类应用程序测试{
@下垂期
国家会议;
@试验
公共作废应设置折扣(){
采购=新采购(新客户(17));
会议.插入(购买);
session.fireAllRules();
assertTrue(purchase.getTicket().hasDiscount());
}
}

有关更多详细信息,请查看博客帖子:

单元测试是关于获取最少的代码并测试定义规范的所有可能用例。通过集成测试,您的目标不是所有可能的用例,而是集成几个协同工作的单元。规则也是如此。按业务含义和目的划分规则。最简单的“测试单元”可以是包含单个或一组规则的文件,以及它工作所需的内容(如果有),如通用dsl定义文件和决策表。对于集成测试,您可以选择有意义的子集或系统的所有规则

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


考虑一下适合这种方法的JUnit

是的,我知道规则执行是如何工作的。我们现在就是这样做的。我的问题是这种方法很难获得足够和适当的测试数据。因为我们不限制可运行的规则,所以任何其他规则都可以运行并更改最终结果。因此,很难预测资产的最终结果。这就是为什么我认为最好将规则进行测试的原因。我想我是想说“任何其他规则都可以运行并改变