5.2 ConstraintStream约束测试

这是我参与更文挑战的第20天,活动详情查看: 更文挑战java

前情提示

上一篇文章咱们学习了,Drools规则约束的测试方法。今天咱们来学习ConstraintStream方式的规则测试。话很少说,咱们来开始学习。markdown

内容

ConstraintStream包括Constraint Verifier单元测试线束。要使用它,首先添加一个optaplanner-test.jar框架

测试单个约束条件

咱们以N皇后为例子:dom

protected Constraint horizontalConflict(ConstraintFactory factory) {
        return factory
                .fromUniquePair(Queen.class, equal(Queen::getRowIndex))
                .penalize("Horizontal conflict", SimpleScore.ONE);
    }
复制代码

下面的例子使用ConstraintVerifier API来为前面的约束流建立一个简单的单元测试:ide

private ConstraintVerifier<NQueensConstraintProvider, NQueens> constraintVerifier
            = ConstraintVerifier.build(new NQueensConstraintProvider(), NQueens.class, Queen.class);

    @Test
    public void horizontalConflictWithTwoQueens() {
        Row row1 = new Row(0);
        Column column1 = new Column(0);
        Column column2 = new Column(1);
        Queen queen1 = new Queen(0, row1, column1);
        Queen queen2 = new Queen(1, row1, column2);
        constraintVerifier.verifyThat(NQueensConstraintProvider::horizontalConflict)
                .given(queen1, queen2)
                .penalizesBy(1);
    }
复制代码

这个测试确保当同一行有两个皇后时,horizontalConflict约束会分配一个1的惩罚。下面一行建立了一个共享的ConstraintVerifier实例,并用NQueensConstraintProvider初始化了该实例。函数

private ConstraintVerifier<NQueensConstraintProvider, NQueens> constraintVerifier
            = ConstraintVerifier.build(new NQueensConstraintProvider(), NQueens.class, Queen.class);
复制代码

@Test注解表示该方法是你选择的测试框架中的单元测试。Constraint Verifier与许多测试框架一块儿工做,包括JUnit和AssertJ。post

测试的第一部分是准备测试数据。在这种状况下,测试数据包括皇后计划实体的两个实例和它们的依赖关系(row、column)。单元测试

Row row1 = new Row(0);
        Column column1 = new Column(0);
        Column column2 = new Column(1);
        Queen queen1 = new Queen(0, row1, column1);
        Queen queen2 = new Queen(1, row1, column2);
复制代码

再往下看,下面的代码是测试约束条件的:学习

constraintVerifier.verifyThat(NQueensConstraintProvider::horizontalConflict)
            .given(queen1, queen2)
            .penalizesBy(1);
复制代码

verifyThat()调用是用来指定被测试的NQueensConstraintProvider类的一个方法。这个方法必须对测试类可见,Java编译器将强制执行。测试

given()调用是用来列举约束流将操做的全部事实。在本例中,given()调用采用先前建立的queen1queen2实例。另外,你也能够在这里使用givenSolution()方法,提供一个规划的解决方案。

最后,policizesBy()调用完成测试,确保水平冲突约束,给定一个Queen,结果是1的惩罚。这个数字是约束流中定义的匹配权重乘以匹配数的score

另外,你可使用rewardsWith()调用来检查奖励而不是惩罚。这里使用的方法取决于相关的约束流是以惩罚仍是以奖励构建块来终止的。

测试全部约束条件

除了测试单个约束以外,还能够测试整个ConstraintProvider实例。考虑一下下面的测试:

@Test
    public void givenFactsMultipleConstraints() {
        Queen queen1 = new Queen(0, row1, column1);
        Queen queen2 = new Queen(1, row2, column2);
        Queen queen3 = new Queen(2, row3, column3);
        constraintVerifier.verifyThat()
                .given(queen1, queen2, queen3)
                .scores(SimpleScore.of(-3));
    }
复制代码

与前面的例子只有两个明显的不一样。

首先,这里的verifyThat()调用不须要参数,表示整个ConstraintProvider实例正在被测试。

第二,这里使用了 scores() 方法,而不是 penalizesBy() rewardsWith() 调用。该方法在给定的事实上运行ConstraintProvider,并返回由给定事实产生的全部约束匹配的 **"分数 "**之和。

使用这个方法,能够确保约束条件提供者不会遗漏任何约束条件,而且随着你的代码库的发展,评分函数保持一致。

结果查看

不匹配结果:

java.lang.AssertionError: Broken expectation.
        Constraint: org.optaplanner.examples.nqueens.domain/Horizontal conflict
  Expected penalty: 1 (class java.lang.Integer) Actual penalty: 0 (class java.lang.Integer) Explanation of score (0): Constraint match totals: 0: constraint (Horizontal conflict) has 0 matches: Indictments: at org.optaplanner.test.impl.score.stream.DefaultSingleConstraintAssertion.assertImpact(DefaultSingleConstraintAssertion.java:112) at org.optaplanner.test.impl.score.stream.DefaultSingleConstraintAssertion.penalizesBy(DefaultSingleConstraintAssertion.java:60) at org.optaplanner.t 复制代码

正常的结果跟上一章的同样。

总结

经过这个例子,咱们学习了OptaPlanner如何测试ConstraintStream的约束规则,这对咱们来讲很是的重要,由于你不会指望着在生产环境测试,或者本地须要一套完整的求解数据才能开始测试。

结束语

下一篇章咱们来学习如何查看约束评分的例子。

创做不易,禁止未受权的转载。若是个人文章对您有帮助,就请点赞/收藏/关注鼓励支持一下吧💕💕💕💕💕💕

相关文章
相关标签/搜索