Standard Test Roles
standard-test-roles provides shared Ansible roles and inventory scripts implementing the Standard Test Interface version
1.1.0. It has support for multiple testing frameworks (such as BeakerLib or Avocado) and in this way allows to easily enable existing tests in Fedora CI.
STR is available for Centos/RHEL from EPEL repository. As the first step install all necessary packages:
sudo dnf install fedpkg libselinux-python standard-test-roles
You can also install the latest version from the copr repo:
sudo dnf copr -y enable @osci/standard-test-roles sudo dnf update standard-test-roles
Output of the test (such as the stdout/stderr output, log files or screenshots) is by default saved in the
artifacts directory. Use
TEST_ARTIFACTS environment variable to choose a different location if desired:
A test subject is what we call the thing to be tested. To turn a test subject into a launched, installed system to be tested, we use Ansible dynamic inventory. Use the following command to enable it:
export ANSIBLE_INVENTORY=$(test -e inventory && echo inventory || echo /usr/share/ansible/inventory)
As you can see from the way how the inventory is set, tests may contain their own inventory, which defines their own instructions for turning a test subject into one or more testable systems.
You can always invoke the tests locally. Many tests modify or change the system they are run against, so take that into account when looking at how to invoke tests. The following examples invoke tests against the same system that the package git repository is checked out on. Below there are further options for invoking tests against another fully formed and integrated systems, such as an Atomic Host or container image test subject.
There may be more than one test present in a package git repository. Testing system will run each playbook matching the glob
tests/tests*.yml separately in a clean environment. Most often a single
tests.yml file is used as the main entry point. To run it use the following command:
You can find output artifacts of the tests in an
artifacts/ or specify a specific directory like this:
TEST_ARTIFACTS=/tmp/output ansible-playbook tests.yml
You can filter which kinds of tests are run by providing a
--tags argument. To only run tests that are suited for classic systems installed by
dnf you can use a command like:
ansible-playbook --tags=classic tests.yml
When run by a CI System the tests are invoked according to the Standard Test Interface. Look here for more details and standard invocation variables.
When you run the tests as above, the tests assume that the system to be tested is the same as the system invoking the tests. In particular, the test assumes that the thing to be tested is already installed.
A test subject is what we call the thing to be tested. RPMs are a particular kind of test subject. To turn a test subject into a launched, installed system to be tested, we use Ansible dynamic inventory. Let’s invoke the tests with an inventory and a specific version of gzip:
curl -o gzip.rpm https://kojipkgs.fedoraproject.org//packages/gzip/1.8/2.fc26/x86_64/gzip-1.8-2.fc26.x86_64.rpm export TEST_SUBJECTS=$PWD/gzip.rpm ansible-playbook tests.yml
You’ll notice that the RPM is installed into the testable system before invoking the tests. Some tests contain their own inventory, that is their own instructions for turning a test subject into one or more testable systems. But in this case we use the default
standard-test-roles inventory in
/usr/share/ansible/inventory to do this.
Another example is to use a test subject of a container image. This is also a fully formed and integrated deliverable. The test subject again represents the thing to be tested. For testing containers there is an additional dependency needed:
sudo dnf install standard-test-roles-inventory-docker
The container image is pulled from a registry and launched using docker by an Ansible dynamic inventory.
export TEST_SUBJECTS=docker:docker.io/library/fedora:27 ansible-playbook --tags=container tests.yml
If you watch closely you’ll notice the image is pulled if not already local, launched as a container, and then prepared for the tests to run on. The first time this may take a little longer. Not all tests are able to function in the somewhat different environment of a container. In fact, for certain tests, the software to be tested may not be included in the container. But many of the tests for core packages should work here.
--tags argument filters out tests that are not suitable for running in a container, either because the system functions differently, or the correct packages are not installable.
See the Debug section for instructions how to log into a running container and diagnose why the tests failed.
Tests for containers are run with a help of Docker. Containers are run within default security context. For more info see Seccomp security profiles for Docker. It is possible that some tests require additional privileges. In this case specify necessary arguments for Docker using an environment variable
TEST_DOCKER_EXTRA_ARGS. For this create a file
inventory file in
tests directory with the following content:
#!/bin/bash export TEST_DOCKER_EXTRA_ARGS="--security-opt seccomp:unconfined" exec merge-standard-inventory "$@"
#!/bin/bash export TEST_DOCKER_EXTRA_ARGS="--privileged" exec merge-standard-inventory "$@"
See merge-standard-inventory documentation for details.
The former example may seem a bit contrived, but the concept of a test subject starts to make more sense when you want to test a fully formed and integrated deliverable, such as Atomic Host. The test subject again represents the thing to be tested. The test subject in this case is a QCow2 image. To turn a test subject into a launched system ready to be tested, we use Ansible dynamic inventory.
curl -Lo /tmp/atomic.qcow2 https://getfedora.org/atomic_qcow2_latest export TEST_SUBJECTS=/tmp/atomic.qcow2 ansible-playbook --tags=atomic tests.yml
If you watch closely you’ll see that the Atomic Host image is booted, and the tests run against the launched image. Not all tests are able to function in the somewhat different environment of Atomic Host, in fact, for certain cases, the software to be tested may not be included in the Atomic Host test subject. But most of the tests in core packages should work here.
Some tests contain their own inventory, that is their own instructions for turning a test subject into one or more testable systems. But in this case we use the default
standard-test-roles inventory to do this.
--tags argument filters out tests that are not suitable for running on an Atomic Host, either because the system functions differently, or the correct packages are not available on that system.
See the Debug section to learn how to diagnose why the tests failed, and log into the running Atomic Host.
To increase output verbosity use option
ansible-playbook --tags=container tests.yml -v
or for full verbosity:
ansible-playbook --tags=container tests.yml -vvv
To debug tests in a running container or atomic host use the
TEST_DEBUG environment variable. After the playbook runs, you’ll see diagnosis information with a helpful command to log in.
For container you’ll see output like this:
DIAGNOSE: docker exec -it 56de801f0ddde36fc9770666f7be2a68f89d7f18f52b7b6fe7df7a12b193bf08 /bin/bash DIAGNOSE: kill 18261 # when finished
For atomic host the instructions are a bit different:
DIAGNOSE: ssh -p 2222 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null email@example.com # password: foobar DIAGNOSE: export ANSIBLE_INVENTORY=/tmp/inventory-cloudxyhF2M/inventory DIAGNOSE: kill 16611 # when finished
Now you can easily connect using these commands. Use suggested
kill command to finish the running instance when done with investigation.
Here’s the list of currently supported roles for test execution:
Role for executing tests written via the Avocado testing framework
A simple role for executing runtest.sh scripts, or other scripts in given directories
Role for executing tests written via Beakerlib testing framework, supporting all testing environments
Here’s list of currently supported helper roles:
This is the recommended role for running tests written via the Beakerlib Testing Framework as it supports all currenlty supported testing environments (atomic, classic, container). It also supports beakerlib-libraries which allow easy code reuse among multiple tests.
To use this role create
tests.yml file with contents similar to the following snippet. The
tests parameter should include the list of directories with your beakerlib tests.
- hosts: localhost tags: - atomic - classic - container roles: - role: standard-test-beakerlib tests: - cmd-line-options
required_packages parameter can be used to list additional packages that need to be installed on the system to run tests. If you have required packages correctly specified in the beakerlib test metadata (in Makefile
RhtsRequires stands for hard requirements,
Requires for soft requirements) it is not necessary to list them again here.
- hosts: localhost tags: - atomic - classic - container roles: - role: standard-test-beakerlib tests: - cmd-line-options required_packages: - which # which package required for cmd-line-options - rpm-build # upstream-testsuite requires rpmbuild command - libtool # upstream-testsuite requires libtool - gettext # upstream-testsuite requires gettext
Instead of manually listing all tests to be executed it is also possible to provide an fmf filter in the following way:
- hosts: localhost roles: - role: standard-test-beakerlib tags: - classic repositories: - repo: "https://src.fedoraproject.org/tests/shell.git" dest: "shell" fmf_filter: "tier: 1"
Filter can be used also if tests are stored directly in the git:
- hosts: localhost roles: - role: standard-test-beakerlib tags: - classic fmf_filter: "tier: 1"
See Metadata for more info about filtering tests based on fmf metadata.
Basic role can be used for executing scripts or binaries as simple tests. For example the following
tests.yml file will run
binary --help as a shell command in the current directory and provide pass/fail based on its return code:
- hosts: localhost roles: - role: standard-test-basic tags: - classic tests: - simple: dir: . run: binary --help
Here’s another example
tests.yml file which fetches a single integration test from a shared repository and uses parametrizing to run it multiple times with different environment variables:
- hosts: localhost roles: - role: standard-test-basic tags: - classic repositories: - repo: "https://src.fedoraproject.org/tests/python.git" dest: "python" tests: - smoke27: dir: python/smoke run: VERSION=2.7 METHOD=virtualenv ./venv.sh - smoke37: dir: python/smoke run: VERSION=3.7 ./venv.sh required_packages: - python27 - python37 - python2-virtualenv - python3-virtualenv - python2-devel - python3-devel
This role has been obsoleted by the BeakerLib role which provides similar functionality.