Standard Discovery, Staging and Invocation of Integration Tests

Summary

Lets define a clear delineation of between a test suite (including framework) and the CI system that is running the test suite. This is the standard interface.

What follows is a standard way to discover, package and invoke integration tests for a package stored in a Fedora dist-git repo.

Many Fedora packages have unit tests. These tests are typically run during a %check RPM build step and run in a build root. On the other hand, integration testing should happen against a composed system. Upstream projects have integration tests, both Fedora QA and the Atomic Host team would like to create more integration tests, Red Hat would like to bring integration tests upstream.

The format of the textual logs and test artifacts that come out of a test suite is not prescribed by this document. Nor is it envisioned to be standardized across all possible test suites.

Requirements

The test suite and test framework SHOULD NOT leak its implementation details into the testing system, other than via the standard interface.

The test suite and test framework SHOULD NOT rely on behavior of the testing system other than the standard interface.

The standard interface MUST enable a dist-git packager to run a test suite locally.

Test suites or test frameworks MAY call out to the network for certain tasks.

It MUST be possible to stage an upstream test suite using the standard interface.

Both in-situ tests, and more rigorous outside-in tests MUST be possible with the standard interface.

For in-situ tests the test suite is in the same file system tree and process space as the test subject.

For outside-in tests the test suite is outside of the file system tree and process space of the test subject.

The test suite and test framework SHOULD be able to provision containers and virtual machines necessary for its testing without requesting them from the testing system.

The standard interface SHOULD describe how to uniquely identify a test suite,

Benefit to Fedora

Developers benefit by having a consistent target for how to describe tests, while also being able to execute them locally while debugging issues or iterating on tests.

By staging and invoking tests consistently in Fedora we create an eco-system for the tests that allows varied test frameworks as well as CI system infrastructure to interoperate. The integration tests outlast the implementation details of either the frameworks they're written in or the CI systems running them.

Detailed Description

This standard interface describes how to discover, stage and invoke tests. It is important to cleanly separate implementation details of the testing system from the test suite and its framework. It is also important to allow Fedora packagers to locally and manually invoke a test suite.

Staging

Tests files will be added into the tests/ folder of a dist-git repository branch. The structure of the files and folders is left to the liberty of the packagers but there are one or more playbooks in the tests/ folder that can be invoked to run the test suites.

The testing system SHOULD stage the tests on target (eg: Fedora) operating system appropriate for the branch name of the dist-git repository containing the tests.

The testing system SHOULD stage a clean a system for each set of tests it runs.

The testing system MUST stage the following packages:

ansible python2-dnf libselinux-python standard-test-roles

The testing system MUST clone the dist-git repository for the test, and checks out the appropriate branch.

The contents of /etc/yum.repos.d on the staged system SHOULD be replaced with repository information that reflects the known good Fedora packages corresponding to the branch of the dist-git repository.

The testing system MAY use multiple repositories, including updates or updates-testing to ensure this.

Invocation

The testing system MUST run the playbook tests/tests.yml in the dist-git repo. The testing system should look for the presence of a file or directory tests/inventory and take it into consideration below.

The test subjects are passed to the playbook and inventory as operating system environment and ansible environment. Often only one test subject is passed in. However multiple subjects may be concatenated together in a shell escaped string. The playbook and inventory script split the string. The extensions as follows are used to determine the type of subject:

Various tests in a playbook constitute a test suite. Some parts of this test suite will run in certain contexts, against certain deliverable artifacts. Certain tests will run against Atomic Host deliverables, while others will not. Certain tests will run against Docker deliverables while others will not. This is related to, but does not exactly overlap with the test subject identifiers above. Ansible tags are used to denote these contexts.

Tag

Test context

atomic

Atomic Host

container

A Docker or OCI container

classic

Tested against a classic installed YUM/DNF installed system.

...

Other test subject identifiers may be added later.

To invoke the playbook, the testing system:

MUST execute the playbook with the following operating system environment variables:

TEST_SUBJECTS: The test subjects string as described above

TEST_ARTIFACTS: The full path of an empty folder for test artifacts

MUST execute the playbook with the following variables.

subjects: The test subjects string as described above

artifacts: The full path of an empty folder for test artifacts

SHOULD execute the playbook with a all Ansible tags best represents the intended test context.

The choice of test context tags is related to the test subject being tested

MUST execute Ansible with inventory set to the full path of the file or directory tests/inventory if it exists.

If the tests/inventory file doesn't exist, then the following inventory SHOULD be used as a default:/usr/share/ansible/inventory

MUST execute the playbook as root.

MUST examine the exit code of the playbook. A zero exit code is successful test result, non-zero is failure.

MUST treat the file test.log in the artifacts folder as the main readable output of the test.

SHOULD place the textual stdout/stderr of the ansible-playbook command in the ansible.log file in the artifacts folder.

SHOULD treat the contents of the artifacts folder as the test artifacts.

The playbook and its test suite or test framework:

SHOULD drop privileges appropriately if the test suite should be run as non-root.

MUST install any requirements of its test suite or test framework and MUST fail if this is not possible.

MUST provision the test subject listed in the subjects variable appropriately for its playbook name (described above) and MUST fail if this is not possible.

MUST place the main readable output of the test suite into a test.log file in the artifacts variable folder. This MUST happen even if some of the test suites fail.

SHOULD place additional test artifacts in the folder defined in the artifacts variable.

If an inventory file or script exists, it:

MUST describe where to invoke the playbook and how to connect to that target.

SHOULD launch or install any supported $TEST_SUBJECTS so that the playbook can be invoked against them.\

SHOULD put relevant logs in the $TEST_ARTIFACTS directory.

Discovery

Test discovery is done via dist-git. Both packages and modules may have tests in this format.

Scope

Since the tests are added in a sub-folder of the dist-git repo, there are no changes required to the Fedora infrastructure and will have no impact on the packagers' workflow and tooling.

Only the testing system will need to be taught to install the requirements and run the playbooks.

User Experience

A standard way to package, store and run tests benefits Fedora stability, and makes Fedora better for users.

This structure makes it easy to run locally thus potentially reproducing an error triggered on the test system.

Ansible is being more and more popular, thus making it easier for people to contribute new tests

Used by a lot of sys-admin, ansible could help sys-admin to bring test-cases to the packagers and developers about situation where something failed for them.

Upgrade/compatibility impact

There are no real upgrade or compatibility impact. The tests will be branched per release as spec files are branched dist-git is now.