Let's Actually Make A Test (For Real)
Overview
Teaching: 5 min
Exercises: 20 minQuestions
I’m out of questions.
I’ve been here too long. Mr. Stark, I don’t feel too good.
Objectives
Actually add a test on the output of running physics.
So at this point, I’m going to be very hands-off and just explain what you will be doing. Here’s where you should be starting from:
stages:
- build
- run
- plot
.template_build:
stage: build
before_script:
- COMPILER=$(root-config --cxx)
- FLAGS=$(root-config --cflags --libs)
script:
- $COMPILER -g -O3 -Wall -Wextra -Wpedantic -o skim skim.cxx $FLAGS
artifacts:
paths:
- skim
expire_in: 1 day
multi_build:
extends: .template_build
image: $ROOT_IMAGE
parallel:
matrix:
- ROOT_IMAGE: ["rootproject/root:6.28.10-ubuntu22.04", "rootproject/root:latest"]
skim_ggH:
stage: run
dependencies:
- build_skim
image: rootproject/root:6.28.10-ubuntu22.04
script:
- ./skim root://eospublic.cern.ch//eos/root-eos/HiggsTauTauReduced/GluGluToHToTauTau.root skim_ggH.root 19.6 11467.0 0.1
artifacts:
paths:
- skim_ggH.root
- skim_ggH.log
expire_in: 1 week
plot_ggH:
stage: plot
dependencies:
- skim_ggH
image: rootproject/root:6.28.10-ubuntu22.04
script:
- python histograms.py skim_ggH.root ggH hist_ggH.root
artifacts:
paths:
- hist_ggH.root
expire_in: 1 week
Adding a regression test
- Add a
teststage after theplotstage.- Add a test job,
test_ggH, part of theteststage, and has the rightdependencies.
- Note:
./skimneeds to be updated to produce askim_ggH.log(hint:./skim .... > skim_ggH.log).- We also need the
hist_ggH.rootfile produced by the plot job.- Create a directory called
tests/and make two Python files in it namedtest_cutflow_ggH.pyandtest_plot_ggH.pythat usePyROOTandpython3.
- You might find the following lines (below) helpful to set up the tests.
- Write a few different tests of your choosing that test (and assert) something about
hist_ggH.root. Some ideas are:
- Check the structure (does
ggH_pt_1exist?).- Check that the integral of a histogram matches a value you expect.
- Check that the bins of a histogram match the values you expect.
- Update your
test_ggHjob to execute the regression tests.- Try causing your CI/CD to fail on the
test_ggHjob.Done?
Once you’re happy with setting up the regression test, mark your merge request as ready by clicking the
Resolve WIP Statusbutton, and then merge it into master.
Template for test_cutflow_ggH.py
import sys
logfile = open('skim_ggH.log', 'r')
lines = [line.rstrip() for line in logfile]
required_lines = [
'Number of events: 47696',
'Cross-section: 19.6',
'Integrated luminosity: 11467',
'Global scaling: 0.1',
'Passes trigger: pass=3402 all=47696 -- eff=7.13 % cumulative eff=7.13 %',
'nMuon > 0 : pass=3402 all=3402 -- eff=100.00 % cumulative eff=7.13 %',
'nTau > 0 : pass=3401 all=3402 -- eff=99.97 % cumulative eff=7.13 %',
'Event has good taus: pass=846 all=3401 -- eff=24.88 % cumulative eff=1.77 %',
'Event has good muons: pass=813 all=846 -- eff=96.10 % cumulative eff=1.70 %',
'Valid muon in selected pair: pass=813 all=813 -- eff=100.00 % cumulative eff=1.70 %',
'Valid tau in selected pair: pass=813 all=813 -- eff=100.00 % cumulative eff=1.70 %',
]
print('\n'.join(lines))
for required_line in required_lines:
if not required_line in lines:
print(f'Did not find line in log file. {required_line}')
sys.exit(1)
Template for test_plot_ggH.py
import sys
import ROOT
f = ROOT.TFile.Open('hist_ggH.root')
keys = [k.GetName() for k in f.GetListOfKeys()]
required_keys = ['ggH_pt_1', 'ggH_pt_2']
print('\n'.join(keys))
for required_key in required_keys:
if not required_key in keys:
print(f'Required key not found. {required_key}')
sys.exit(1)
integral = f.ggH_pt_1.Integral()
if abs(integral - 222.88716647028923) > 0.0001:
print(f'Integral of ggH_pt_1 is different: {integral}')
sys.exit(1)
Key Points
This kind of test is a regression test, as we’re testing assuming the code up to this point was correct.
This is not a unit test. Unit tests would be testing individual pieces of the
atlas/athenaorCMSSWcode-base, or specific functionality you wrote into your algorithms.