1+ from __future__ import annotations
2+
13import io
24import os
3- import shutil
45import subprocess
56import tempfile
7+ from typing import Sequence
68from xml .etree import ElementTree
79
810from pytest_cpp .error import CppTestFailure
11+ from pytest_cpp .error import Markup
12+ from pytest_cpp .facade_abc import AbstractFacade
913
1014
11- class BoostTestFacade (object ):
15+ class BoostTestFacade (AbstractFacade ):
1216 """
1317 Facade for BoostTests.
1418 """
1519
1620 @classmethod
17- def is_test_suite (cls , executable ) :
21+ def is_test_suite (cls , executable : str ) -> bool :
1822 try :
1923 output = subprocess .check_output (
2024 [executable , "--help" ],
@@ -26,37 +30,41 @@ def is_test_suite(cls, executable):
2630 else :
2731 return "--output_format" in output and "log_format" in output
2832
29- def list_tests (self , executable ) :
33+ def list_tests (self , executable : str ) -> list [ str ] :
3034 # unfortunately boost doesn't provide us with a way to list the tests
3135 # inside the executable, so the test_id is a dummy placeholder :(
3236 return [os .path .basename (os .path .splitext (executable )[0 ])]
3337
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 :
3846 try :
3947 with io .open (name ) as f :
4048 return f .read ()
4149 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 )
6068
6169 if p .returncode not in (0 , 200 , 201 ):
6270 msg = (
@@ -81,14 +89,13 @@ def read_file(name):
8189 return [failure ], stdout
8290
8391 results = self ._parse_log (log = log )
84- shutil .rmtree (temp_dir )
8592
8693 if results :
8794 return results , stdout
8895
8996 return None , stdout
9097
91- def _parse_log (self , log ) :
98+ def _parse_log (self , log : str ) -> list [ BoostTestFailure ] :
9299 """
93100 Parse the "log" section produced by BoostTest.
94101
@@ -116,19 +123,19 @@ def _parse_log(self, log):
116123 for elem in parsed_elements :
117124 filename = elem .attrib ["file" ]
118125 linenum = int (elem .attrib ["line" ])
119- result .append (BoostTestFailure (filename , linenum , elem .text ))
126+ result .append (BoostTestFailure (filename , linenum , elem .text or "" ))
120127 return result
121128
122129
123130class BoostTestFailure (CppTestFailure ):
124- def __init__ (self , filename , linenum , contents ) :
131+ def __init__ (self , filename : str , linenum : int , contents : str ) -> None :
125132 self .filename = filename
126133 self .linenum = linenum
127134 self .lines = contents .splitlines ()
128135
129- def get_lines (self ):
136+ def get_lines (self ) -> list [ tuple [ str , Markup ]] :
130137 m = ("red" , "bold" )
131138 return [(x , m ) for x in self .lines ]
132139
133- def get_file_reference (self ):
140+ def get_file_reference (self ) -> tuple [ str , int ] :
134141 return self .filename , self .linenum
0 commit comments