Sync actor tests

Source:

import logging
import testing

actor MathTester():
    def add(a, b):
        return a + b

actor SyncTester(log_handler):
    def test():
        m = MathTester()
        testing.assertEqual(m.add(1, 2), 3, "1 + 2 = 3")

def _test_syncact(log_handler: logging.Handler) -> None:
    """A test using actors and synchronous control flow"""
    # We make use of an actor as the central point for running our test logic.
    # This _test_syncact function is just a wrapper picked up by the acton
    # test framework runner
    s = SyncTester(log_handler)
    return s.test()

Run:

acton test

Output:

Building project in /home/user/foo
  Compiling example.act for release
   Finished compilation in   0.027 s
  Final compilation step
   Finished final compilation step in   0.526 s

Tests - module example:
  syncact:               OK: 1175 runs in 50.005ms

All 1 tests passed (0.655s)

Since the Acton RTS is multi-threaded and actors are scheduled concurrently on worker threads, using actors imply a degree of non-determinism and so unlike unit tests, which are deterministic, actors tests are fundamentally non-deterministic. You can still write deterministic tests as long as you pay attention to how you construct your test results.

For example, actor A might be scheduled before or after actor B so if the test relies on ordering of the output, it could fail or succeed intermittently. Interacting with the surrounding environment by reading files or communicating over the network introduces even more sources of non-determinism. Avoid it if you can.