Back to home page

EIC code displayed by LXR

 
 

    


Warning, /acts/docs/groups/python/python_testing.md is written in an unsupported language. File is not indexed.

0001 @defgroup python_testing Python-based testing
0002 @ingroup python_bindings
0003 @brief Running the Python test suite and checking ROOT file hashes.
0004 
0005 Python bindings are exercised through `pytest`, in addition to the doc-example snippets used by
0006 @ref python_bindings.
0007 
0008 # Running the tests
0009 
0010 First configure and build the Python bindings, then load the generated environment as
0011 described in @ref python_bindings. Enable the optional components needed by the tests you want
0012 to run.
0013 
0014 A number of unit tests based on the `pytest` library are shipped with the repository, under
0015 `$REPO_ROOT/Python/Core/tests`, `Python/Fatras/tests`, and `Python/Examples/tests`. They cover
0016 the public API of the Python bindings, and a set of tests also execute the standalone example
0017 scripts under `Examples/Scripts/Python/`.
0018 
0019 To run these tests, `pytest` and a few other dependencies need to be installed:
0020 
0021 ```console
0022 pip install -r Python/Examples/tests/requirements.txt
0023 ```
0024 
0025 You can then simply run `pytest` from the repository root.
0026 
0027 > [!tip]
0028 > It is **strongly recommended** to use a [virtual
0029 > environment](https://realpython.com/python-virtual-environments-a-primer/)
0030 > for this purpose! For example, run
0031 > ```console
0032 > python -m venv venv
0033 > source venv/bin/activate
0034 > ```
0035 > to create a local virtual environment, and then run the `pip` command above.
0036 
0037 ## Markers
0038 
0039 Tests are grouped by optional dependency using pytest markers: `csv`, `obj`, `root`, `json`,
0040 `slow`, `edm4hep`, `odd`, `hepmc3`, and `pypi`. `pypi` marks the subset that only exercises what
0041 the PyPI wheel actually provides (see @ref python_bindings) — this is what `cibuildwheel`
0042 runs as the wheel smoke test. Run one marker's subset with:
0043 
0044 ```console
0045 pytest -m odd
0046 ```
0047 
0048 ## ROOT file hash regression checks {#root_file_hashes}
0049 
0050 In a number of cases, the python based test suite will run hash based regression tests against ROOT files that are
0051 written by the test workloads. These tests use a custom hash algorithm written in python, which hashes each individual
0052 entry of each `TTree` found in a file. These entry hashes are then sorted, concatenated and hashed again for the final output.
0053 This procedure ensures that if the ROOT file content changes, the hash changes, while also giving the same hash when the events
0054 stored in the file are reordered.
0055 
0056 The tests are implemented by looking up a reference hash from a central data file `$REPO_ROOT/Python/Examples/tests/root_file_hashes.txt`
0057 that looks like
0058 
0059 ```none
0060 test_ckf_tracks_example_full_seeding__performance_seeding_trees.root: 938bcc9b9425b12c620f5d0efa2c592817dfe92a18c309e97aa9d87412918620
0061 test_ckf_tracks_example_full_seeding__trackstates_ckf.root: 2faceafd4a521ff4030557301723e29c3d870edad052965eb644b824b57e2146
0062 test_ckf_tracks_example_truth_estimate__performance_seeding_trees.root: 5c0cf9e84af64e6814ab1ddf4cbaf4be6008ad8b2371b5b0241085b19d0fc52c
0063 test_ckf_tracks_example_truth_estimate__performance_seeding_trees.root: 5c0cf9e84af64e6814ab1ddf4cbaf4be6008ad8b2371b5b0241085b19d0fc52c
0064 test_ckf_tracks_example_truth_estimate__trackstates_ckf.root: ac4485c09a68fca3d056cb8d9adb81695e68d822629e48c71fd2b6d2bbd31f88
0065 ```
0066 
0067 where the left side before the `:` indicates the test in which the check is
0068 performed and the name of the ROOT file that is checked. The right side is the
0069 reference hash.
0070 
0071 > [!note]
0072 > The file from which reference hashes are loaded can be changed by setting the
0073 > environment variable `ROOT_HASH_FILE` to the desired file.
0074 
0075 These checks have two purposes:
0076 
0077 1. Detect regressions in the algorithms: if an algorithm produces different
0078    output, the test will catch it. This also means that if algorithmic changes
0079    are made that intentionally change the output, the reference hashes also have
0080    to be updated.
0081 
0082    > [!warning]
0083    > Please make sure to check the contents of a changed file are
0084    > correct/reasonable before updating the reference hash!
0085 
0086 2. Detect potential reproducibility issues. Tests that run with multiple
0087    threads should produce the same output every run, event ordering aside. If a
0088    test workload has a thread-reproducibility issue, the output hash should also
0089    change.
0090 
0091 ### Running the hash checks locally and how to update the reference hashes
0092 
0093 By default, the hash checks are not executed when the `pytest` command is run. To enable them, you need to set the environment
0094 variable `ROOT_HASH_CHECKS` needs to be set to `ON`, for example like:
0095 
0096 ```console
0097 ROOT_HASH_CHECKS=ON pytest
0098 ```
0099 
0100 If any hash mismatches are observed, the corresponding tests will fail, and `pytest` will print a summary at the end that looks like
0101 
0102 ```console
0103 ------------------------------------------- RootHashAssertionErrors -----------------------------------------------------
0104 The ROOT files produced by tests have changed since the last recorded reference.
0105 This can be be expected if e.g. the underlying algorithm changed, or it can be a test failure symptom.
0106 Please manually check the output files listed below and make sure that their content is correct.
0107 If it is, you can update the test reference file Python/Examples/tests/root_file_hashes.txt with the new hashes below.
0108 
0109 test_seeding__estimatedparams.root: 8bbc97cb3d4777c61dd0b483a1c8268fc8411ad182c35bc731e5ed222450deca
0110 test_material_recording__geant4_material_tracks.root: 019ce62ce378efa5c02a94768039686ed3cdfbd60c115c1f0cab2cbc53def57b
0111 test_material_mapping__material-maps_tracks.root: c03215e8b53733a3a7d7a0a5f9aec5bf2df20e8e40cc0492a8fa22400491d216
0112 test_material_mapping__propagation-material.root: a15a5c1e92fc3b848efb232eea1d40c422ee3a1d9ef1f7140294415621a04ce5
0113 test_ckf_tracks_example_full_seeding__tracksummary_ckf.root: 9e4d14169f20961be38d0305853a7cf7eeea4a647f0c94a48aada22c3c2c7a51
0114 test_ckf_tracks_example_truth_estimate__tracksummary_ckf.root: 3d56b26788163852e2c1f7288920f60a505bd14deeabb6f9189b680fcd90bfc5
0115 test_ckf_tracks_example_truth_smeared__tracksummary_ckf.root: ca2ce4069d2a2388c3d3c826dec8bea9f9d1e622239a20f8b985784d6c546c6e
0116 =========================================== short test summary info =====================================================
0117 FAILED Python/Examples/tests/test_examples.py::test_seeding
0118 FAILED Python/Examples/tests/test_examples.py::test_material_recording
0119 FAILED Python/Examples/tests/test_examples.py::test_material_mapping
0120 FAILED Python/Examples/tests/test_examples.py::test_ckf_tracks_example_full_seeding
0121 FAILED Python/Examples/tests/test_examples.py::test_ckf_tracks_example_truth_estimate
0122 FAILED Python/Examples/tests/test_examples.py::test_ckf_tracks_example_truth_smeared
0123 ================================== 6 failed, 183 passed in 199.82s (0:03:19) ============================================
0124 ```
0125 
0126 Here, we see that 7 hash checks have failed. The error output conveniently has the same format as the reference hashes found in `root_file_hashes.txt`.
0127 To update the reference hashes, simply replace the corresponding entries in `root_file_hashes.txt` with the output from the `pytest` run.
0128 
0129 > [!note]
0130 > CI runs the ROOT hash checks. However, we have observed the hashes to change
0131 > between different machines. This is believed to be due to differences in math
0132 > libraries producing slightly different outputs. As a consequence, locally
0133 > obtained file hashes might cause CI failures, as the CI hashes are different.
0134 >
0135 > For local testing, it is therefore advisable to use `ROOT_HASH_FILE` to use a
0136 > different file for the reference hashes and populated it with known-good
0137 > reference hashes from the `main` branch, before testing your developments.
0138 >
0139 > To make the CI succeed if it obtains different hashes than you get locally:
0140 > make sure that the output is correct, and then update the central
0141 > `root_file_hashes.txt` with the hashes reported in the failed CI job.