Skip to content

Running automated tests

This page describes how to run the midas tests: the full test suite (with make test, or step by step with CMake and CTest), the older Python unit tests, and the test programs installed in bin.

For more details, see tests/README.md in the midas repository, and the README.md and testplan.md in each directory under tests.

There are three sets of tests:

Tests What they test How to run them
The test suite The C++ libraries and programs (GoogleTest), the Python package (pytest), and the JavaScript of the web pages (node:test and Playwright) make test from the midas directory, or step by step with CMake and ctest. Not built by default
Python unit tests The Python package, in python/tests python3 -m unittest, against a running experiment
Test programs The ODB, the frontend frameworks and the operating system functions Run the programs in bin by hand

The test suite

The test suite is in the tests directory. It runs each test in its own temporary experiment, so it doesn't touch your experiments, and it doesn't need a running midas.

Note

Before September 2026, make test ran a short self test instead. It created an experiment in testexpt, ran a frontend and mlogger through a few runs, and compared the output with testexpt.example. make test now runs the full test suite.

Requirements

You need these system packages:

  • a C++ compiler, make, CMake 3.24 or newer and git
  • Python 3 and pip
  • Node.js 22 or newer and npm. Linux distributions often have an older version, so install it from NodeSource if needed
  • lcov, only for coverage reports

For example, on Debian or Ubuntu:

sudo apt install build-essential cmake git python3 python3-pip lcov
curl -fsSL https://deb.nodesource.com/setup_current.x | sudo -E bash -
sudo apt install nodejs

On macOS with Homebrew:

xcode-select --install
brew install cmake git python node lcov

The tests also need about 32 MB of shared memory (/dev/shm on Linux). This matters in Docker containers, which have only 64 MB by default.

The first build of the tests downloads GoogleTest (unless it is already installed), so it needs network access once. A normal midas build doesn't build the tests, and doesn't need network access.

Running everything with make test

From the midas directory:

cd $MIDASSYS
make test

make test has three steps, which you can also run one at a time:

Step What it does
make test-deps Checks that Node.js is new enough. Installs the midas Python package (pip install -e python/), pytest and pytest-cov, the JavaScript test packages (npm install in tests/resources) and Playwright's Chromium browser
make test-build Configures build with -DMIDAS_BUILD_TESTS=ON, builds midas and the tests, and installs midas into the midas directory (bin, lib, ...)
make test-run Runs all the tests with ctest --test-dir build --output-on-failure

Warning

make test-deps installs Python packages into whichever Python environment is active, so you may want to activate a virtual environment first. make test-build installs the newly built midas programs and libraries into the midas directory, replacing the ones there. Don't run it in a midas installation that a running experiment is using.

Building the tests by hand

The tests are built by the normal midas CMake build when MIDAS_BUILD_TESTS is on:

cd $MIDASSYS
mkdir build
cd build
cmake .. -DMIDAS_BUILD_TESTS=ON
make
make install

make install is needed for the tests that run midas programs (e.g. mhttpd) or use the midas library from Python, as they use the installed copies in the midas directory. Install the Python and JavaScript test packages first (e.g. with make test-deps), as their tests are only registered with CTest if pytest and tests/resources/node_modules exist when CMake runs. Tests whose prerequisites are missing are skipped rather than failing.

Running the tests with ctest

ctest runs all the tests. Each C++ test case is a separate CTest entry, while the Python and JavaScript tests are run in a few larger entries. Run it from the midas directory:

export MIDASSYS=$PWD
ctest --test-dir build --output-on-failure

Useful options:

Option Effect
-j8 Runs 8 tests at a time. This is several times faster. Each test uses shared memory, so in a container with little shared memory, use fewer jobs or none
-N Lists the tests without running them
-R <regex> Runs only the tests whose names match, e.g. -R '^OdbXx'
-LE External Leaves out the end-to-end browser tests
-LE LiveHttp Leaves out the tests that start a real mhttpd (about 25 tests, which take about 26 s)
-LE Pipeline Leaves out the end-to-end test that runs several midas programs together

Some tests fail on purpose: they check for the correct behaviour where midas still has a known bug. They are listed in tests/expected_failures.txt, and CTest counts them as passing while they fail. So ctest reports no failures on an unmodified midas, and anything that fails is a new problem. If a bug is fixed, its test starts passing and CTest reports it as failed, as a reminder to remove it from expected_failures.txt. The bugs themselves are described in tests/BUG_SUMMARY.md.

Running one suite

C++

Each C++ suite is built into one program, which you can run directly. This gives more detailed GoogleTest output, and --gtest_filter selects tests by name:

./build/tests/src/midas_unit_tests --gtest_filter='OdbXxValues.*'
./build/tests/src/midas_unit_tests --gtest_list_tests
Directory Program Tests
tests/src midas_unit_tests The midas library (src)
tests/progs midas_progs_unit_tests The midas programs (progs), including tests that run several programs together
tests/midasio midasio_unit_tests midasio (reading and writing midas files)
tests/mjson mjson_unit_tests mjson
tests/mvodb mvodb_unit_tests MVOdb
tests/mxml mxml_unit_tests mxml
tests/msetpoint msetpoint_unit_tests The MSetPoint EPICS frontend
tests/manalyzer manalyzer_unit_tests manalyzer
tests/mscb mscb_unit_tests MSCB

The programs are in the same directories under build. Tests that use an ODB need MIDASSYS to be set, as they run $MIDASSYS/bin/odbinit to create their temporary experiment. To add a test, add a test_*.cxx file to the suite's directory: it is found automatically.

Python

The Python tests are in tests/python, and are run with pytest. They are divided into tiers with pytest markers. The tests that need no midas installation run with:

pip install -e python/
pytest tests/python -m "not needs_midas"

The tests that use the midas library need a built midas, and create their own temporary experiment:

export MIDASSYS=$PWD
export PYTHONPATH=$PWD/python
pytest tests/python -m "needs_midas and not external"

Tests marked external need hardware or a network service, and are left out unless you select them with -m external. In CTest, the two tiers are the python_pure and python_live entries. See tests/python/README.md for the markers and fixtures.

JavaScript

The JavaScript tests are in tests/resources. The unit tests load the JavaScript files of the web pages into a simulated browser (jsdom), and the end-to-end tests run a real mhttpd and drive the Chromium browser with Playwright:

cd tests/resources
npm install
npm run test:unit
npx playwright install chromium
npm run test:e2e

package.json also has scripts that run the unit tests of one file, e.g. npm run test:unit:mplot. In CTest, the two tiers are the js_unit and js_e2e entries. See tests/resources/README.md for details.

Coverage

make coverage builds midas with coverage instrumentation, runs all the tests, and writes a coverage report for each language:

Report Language
cov_html C++ (with lcov)
cov_html_python Python (with pytest-cov)
tests/resources/coverage JavaScript

make coverage-recapture measures the coverage again with the existing build, without configuring it again. It doesn't rebuild either, so run make and make install in build first. Some code is deliberately left out of the coverage figures, e.g. obsolete functions. See tests/coverage_exclusions.md for the list and the reasons.

Continuous integration

The GitLab CI job build_and_test (in .gitlab-ci.yml) runs the test suite on Ubuntu 24.04, with ROOT installed. It runs make test-deps and make test-build as root, then make test-run as an unprivileged user, because some tests check what happens when a file can't be read. The job doesn't run on every commit. It runs on a schedule, or when started by hand from the GitLab web interface with the variable JOB_NAME set to full-test. If it fails, the CTest log and the Playwright reports are kept as job artifacts for a week.

Python unit tests

The original unit tests of the Python package are in python/tests, and use the Python unittest framework. Many of them have since been moved into the test suite (tests/python), which runs them in a temporary experiment.

Warning

These tests connect to the current experiment (as set by MIDAS_EXPT_NAME or exptab). They start and stop runs, and change the ODB. Only run them in a test experiment.

With the environment set up for a test experiment:

cd $MIDASSYS/python/tests
python3 -m unittest                            # all the tests
python3 -m unittest test_odb                   # the tests in test_odb.py
python3 -m unittest test_odb.TestOdb.testInt   # one test

Test programs

midas also builds some programs that test parts of midas by hand, such as test_odb, test_mvodb and torture_odb for the ODB, hwtest for the hardware and operating system, and the fetest frontend. They are installed in bin. Some of them (e.g. test_mvodb and torture_odb) don't report failures through their exit code, so check their output. See Test programs for the list.