How to write unit tests for Constraints where it is applied penalizeConfigurable() method in Timefold?

60 views Asked by At

Starting from the github project provided by Timefold (https://github.com/TimefoldAI/timefold-quickstarts/tree/stable/technology/java-spring-boot) and extend it by using ConstraintConfiguration and ConstraintWeight to apply some dynamic constraints (How to choose dynamically which constraints should be applied on the optimization problem based on the frontend input in Timefold Spring Boot?) I want to write some unit tests. How can I simulate the ConstraintConfiguration for the unit tests?

For the following test:

@Test
    void roomConflict() {
        Lesson firstLesson = new Lesson(1, "Subject1", new Teacher(1L, "Teacher1", null), new StudentGroup(1L,"Group1", 30), TIMESLOT1, ROOM1);
        Lesson conflictingLesson = new Lesson(2, "Subject2", new Teacher(2L, "Teacher2", null), new StudentGroup(2L,"Group2", 30), TIMESLOT1, ROOM1);
        Lesson nonConflictingLesson = new Lesson(3, "Subject3", new Teacher(3L, "Teacher3", null), new StudentGroup(3L,"Group3", 30), TIMESLOT2, ROOM1);
        constraintVerifier.verifyThat(TimetableConstraintProvider::roomConflict)
                .given(firstLesson, conflictingLesson, nonConflictingLesson)
                .penalizesBy(0, "roomConflict");
    }

I wanted to check the output, but I receive a soft constraint justification instead of a hard one:

java.lang.AssertionError: roomConflict
        Constraint: com.timetablealgo.testingtimetablealgo.solver/roomConflict
  Expected penalty: 0 (class java.lang.Integer)
    Actual penalty: 1 (class java.lang.Integer)

  Explanation of score (0hard/1soft):
    Constraint matches:
        1soft: constraint (roomConflict) has 1 matches:
            1soft: justified with (RoomConflictJustification[room=Room(id=1, name=Room1, capacity=0, type=null, building=null, dotari=null), lesson1=Lesson(id=1, subject=Subject1, teacher=Teacher(id=1, name=Teacher1, preferredTimeslot=null), studentGroup=StudentGroup(id=1, year=null, name=Group1, group=null, semiGroup=null, numberOfStudents=30), type=null, year=null, timeslot=Timeslot(id=1, dayOfWeek=MONDAY, startTime=12:00, endTime=14:00), room=Room(id=1, name=Room1, capacity=0, type=null, building=null, dotari=null)), lesson2=Lesson(id=2, subject=Subject2, teacher=Teacher(id=2, name=Teacher2, preferredTimeslot=null), studentGroup=StudentGroup(id=2, year=null, name=Group2, group=null, semiGroup=null, numberOfStudents=30), type=null, year=null, timeslot=Timeslot(id=1, dayOfWeek=MONDAY, startTime=12:00, endTime=14:00), room=Room(id=1, name=Room1, capacity=0, type=null, building=null, dotari=null)), description=Room 'Room(id=1, name=Room1, capacity=0, type=null, building=null, dotari=null)' is used for lesson 'Subject1' for student group 'StudentGroup(id=1, year=null, name=Group1, group=null, semiGroup=null, numberOfStudents=30)' and lesson 'Subject2' for student group 'StudentGroup(id=2, year=null, name=Group2, group=null, semiGroup=null, numberOfStudents=30)' at 'MONDAY 12:00'])
    Indictments:
        1soft: indicted with (Lesson(id=1, subject=Subject1, teacher=Teacher(id=1, name=Teacher1, preferredTimeslot=null), studentGroup=StudentGroup(id=1, year=null, name=Group1, group=null, semiGroup=null, numberOfStudents=30), type=null, year=null, timeslot=Timeslot(id=1, dayOfWeek=MONDAY, startTime=12:00, endTime=14:00), room=Room(id=1, name=Room1, capacity=0, type=null, building=null, dotari=null))) has 1 matches:
            1soft: constraint (roomConflict)
        1soft: indicted with (Lesson(id=2, subject=Subject2, teacher=Teacher(id=2, name=Teacher2, preferredTimeslot=null), studentGroup=StudentGroup(id=2, year=null, name=Group2, group=null, semiGroup=null, numberOfStudents=30), type=null, year=null, timeslot=Timeslot(id=1, dayOfWeek=MONDAY, startTime=12:00, endTime=14:00), room=Room(id=1, name=Room1, capacity=0, type=null, building=null, dotari=null))) has 1 matches:
            1soft: constraint (roomConflict)


    at ai.timefold.solver.test.impl.score.stream.DefaultSingleConstraintAssertion.assertImpact(DefaultSingleConstraintAssertion.java:135)
    at ai.timefold.solver.test.impl.score.stream.DefaultSingleConstraintAssertion.penalizesBy(DefaultSingleConstraintAssertion.java:48)
    at com.timetablealgo.testingtimetablealgo.solver.TimetableConstraintProviderTest.roomConflict(TimetableConstraintProviderTest.java:31)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

How can I solve this issue?

PS: I added some fields to the classes but they don't change the basic functionality provided by the Github project in any way.

0

There are 0 answers