1+ import subprocess
2+ import sys
3+ import pathlib
4+ import ROOT
5+ import os
6+ import pytest
7+ import signal
8+
9+ ROOT .gROOT .SetBatch (True )
10+
11+ tutorial_dir = pathlib .Path (str (ROOT .gROOT .GetTutorialDir ()))
12+
13+ subdirs = [
14+ "analysis/dataframe" ,
15+ "analysis/tree" ,
16+ "hist" ,
17+ "io/ntuple" ,
18+ "roofit/roofit"
19+ ]
20+
21+ # ----------------------
22+ # Python tutorials tests
23+ # ----------------------
24+ py_tutorials = []
25+ for sub in subdirs :
26+ sub_path = tutorial_dir / sub
27+ # py_tutorials.extend(sub_path.rglob("*.py"))
28+ for f in sub_path .rglob ("*.py" ):
29+ # skip distrdf tutorials for now
30+ if "distrdf" in f .name :
31+ continue
32+ py_tutorials .append (f )
33+
34+ def test_tutorials_are_detected ():
35+ assert len (py_tutorials ) > 0
36+
37+ @pytest .mark .parametrize ("tutorial" , py_tutorials , ids = lambda p : p .name )
38+ def test_tutorial (tutorial ):
39+ env = dict (** os .environ )
40+ # force matplotlib to use a non-GUI backend
41+ env ["MPLBACKEND" ] = "Agg"
42+ print ("Test env:" , env )
43+ try :
44+ result = subprocess .run (
45+ [sys .executable , str (tutorial )],
46+ check = True ,
47+ env = env ,
48+ timeout = 60 ,
49+ )
50+ print ("Test stderr:" , result .stderr )
51+ except subprocess .TimeoutExpired :
52+ pytest .skip (f"Tutorial { tutorial } timed out" )
53+ except subprocess .CalledProcessError as e :
54+ # read stderr to see if EOFError occurred
55+ if "EOFError" in e .stderr :
56+ pytest .skip (f"Skipping { tutorial .name } (requires user input)" )
57+ raise
58+
59+ # ----------------------
60+ # C++ tutorials tests
61+ # ----------------------
62+ cpp_tutorials = []
63+ for sub in subdirs :
64+ sub_path = tutorial_dir / sub
65+ cpp_tutorials .extend (sub_path .rglob ("*.C" ))
66+
67+ def test_cpp_tutorials_are_detected ():
68+ assert len (cpp_tutorials ) > 0
69+
70+ @pytest .mark .parametrize ("tutorial" , cpp_tutorials , ids = lambda p : p .name )
71+ def test_cpp_tutorial (tutorial ):
72+ try :
73+ result = subprocess .run (
74+ [sys .executable , "-c" , f'import ROOT; ROOT.gROOT.ProcessLine(".x { tutorial } ")' ],
75+ check = True ,
76+ timeout = 60 ,
77+ capture_output = True ,
78+ text = True
79+ )
80+ except subprocess .TimeoutExpired :
81+ pytest .skip (f"Tutorial { tutorial } timed out" )
82+ except subprocess .CalledProcessError as e :
83+ if e .returncode == - signal .SIGILL or e .returncode == 132 :
84+ pytest .fail (f"Failing { tutorial .name } (illegal instruction on this platform)" )
85+ elif "EOFError" in e .stderr :
86+ pytest .skip (f"Skipping { tutorial .name } (requires user input)" )
87+ raise
0 commit comments