1
1
from __future__ import annotations
2
2
3
+ import enum
3
4
import os
4
5
import subprocess
5
6
import tempfile
7
+ from typing import Optional
6
8
from typing import Sequence
7
9
from xml .etree import ElementTree
8
10
14
16
from pytest_cpp .helpers import make_cmdline
15
17
16
18
19
+ class Catch2Version (enum .Enum ):
20
+ V2 = "v2"
21
+ V3 = "v3"
22
+
23
+
17
24
class Catch2Facade (AbstractFacade ):
18
25
"""
19
26
Facade for Catch2.
20
27
"""
21
28
22
29
@classmethod
23
- def is_test_suite (
30
+ def get_catch_version (
24
31
cls ,
25
32
executable : str ,
26
33
harness_collect : Sequence [str ] = (),
27
- ) -> bool :
34
+ ) -> Optional [ Catch2Version ] :
28
35
args = make_cmdline (harness_collect , executable , ["--help" ])
29
36
try :
30
37
output = subprocess .check_output (
@@ -33,25 +40,47 @@ def is_test_suite(
33
40
universal_newlines = True ,
34
41
)
35
42
except (subprocess .CalledProcessError , OSError ):
36
- return False
43
+ return None
37
44
else :
38
- return "--list-test-names-only" in output
45
+ return (
46
+ Catch2Version .V2
47
+ if "--list-test-names-only" in output
48
+ else Catch2Version .V3
49
+ if "--list-tests" in output
50
+ else None
51
+ )
52
+
53
+ @classmethod
54
+ def is_test_suite (
55
+ cls ,
56
+ executable : str ,
57
+ harness_collect : Sequence [str ] = (),
58
+ ) -> bool :
59
+ return cls .get_catch_version (executable , harness_collect ) in [
60
+ Catch2Version .V2 ,
61
+ Catch2Version .V3 ,
62
+ ]
39
63
40
64
def list_tests (
41
65
self ,
42
66
executable : str ,
43
67
harness_collect : Sequence [str ] = (),
44
68
) -> list [str ]:
45
69
"""
46
- Executes test with "--list-test-names-only" and gets list of tests
70
+ Executes test with "--list-test-names-only" (v2) or "--list-tests --verbosity quiet" (v3) and gets list of tests
47
71
parsing output like this:
48
72
49
73
1: All test cases reside in other .cpp files (empty)
50
74
2: Factorial of 0 is 1 (fail)
51
75
2: Factorials of 1 and higher are computed (pass)
52
76
"""
53
77
# This will return an exit code with the number of tests available
54
- args = make_cmdline (harness_collect , executable , ["--list-test-names-only" ])
78
+ exec_args = (
79
+ ["--list-test-names-only" ]
80
+ if self .get_catch_version (executable , harness_collect ) == Catch2Version .V2
81
+ else ["--list-tests" , "--verbosity quiet" ]
82
+ )
83
+ args = make_cmdline (harness_collect , executable , exec_args )
55
84
try :
56
85
output = subprocess .check_output (
57
86
args ,
@@ -77,6 +106,11 @@ def run_test(
77
106
On Windows, ValueError is raised when path and start are on different drives.
78
107
In this case failing back to the absolute path.
79
108
"""
109
+ catch_version = self .get_catch_version (executable , harness )
110
+
111
+ if catch_version is None :
112
+ raise Exception ("Invalid Catch Version" )
113
+
80
114
try :
81
115
xml_filename = os .path .join (os .path .relpath (temp_dir ), "cpp-report.xml" )
82
116
except ValueError :
@@ -97,7 +131,7 @@ def run_test(
97
131
except subprocess .CalledProcessError as e :
98
132
output = e .output
99
133
100
- results = self ._parse_xml (xml_filename )
134
+ results = self ._parse_xml (xml_filename , catch_version )
101
135
102
136
for executed_test_id , failures , skipped in results :
103
137
if executed_test_id == test_id :
@@ -123,11 +157,16 @@ def run_test(
123
157
return [failure ], output
124
158
125
159
def _parse_xml (
126
- self , xml_filename : str
160
+ self , xml_filename : str , catch_version : Catch2Version
127
161
) -> Sequence [tuple [str , Sequence [tuple [str , int , str ]], bool ]]:
128
162
root = ElementTree .parse (xml_filename )
129
163
result = []
130
- for test_suite in root .findall ("Group" ):
164
+ test_suites = (
165
+ root .findall ("Group" )
166
+ if catch_version == Catch2Version .V2
167
+ else root .iter ("Catch2TestRun" )
168
+ )
169
+ for test_suite in test_suites :
131
170
for test_case in test_suite .findall ("TestCase" ):
132
171
test_name = test_case .attrib ["name" ]
133
172
test_result = test_case .find ("OverallResult" )
0 commit comments