Design: TestBartender

Archtictural decision for lazy test evaluation

pytest does testcollection at the beginning.

We decided to do lazy testcollection.

  • The test duration might differ a lot - between a few seconds and 10 minutes.

  • The goal is, to have the overall time of the tests as small as possible.

Influencing the test process / freedom in the choice of tentacles

  • There might be redundant tentacles to speed up critical path.

  • For tests requireing two tentacles, for example WLAN STA vs WLAN AP, we may pick tentacles which are ready just now.

Classes involved in testcollection

The TestBartender and the testcollection is quite complex.

The sources are in this package: src/testbed/testcollection The sources of the test specs are in this package: src/testbed/testrunspecs

There is some unit testing here: <testbed_micropython>/tests/test_collection.py

TestRunSpec

A TestRunSpec is used to specify a test in the micropython directory which may be called in a test run.

The method generate() will generate the next TestRun - for example a call to ‘run-perfbench.py’.

The method generate() might be seen as a bartender which hands out a burger or asks for money depending on the actual needs.

classDiagram class TestRunSpec{ generate(available_tentacles, available_firmwares) -> TestRun } TestRunSpec *-- TestRunSpecs
TESTRUNSPEC_PERFTEST = TestRunSpec("run-perfbench.py", TestRunPerfTest)
TESTRUNSPEC_RUNTESTS_MULTINET = TestRunSpec("run-multitests.py", TestRunMultitestMultinet)
TESTRUNSPEC_RUNTESTS_STANDARD = TestRunSpec("run-tests.py", TestRunRunTests)

specs = [
    multinet.TESTRUNSPEC_RUNTESTS_MULTBLUETOOTH,
    multinet.TESTRUNSPEC_RUNTESTS_MULTINET,
    perftest.TESTRUNSPEC_PERFTEST,
    runtests_net_inet.TESTRUNSPEC_RUNTESTS_NET_HOSTED,
    runtests_net_inet.TESTRUNSPEC_RUNTESTS_NET_INET,
    runtests.TESTRUNSPEC_RUNTESTS_STANDARD,
    runtests.TESTRUNSPEC_RUNTESTS_EXTMOD_HARDWARE,
]

TestRun

A TestRun will

  • create a directory <repo>/results/RUN-TESTS_EXTMOD_HARDWARE[5f2c-RPI_PICO_W]

  • start a process which

    • Lock the associated tentacles

    • initalizes the associated tentacles

    • flashes the boards if needed

    • starts the test, for example ‘run-perfbench.py’

    • Release the associated tentacles

The TestRun knows the associated TestRunSpec which will provide information needed to run the test.

classDiagram class TestRun{ testid 'RUN-TESTS_EXTMOD_HARDWARE[5f2c-RPI_PICO_W]' assigned tentacles assigned firmwares test() } class TestRunPerfTest{ test() } class TestRunRunTests{ test() } class TestRunMultitestBase{ test() } TestRun <|-- TestRunPerfTest TestRun <|-- TestRunRunTests TestRun <|-- TestRunMultitestBase

TestRunSpecs generating TestRun

classDiagram class TestRunSpec{ generate(available_tentacles, available_firmwares) -> TestRun } class TestRunSpecs{ generate(available_tentacles, available_firmwares) -> TestRun } class TestRun{ +testid Example: RUN-TESTS_EXTMOD_HARDWARE[5f2c-RPI_PICO_W] +assigned tentacles +assigned firmwares -test() } class TestRunPerfTest{ -test() } class TestRunRunTests{ -test() } class TestRunMultitestBase{ -test() } TestRun <|-- TestRunPerfTest TestRun <|-- TestRunRunTests TestRun <|-- TestRunMultitestBase TestRun --> TestRunSpec TestRunSpec *-- TestRunSpecs

The TestBartender calls TestRunSpecs.generate() to get a new TestRun.

  • Generate will loop over all TestRunSpecs.generate().

  • This will be a possible long list of possible ‘TestRun’s.

  • Not the ‘TestRun’s are ordered by priority.

  • The one with the highest priority is selected.

  • This ‘TestRun’ now will be started - flow see above.

sequenceDiagram participant m as main() participant f as FirmwareBartender participant b as Build Process participant s as Filesystem m->>f: connected tentacles f-->>+b: firmware-variant list b->>+s: RPI_PICO2 s-->>-b: done b-->>f: EventFirmwareSpec(RPI_PICO2) b->>+s: TEENSY40 s-->>-b: done b-->>f: EventFirmwareSpec(TEENSY40) b->>+s: RPI_PICO2-RISCV s-->>-b: done b-->>f: EventFirmwareSpec(RPI_PICO2-RISCV) b-->>-f: EventExitFirmware()