Examples

Simple Production Test

The standard production test consists of running the same test consistently on every start() of the TestSequence. In this sequence, the hardware is allocated on-the-fly within each test.

from time import sleep
from random import choice, random

from mats import Test, TestSequence, ArchiveManager

from my_lib import Device, FlowSensor


# A simple communications check with a device
class CommunicationTest(Test):
    def __init__(self):
        super().__init__(moniker='communications test',
                         pass_if=True)

    def setup(self, is_passing):
        # initialize hardware communications
        self._device = Device()

        # wait for communication to begin...
        while not self._device.is_communicating:
            sleep(0.1)

    # overriding the execute method
    def execute(self, is_passing):
        # should return a the results of the test
        return self._device.is_communicating

    def teardown(self, is_passing):
        # de-allocate the hardware
        self._device.close()


# The FlowTest implements the `setup' and `teardown` methods
# as well in order to demonstrate what that may look like
class FlowTest(Test):
    def __init__(self):
        super().__init__(moniker='pump flow test',
                         min_value=5.6, max_value=6.4)

    def setup(self, is_passing):
        # initialize hardware
        self._flow_sensor = FlowSensor()

        # wait for flow sensor to begin pulling values
        while self._flow_sensor.value is not None:
            sleep(0.1)

    def execute(self, is_passing):
        return self._flow_sensor.value

    def teardown(self, is_passing):
        # again, simulating another long-running process...
        self._flow_sensor.close()


if __name__ == '__main__':
    # create the sequence of test objects
    sequence = [CommunicationTest(), FlowTest()]

    # create the archive manager
    am = ArchiveManager()

    # create the test sequence using the sequence and archive manager
    # objects from above
    ts = TestSequence(sequence=sequence,
                      archive_manager=am,
                      auto_run=False)

    # start the test as many times as you wish!
    for _ in range(3):
        ts.start()
        sleep(2.0)

Simple Production Test (revisited)

The production test could also be done by allocating the hardware at the beginning of the sequence and realizing some time-saving on each test execution of the test.

from time import sleep
from random import choice, random

from mats import Test, TestSequence, ArchiveManager

from my_lib import Device, FlowSensor


# A simple communications check with a device
class CommunicationTest(Test):
    def __init__(self, device: Device):
        super().__init__(moniker='communications test',
                         pass_if=True)

        self._device = device

    # overriding the execute method
    def execute(self, is_passing):
        # should return a the results of the test
        return self._device.is_communicating


class FlowTest(Test):
    def __init__(self, flow_sensor: FlowSensor):
        super().__init__(moniker='pump flow test',
                         min_value=5.6, max_value=6.4)

        self._flow_sensor = flow_sensor

    def execute(self, is_passing):
        return self._flow_sensor.value


if __name__ == '__main__':
    # hardware allocated one time during program initialization, no
    # need to re-allocate during CommunicationTest and FlowTest
    device = Device()
    flow_sensor = FlowSensor()

    while not device.is_communicating and flow_sensor.value is not None:
        sleep(0.1)

    # create the sequence of test objects
    sequence = [
        CommunicationTest(device=device),
        FlowTest(flow_sensor=flow_sensor)
    ]

    # create the archive manager
    am = ArchiveManager()

    # create the test sequence using the sequence and archive manager
    # objects from above
    ts = TestSequence(sequence=sequence,
                      archive_manager=am,
                      auto_run=False)

    # start the test as many times as you wish!
    for _ in range(3):
        ts.start()
        sleep(2.0)

Production Test with Burn-In

This test is similar to the above production test. We use the setup method to provide a burn-in and provide a count.

from time import sleep
from random import choice, random

from mats import Test, TestSequence, ArchiveManager


# The CommunicationTest class shows the minimum test structure
# that might be reasonably be implemented.  Only the `execute()`
# method is implemented.
class CommunicationTest(Test):
    def __init__(self):
        super().__init__(moniker='communications test',
                         pass_if=True)

    # overriding the execute method
    def execute(self, is_passing):
        # a normal test would set `test_is_passing` based on
        # real conditions, we are implementing a random value
        # here simply for illustrative purposes
        is_communicating = choice([True] * 3 + [False])

        # should return a (key, value) which are the results of
        # the test
        return is_communicating


# The FlowTest implements the `setup' and `teardown` methods as
# well in order to demonstrate what that may look like
class BurnIn(Test):
    def __init__(self):
        super().__init__(moniker='burnin', min_value=5.6, max_value=6.4)

    def setup(self, is_passing):
        # just wait for a while, maybe display a bit of a countdown...
        seconds = 0
        while seconds < 10:
            seconds += 1
            self._logger.info(f'burning in count: {seconds}s')
            sleep(1.0)

    def execute(self, is_passing):
        # check to see if the device is still communicating
        is_communicating = choice([True] * 3 + [False])

        # should return a (key, value) tuple which are the results
        # of the test
        return is_communicating


if __name__ == '__main__':
    # create the sequence of test objects
    sequence = [CommunicationTest(), BurnIn()]

    # create the archive manager
    am = ArchiveManager()

    # create the test sequence using the sequence and archive
    # manager objects from above
    ts = TestSequence(sequence=sequence,
                      archive_manager=am,
                      auto_run=False)

    # start the test as many times as you wish!
    ts.start()

Life Test

A test that simulates on-off cycles and keeps chugging… forever… and ever…

from random import choice
from time import sleep

from mats import Test, TestSequence, ArchiveManager


class LifeTest(Test):
    def __init__(self):
        super().__init__(moniker='life test', pass_if=True)

    def setup(self, is_passing):
        # do_something_to_setup()
        sleep(0.1)

    def execute(self, is_passing):
        sleep(0.5)

        # simulate the collection of some data, then return it so
        # that the 'pass-if' condition may be applied
        result = choice([True] * 2 + [False])

        return result

    def teardown(self, is_passing):
        # do_something_to_teardown()
        sleep(0.1)


if __name__ == '__main__':
    from datetime import datetime

    logger = logging.getLogger(__name__)

    ts = TestSequence(
        sequence=[LifeTest()],
        archive_manager=ArchiveManager(path='.'),
        auto_run=3,   # run the test automatically after every iteration
    )

    # allow the test to run until it has completed
    start_dt = datetime.now()
    while ts.in_progress:
        sleep(0.1)

    logger.info(f'test time: {datetime.now() - start_dt}')