How to test event occurrences

When to use it

When you want to verify the SUT behaves correctly during asynchronous behaviour involving one or more transition in states.

Often a programme may return from a call in which the exact time of events occurring at that moment goes unrecorded. This is the case when the call involves asynchronous communications between different processes and the caller depends on events signalling a change of state.

In addition, when a service is being tested to place another device in a particular state, the service may return whilst the transition is still occurring on the other device. This mean that the service reported a condition that may or may not turn out to be true. This problem can also cause synchronization errors in which a next instruction proceeds momentarily too soon and therefore becomes a race condition that is difficult to debug.

How it works

The object to use for testing correct occurrence of events is Occurrences.

There are two distinct “life stages” in this object:
  1. wire tapping: when handlers push the occurrence of events to it whilst waiting for a specific event to occur.

#. verifying outcomes: when the object traverse through the collected list of occurrences and verify the correct relative order of events on other devices against the device.

Given a device (device1) that is expected to transition in state from A to B only after device2 and device3 has transitioned in state from A to B, the Occurrences object can verify that the outcome for device1 on transition B resulted in ahead devices == [device1, device3] and behind devices == []. In other words all devices under investigation transitioned after the main or “subject” device. It does so by simply comparing the times of transitions for each device against the subject device, placing devices behind the subject device in one list and those ahead into another.

How to use it

To configure the correct wire tapping to take place you can configure it using the builders module as follows:

# first get a generic builder for setting up a messageboard
builder = builders.get_message_board_builder()
# then we configure it for transition checking
occurrences = builder.check_that("device1")
.transits_according_to(["A","B"])
.on_attr("state")
.when_transit_occur_on(["device1", "device2"])

This ensures an occurrences object have been initialised and will be used by event handlers to subscriptions on the devices_to_follow (["device1", "device2"]) as well as the main device (device1) to tap in to events as they occur.

Then we exercise the test in a waiting context:

with wait.wait_for(builder, timeout = 25):
    exercise_test()

This will ensure the proper waiting and recording for events occur before exiting the context.

This is equivalent to using the more explicit form below:

board = builder.setup_board()
exercise_test()
wait.wait(board,25)

Finally after the wait has completed, we can run our assertions:

occurrences.assert_that("device1").is_behind_all_on_transit("B")