Toggle navigation OptaPlanner logo
  • Home
  • Download
  • Learn
    • Documentation
    • Videos
    • Slides
    • Training
    • Use cases
    • Compatibility
    • Testimonials and case studies
  • Get help
  • Source
  • Team
  • Services
  • Star
  • @OptaPlanner
  • Fb
Fork me on GitHub
  • How to defeat gerrymandering and create fair el...
  • Red Hat Mobile Portfolio Truck dodges storms wh...

Unit testing constraints with business input from Excel or LibreOffice

Tue 21 August 2018

Avatar Musa Talluzi

Musa Talluzi


Twitter GitHub

Ex OptaPlanner developer

The business experts explain the business constraints to us, the developers. But how can we be sure that we understood them correctly? Or worse, how can we test that they agree among themselves once the constraints are formalized?

Well, there’s one great way to do that: JUnit tests populated by *.xlsx data. We allow them to recreate a small subset of the solution in Excel/LibreOffice and let them decide how many constraints match. Then our JUnit tests check if our constraint implementations adhere to those requirements.

Traditional unit tests

In Conference Scheduling example, to test room conflict constraint (hard penalty per pair of talks in the same room in overlapping timeslots) write:

@Test
public void roomConflict() {
    TalkType talkType = new TalkType(0L, "type1");
    Talk talk1 = new Talk(1L)
            .withTalkType(talkType)
            .withSpeakerList(Collections.emptyList())
            .withRequiredRoomTagSet(Collections.emptySet())
            ...
    Talk talk2 = new Talk(2L)
            ...
    LocalDateTime start1 = LocalDateTime.of(2018, 1, 1, 9, 0);
    LocalDateTime end1 = LocalDateTime.of(2018, 1, 1, 10, 0);
    LocalDateTime start2 = LocalDateTime.of(2018, 1, 1, 9, 30);
    LocalDateTime end2 = LocalDateTime.of(2018, 1, 1, 10, 30);
    LocalDateTime start3 = LocalDateTime.of(2018, 1, 1, 10, 0);
    LocalDateTime end3 = LocalDateTime.of(2018, 1, 1, 11, 0);
    Timeslot slot1 = new Timeslot(1L)
            .withTalkTypeSet(Collections.singleton(talkType))
            .withStartDateTime(start1)
            .withEndDateTime(end1);
    Timeslot slot2 = new Timeslot(2L)
            ...
    Timeslot slot3 = new Timeslot(3L)
            ...
    Room room1 = new Room(1L)
            .withTalkTypeSet(Collections.singleton(talkType))
            .withUnavailableTimeslotSet(Collections.emptySet());
    ConferenceSolution solution = new ConferenceSolution(1L)
            .withTalkTypeList(Collections.singletonList(talkType))
            ...
    scoreVerifier.assertHardWeight(ROOM_CONFLICT, 0, solution);
    // Talks in same room without overlapping time slots
    talk1.withRoom(room1).withTimeslot(slot1);
    talk2.withRoom(room1).withTimeslot(slot3);
    scoreVerifier.assertHardWeight(ROOM_CONFLICT, 0, solution);
    // Talks in same room with overlapping time slots
    talk2.withTimeslot(slot2);
    scoreVerifier.assertHardWeight(ROOM_CONFLICT, -10, solution);
}

In order to test room conflict, you need to initialize two talks, three timeslots and one room. However, the previous snippet of code is too long for such a simple unit test, most of the boilerplate code is for initializing required fields for the conference solution that you do not need for the unit test, and you must do that for every single unit test. For more complex constraints, it gets too cumbersome to write traditional unit tests and reason about them.

Unit tests in xlsx files

In order to avoid initializing unwanted fields, you can take advantage of ConferenceSchedulingXlsxFileIO to initialize them for you, and only write what you use in that test or in other tests in the same spreadsheet.

To test room conflict using an xlsx file, create three timeslots, two talks and one room:

xlsxUnitTestingTimeslots
xlsxUnitTestingTalks
xlsxUnitTestingRooms

After you initialize the required fields, create a separate sheet for every score verification of each constraint. For example, these 2 sheets check the room conflict constraint:

xlsxUnitTestingRoomConflict1
xlsxUnitTestingRoomConflict2

In every test sheet (blue color), specify the constraint package, constraint name, description of current test scenario and expected score. Then assign the talks to rooms and timeslots to visualize them easily. Note that you do not need to list all the timeslots and rooms declared in Timeslots and Rooms sheets.

Conclusion

Instead of writing unit tests in code, business experts can specify how they want the constraints to be matched in an Excel/LibreOffice file. Developers then implement the constraints to pass these tests. This provides a more efficient way of communication between developers and domain experts.

To test score rules in an xlsx file:

  1. List all the required fields for your tests in the setup sheets.

  2. For every score verification, create a separate blue test sheet with the constraint package, constraint name and expected score.

  3. List only the fields that you want to use for the corresponding rule.

  4. Set testFileName in ConferenceSchedulingConstraintsXlsxTest and run the test file.

Related material

Scheduling Voxxed Days Zurich 2018 with OptaPlanner


Comments Permalink
 tagged as use case conference scheduling

Comments

Visit our forum to comment
  • How to defeat gerrymandering and create fair el...
  • Red Hat Mobile Portfolio Truck dodges storms wh...
Atom News feed
Don't want to miss a single blog post?
Follow us on
  • T
  • Fb
Blog archive
Latest release
  • 8.1.0.Final released
    Fri 15 January 2021
Upcoming events
  • KIE Live
    Worldwide - Tue 19 January 2021
    • OptaPlanner Shadow Variables for the Vehicle Routing Problem and Task Assignment by Geoffrey De Smet, Karina Varela, Alex Porcelli
  • Javaland
    Worldwide - Tue 16 March 2021
    • AI on Quarkus: I love it when an OptaPlan comes together by Geoffrey De Smet
Add event / Archive
Latest blog posts
  • Solve the facility location problem
    Fri 9 October 2020
     Jiří Locker
  • OptaPlanner Week 2020 recordings
    Mon 7 September 2020
     Geoffrey De Smet
  • Let’s OptaPlan your jBPM tasks (part 1) - Integrating the two worlds
    Fri 3 July 2020
     Walter Medvedeo
  • AI versus Covid-19: How Java helps nurses and doctors in this fight
    Fri 8 May 2020
     Christopher Chianelli
  • Workflow processes with AI scheduling
    Tue 5 May 2020
     Christopher Chianelli
  • Constraint Streams - Modern Java constraints without the Drools Rule Language
    Tue 7 April 2020
     Geoffrey De Smet
  • How to plan (and optimize) a Secret Santa
    Wed 18 December 2019
     Christopher Chianelli
Blog archive
Latest videos
  • YT Shadow variables
    Tue 19 January 2021
     Geoffrey De Smet
  • YT Domain modeling and design patterns
    Tue 17 November 2020
     Geoffrey De Smet
  • YT Quarkus insights: AI constraint solving
    Tue 20 October 2020
     Geoffrey De Smet
  • YT AI in kotlin
    Wed 23 September 2020
     Geoffrey De Smet
  • YT Planning agility: continuous planning, real-time planning and more
    Thu 3 September 2020
     Geoffrey De Smet
  • YT Quarkus and OptaPlanner: create a school timetable application
    Thu 3 September 2020
     Radovan Synek
  • YT Business use cases and the impact of OptaPlanner
    Thu 3 September 2020
     Satish Kale
Video archive

KIE projects

  • Drools rule engine
  • OptaPlanner constraint solver
  • jBPM workflow engine

Community

  • Blog
  • Get Help
  • Team
  • Governance
  • Academic research

Code

  • Build from source
  • Submit a bug
  • License (Apache-2.0)
  • Release notes
  • Upgrade recipes
Sponsored by
Red Hat
More coder content at
Red Hat Developers
© Copyright 2006-2021, Red Hat, Inc. or third-party contributors - Privacy statement - Terms of use - Website info