1

How do you configure unit testing framework to help develop code that is part of AnyLogic agents?

To have a suitable test driven development rhythm, I need to be able to run all tests in a few seconds. I thought of exporting the project as a standalone application (jar) each time, but that's pretty slow.

I thought of trying to write all the code outside AnyLogic in separate classes, but there are many references to built-in AnyLogic classes, as well as various agents. My code would need to refer to these somehow, and I'm not sure how to do that except by writing the code inside AnyLogic.

I wonder if there's a way of adding the test runner as a dependency, and executing that test runner from within AnyLogic.

Does anyone have a setup that works nicely?

Jaco-Ben Vosloo
  • 3,770
  • 2
  • 16
  • 33
John
  • 6,701
  • 3
  • 34
  • 56

1 Answers1

2

This definitely requires some advanced Java, but testing, especially unit testing is too often neglected in building good robust models. I hope this simple example is enough to get you (and lots of other modellers) going.

For Junit testing, we make use of two libraries that you can add as a dependency to your model.

enter image description here

Now there are two main types of logic that you will want to test in simulation models.

  1. Functions in Java classes
  2. Model execution

Type 1: Suppose I have this very simple Java class

public class MyClass {

    public MyClass() {
    }
    
    public boolean getResult() {
        return true;
    }
}

And I want to test the function getResult()

I can simply create a new class and create a function that I annotate with the @Test modifier and then also make use of the assertEquals() method, which is standard in junit testing

import org.junit.Test;
import static org.junit.Assert.assertEquals;
    
public class MyTestClass{

    @Test
    public void testMyClassFunction1() {
        boolean result = new MyClass().getResult();
        assertEquals("The value of the test class 1", result, true);
    }

Now comes the AnyLogic specific implementation (there are other ways to do this but this is the easiest/most useful, you will see in a minute)

You need to create a custom experiment

enter image description here

Now if you run this from the Run Model button you will get this output

enter image description here

SUCCESS

Run: 1
Failed: 0


You can obviously update and change the output as to your liking

Type 2: Suppose we have this very simple model

enter image description here

And the function getResult() simply returns an int of 2.

Now we need to create another custom experiment to run this model

enter image description here

And then we can write a test to run this Custom Experiment and check the result

Simply add the following to your MyTestClass

@Test
    public void testMyClassFunction2() {
        int result = new SingleRun(null).runExperiment();
        assertEquals("Value of a single run", result, 2);
    }

And now if you run the RunAllTests customer experiment it will give you this output

SUCCESS

Run: 2
Failed: 0

This is just the beginning, you can read up tons on using junit to your advantage

Jaco-Ben Vosloo
  • 3,770
  • 2
  • 16
  • 33
  • Thanks for the very detailed reply, Jaco-Ben. I think the second example is more of an end-to-end test than a unit test, but still important and useful, and JUnit is still a suitable framework. – John Sep 01 '21 at 23:18
  • 1
    Yes you are right, although not a true unit test, depending on your model this can be a very very small test. We have had highly configurable models where the tests using the model is just running 1 machine with 1 product or 1 maintenance event for 1 day and checking the output and statistics. IMO this can be seen as a unit test (albeit not a single function) it is still testing only a single piece of functionality of your model. I think the term unit test depends on the level of abstraction within your model. – Jaco-Ben Vosloo Sep 02 '21 at 06:33