1
+ from __future__ import annotations
2
+
1
3
import io
2
4
import os
3
- import shutil
4
5
import subprocess
5
6
import tempfile
7
+ from typing import Sequence
6
8
from xml .etree import ElementTree
7
9
8
10
from pytest_cpp .error import CppTestFailure
11
+ from pytest_cpp .error import Markup
12
+ from pytest_cpp .facade_abc import AbstractFacade
9
13
10
14
11
- class BoostTestFacade (object ):
15
+ class BoostTestFacade (AbstractFacade ):
12
16
"""
13
17
Facade for BoostTests.
14
18
"""
15
19
16
20
@classmethod
17
- def is_test_suite (cls , executable ) :
21
+ def is_test_suite (cls , executable : str ) -> bool :
18
22
try :
19
23
output = subprocess .check_output (
20
24
[executable , "--help" ],
@@ -26,37 +30,41 @@ def is_test_suite(cls, executable):
26
30
else :
27
31
return "--output_format" in output and "log_format" in output
28
32
29
- def list_tests (self , executable ) :
33
+ def list_tests (self , executable : str ) -> list [ str ] :
30
34
# unfortunately boost doesn't provide us with a way to list the tests
31
35
# inside the executable, so the test_id is a dummy placeholder :(
32
36
return [os .path .basename (os .path .splitext (executable )[0 ])]
33
37
34
- def run_test (self , executable , test_id , test_args = (), harness = None ):
35
- harness = harness or []
36
-
37
- def read_file (name ):
38
+ def run_test (
39
+ self ,
40
+ executable : str ,
41
+ test_id : str ,
42
+ test_args : Sequence [str ] = (),
43
+ harness : Sequence [str ] = (),
44
+ ) -> tuple [Sequence [BoostTestFailure ] | None , str ]:
45
+ def read_file (name : str ) -> str :
38
46
try :
39
47
with io .open (name ) as f :
40
48
return f .read ()
41
49
except IOError :
42
- return None
43
-
44
- temp_dir = tempfile .mkdtemp ()
45
- log_xml = os .path .join (temp_dir , "log.xml" )
46
- report_xml = os .path .join (temp_dir , "report.xml" )
47
- args = harness + [
48
- executable ,
49
- "--output_format=XML" ,
50
- "--log_sink=%s" % log_xml ,
51
- "--report_sink=%s" % report_xml ,
52
- ]
53
- args .extend (test_args )
54
- p = subprocess .Popen (args , stdout = subprocess .PIPE , stderr = subprocess .STDOUT )
55
- raw_stdout , _ = p .communicate ()
56
- stdout = raw_stdout .decode ("utf-8" ) if raw_stdout else ""
57
-
58
- log = read_file (log_xml )
59
- report = read_file (report_xml )
50
+ return ""
51
+
52
+ with tempfile .TemporaryDirectory ( prefix = "pytest-cpp" ) as temp_dir :
53
+ log_xml = os .path .join (temp_dir , "log.xml" )
54
+ report_xml = os .path .join (temp_dir , "report.xml" )
55
+ args = list ( harness ) + [
56
+ executable ,
57
+ "--output_format=XML" ,
58
+ "--log_sink=%s" % log_xml ,
59
+ "--report_sink=%s" % report_xml ,
60
+ ]
61
+ args .extend (test_args )
62
+ p = subprocess .Popen (args , stdout = subprocess .PIPE , stderr = subprocess .STDOUT )
63
+ raw_stdout , _ = p .communicate ()
64
+ stdout = raw_stdout .decode ("utf-8" ) if raw_stdout else ""
65
+
66
+ log = read_file (log_xml )
67
+ report = read_file (report_xml )
60
68
61
69
if p .returncode not in (0 , 200 , 201 ):
62
70
msg = (
@@ -81,14 +89,13 @@ def read_file(name):
81
89
return [failure ], stdout
82
90
83
91
results = self ._parse_log (log = log )
84
- shutil .rmtree (temp_dir )
85
92
86
93
if results :
87
94
return results , stdout
88
95
89
96
return None , stdout
90
97
91
- def _parse_log (self , log ) :
98
+ def _parse_log (self , log : str ) -> list [ BoostTestFailure ] :
92
99
"""
93
100
Parse the "log" section produced by BoostTest.
94
101
@@ -116,19 +123,19 @@ def _parse_log(self, log):
116
123
for elem in parsed_elements :
117
124
filename = elem .attrib ["file" ]
118
125
linenum = int (elem .attrib ["line" ])
119
- result .append (BoostTestFailure (filename , linenum , elem .text ))
126
+ result .append (BoostTestFailure (filename , linenum , elem .text or "" ))
120
127
return result
121
128
122
129
123
130
class BoostTestFailure (CppTestFailure ):
124
- def __init__ (self , filename , linenum , contents ) :
131
+ def __init__ (self , filename : str , linenum : int , contents : str ) -> None :
125
132
self .filename = filename
126
133
self .linenum = linenum
127
134
self .lines = contents .splitlines ()
128
135
129
- def get_lines (self ):
136
+ def get_lines (self ) -> list [ tuple [ str , Markup ]] :
130
137
m = ("red" , "bold" )
131
138
return [(x , m ) for x in self .lines ]
132
139
133
- def get_file_reference (self ):
140
+ def get_file_reference (self ) -> tuple [ str , int ] :
134
141
return self .filename , self .linenum
0 commit comments