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的約束規則,這對咱們來講很是的重要,由於你不會指望着在生產環境測試,或者本地須要一套完整的求解數據才能開始測試。

結束語

下一篇章咱們來學習如何查看約束評分的例子。

創做不易,禁止未受權的轉載。若是個人文章對您有幫助,就請點贊/收藏/關注鼓勵支持一下吧💕💕💕💕💕💕

相關文章
相關標籤/搜索