Test driven development Optaplanner

Viewed 88

In the library Optaplanner, in the file "CloudBalancingScoreConstraintTest.java" there is the following line of code: scoreVerifier.assertHardWeight("requiredCpuPowerTotal", -570, solution). How was calculated the expected weight "-570"? this was known before creating the classes (CloudBalance.java, CloudComputer.java) in a test driven development approach or after the creation of the classes?

1 Answers

TLDR: ignore CloudBalancingScoreConstraintTest and look at CloudBalancingConstraintProviderTest instead.

Long explanation:

CloudBalancing currently still defaults to scoreDrl. It also has an alternative implementation with ConstrainStreams: CloudBalancingConstraintProvider. ConstraintStreams are in many ways better than scoreDRL, as of OptaPlanner 8.4.0 equally fast and have 99% feature parity with DRL. Once that's 100%, all examples will use ConstraintStreams by default.

So why is it -570? Because ScoreVerifier checks all constraints. So add one constraint and you have to adjust all your tests. Very painful. Not TDD.

What's the fix? Use ConstraintVerifier. ConstraintVerifier is ScoreVerifier++. ConstraintVerifier tests the matchWeight of one constraint.

`constraintWeight * matchWeight * (+1 for reward | -1 for penalize) = score impact`

It even ignores the constraintWeight of the constraint, which is a blessing once the business stakeholders start tweaking the constraint weights. Additionally, it's far less verbose to use (no solution instance needed). What's the catch? It only works for ConstraintStreams.

An example:

@Test
public void requiredCpuPowerTotal() {
    CloudComputer computer1 = new CloudComputer(1, 1, 1, 1, 2);
    CloudComputer computer2 = new CloudComputer(2, 2, 2, 2, 4);
    CloudProcess unassignedProcess = new CloudProcess(0, 1, 1, 1);
    // Total = 2, available = 1.
    CloudProcess process1 = new CloudProcess(1, 1, 1, 1);
    process1.setComputer(computer1);
    CloudProcess process2 = new CloudProcess(2, 1, 1, 1);
    process2.setComputer(computer1);
    // Total = 1, available = 2.
    CloudProcess process3 = new CloudProcess(3, 1, 1, 1);
    process3.setComputer(computer2);

    constraintVerifier.verifyThat(CloudBalancingConstraintProvider::requiredCpuPowerTotal)
            .given(unassignedProcess, process1, process2, process3)
            .penalizesBy(1); // Only the first computer.
}

To learn more, watch Lukas's OptaPlanner Test driven development video.

Related