Unit Testing Stages

Let us add some basic system tests to the ExampleConsumer class describe earlier, so that we can make sure our stage is behaving as expected while we work on it.

Kotekan uses pytest for its system tests. Through the pytest framework you can set up a corresponding producer stage/input buffer, automate the creation of a pipeline configuration, run your consumer stage, and then make assertions on its behaviour.

The steps for building a test are:

  1. Set the parameters for the configuration of your stage.

  2. Write a pytest fixture that runs kotekan:

    • Create a temporary directory for the data produced by your test.

    • If the stage you are testing has consumer components, set up a producer stage which generates the input buffer.

    • If the stage you are testing has producer components, set up the data dumper, which will allow you to validate your stage’s behaviour.

    • Configure KotekanStageTester with your stage, and tell it where it will can find the input buffer, and/or where it can output its buffer.

    • yield the final buffer for asserting.

  3. Create the actual test. Pass it your stage’s pytest fixture. Assert the expected output frames.

 1import pytest
 2from kotekan import runner
 3
 4# this is the equivalent of the pipeline config file for kotekan to run your test
 5params = {
 6    "num_elements": 7,
 7    "num_ev": 0,
 8    "total_frames": 128,
 9    "cadence": 10.0,
10    "mode": "default",
11    "variable_my_stage_needs": -1,
12}
13
14# this runs kotekan and yields the data you want to inspect
15@pytest.fixture(scope="module")
16def data(tmpdir_factory):
17
18    # keep all the data this test produces in a tmp directory
19    tmpdir = tmpdir_factory.mktemp("name_of_the_test_case")
20
21    # you can use FakeVisBuffer as a mock producer stage
22    # to produce a Kotekan buffer with fake data
23    fakevis_buffer = runner.FakeVisBuffer(
24        num_frames=params["total_frames"], mode=params["mode"]
25    )
26
27    # DumpVisBuffer can be used to dump data
28    # afterwards for asserting expectations
29    dump_buffer = runner.DumpVisBuffer(str(tmpdir))
30
31    # KotekanStageTester is used to run your
32    # kotekan stage with your config
33    # Replace stage_type with the name of your stage
34    test = runner.KotekanStageTester(
35        stage_type="stageUnderTest",
36        stage_config={},
37        buffers_in=fakevis_buffer,
38        buffers_out=dump_buffer,
39        global_config=params,
40    )
41
42    test.run()
43
44    # here the data that the stage under test
45    # put out is passed on to test the stage
46    yield dump_buffer.load()
47
48
49# this is the actual test (give a name to it)
50def test_<name>(data):
51
52    for frame in data:
53        assert frame.vis == {1, 0}

And there you go!

To run the test, while in the kotekan repo, type:

kotekan$ export PYTHONPATH=python
kotekan$ pytest -sv location_of_test/example_test.py

If it cannot find your new stage, ensure that pytest is running the correct local kotekan build, which includes your new code.

And congratulations! You now have the foundation in place to further develop your stage.