Unit Testing Guidelines

Test modules, directories

Spine project uses the pytest framework for testing. The tests are organized into Python modules starting with the prefix test_ under <project root>/tests/. The structure of tests/ mirrors that of the package being tested.

The naming convention for modules is test_<module_name>.py. Within those files, pytest will run test prefixed functions or methods outside of classes, and test prefixed functions or methods inside Test prefixed test classes (without an __init__ method). Methods decorated with @staticmethod and @classmethods are also considered.

Please consult the conventions for python test discovery https://docs.pytest.org/en/stable/explanation/goodpractices.html#conventions-for-python-test-discovery for further details.

Running the tests

Tests are run as a GitHub action whenever a branch is pushed to GitHub. This process is configured by <project root>/.github/workflows/unittest_runner.yml

To execute the tests manually, run pytest tests/ in project’s root.

Helpers

mock_helpers module in Toolbox’s test package contains some helpful functions. Especially the methods to create mock ToolboxUI and SpineToolboxProject objects come very handy.

When instantiation of QWidget (this includes all GUI testing) is needed, Qt’s main loop must be running during testing. This can be achieved by e.g. the setUpClass method below:

@classmethod
def setUpClass(cls):
    if not QApplication.instance():
        QApplication()

Sometimes an in-memory database can be handy because it does not require a temporary files or directories and it may be faster than an .sqlite file. To create an in-memory database, use sqlite:// as the URL:

db_map = DiffDatabaseMapping("sqlite://", create=True)

Unfortunately, it is not possible to refer to the created database with the same URL prohibiting multiple database maps the access to the same in-memory database.