Skip to content

Commit 95c634f

Browse files
committed
Refactorings: CppTestFailure is an ABC, use temporary directories better
1 parent 97e4d8f commit 95c634f

File tree

5 files changed

+91
-94
lines changed

5 files changed

+91
-94
lines changed

src/pytest_cpp/boost.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import io
44
import os
5-
import shutil
65
import subprocess
76
import tempfile
87
from typing import Sequence
@@ -50,22 +49,22 @@ def read_file(name: str) -> str:
5049
except IOError:
5150
return ""
5251

53-
temp_dir = tempfile.mkdtemp()
54-
log_xml = os.path.join(temp_dir, "log.xml")
55-
report_xml = os.path.join(temp_dir, "report.xml")
56-
args = list(harness) + [
57-
executable,
58-
"--output_format=XML",
59-
"--log_sink=%s" % log_xml,
60-
"--report_sink=%s" % report_xml,
61-
]
62-
args.extend(test_args)
63-
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
64-
raw_stdout, _ = p.communicate()
65-
stdout = raw_stdout.decode("utf-8") if raw_stdout else ""
66-
67-
log = read_file(log_xml)
68-
report = read_file(report_xml)
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)
6968

7069
if p.returncode not in (0, 200, 201):
7170
msg = (
@@ -90,7 +89,6 @@ def read_file(name: str) -> str:
9089
return [failure], stdout
9190

9291
results = self._parse_log(log=log)
93-
shutil.rmtree(temp_dir)
9492

9593
if results:
9694
return results, stdout

src/pytest_cpp/catch2.py

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -61,43 +61,44 @@ def run_test(
6161
test_args: Sequence[str] = (),
6262
harness: Sequence[str] = (),
6363
) -> tuple[Sequence[Catch2Failure] | None, str]:
64-
xml_filename = self._get_temp_xml_filename()
65-
args = list(harness) + [
66-
executable,
67-
test_id,
68-
"--success",
69-
"--reporter=xml",
70-
"--out %s" % xml_filename,
71-
]
72-
args.extend(test_args)
73-
74-
try:
75-
output = subprocess.check_output(
76-
args, stderr=subprocess.STDOUT, universal_newlines=True
77-
)
78-
except subprocess.CalledProcessError as e:
79-
output = e.output
80-
if e.returncode != 1:
81-
msg = (
82-
"Internal Error: calling {executable} "
83-
"for test {test_id} failed (returncode={returncode}):\n"
84-
"{output}"
85-
)
86-
failure = Catch2Failure(
87-
executable,
88-
0,
89-
msg.format(
90-
executable=executable,
91-
test_id=test_id,
92-
output=e.output,
93-
returncode=e.returncode,
94-
),
64+
with tempfile.TemporaryDirectory(prefix="pytest-cpp") as tmp_dir:
65+
xml_filename = os.path.join(tmp_dir, "cpp-report.xml")
66+
args = list(harness) + [
67+
executable,
68+
test_id,
69+
"--success",
70+
"--reporter=xml",
71+
"--out %s" % xml_filename,
72+
]
73+
args.extend(test_args)
74+
75+
try:
76+
output = subprocess.check_output(
77+
args, stderr=subprocess.STDOUT, universal_newlines=True
9578
)
79+
except subprocess.CalledProcessError as e:
80+
output = e.output
81+
if e.returncode != 1:
82+
msg = (
83+
"Internal Error: calling {executable} "
84+
"for test {test_id} failed (returncode={returncode}):\n"
85+
"{output}"
86+
)
87+
failure = Catch2Failure(
88+
executable,
89+
0,
90+
msg.format(
91+
executable=executable,
92+
test_id=test_id,
93+
output=e.output,
94+
returncode=e.returncode,
95+
),
96+
)
9697

97-
return [failure], output
98+
return [failure], output
99+
100+
results = self._parse_xml(xml_filename)
98101

99-
results = self._parse_xml(xml_filename)
100-
os.remove(xml_filename)
101102
for (executed_test_id, failures, skipped) in results:
102103
if executed_test_id == test_id:
103104
if failures:
@@ -121,9 +122,6 @@ def run_test(
121122
)
122123
return [failure], output
123124

124-
def _get_temp_xml_filename(self) -> str:
125-
return tempfile.mktemp()
126-
127125
def _parse_xml(
128126
self, xml_filename: str
129127
) -> Sequence[tuple[str, Sequence[tuple[str, int, str]], bool]]:

src/pytest_cpp/error.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import os
44
import string
5+
from abc import ABC
6+
from abc import abstractmethod
57
from typing import Sequence
68
from typing import Tuple
79

@@ -21,13 +23,14 @@ def __init__(self, failures: Sequence[CppTestFailure]) -> None:
2123
Markup = Tuple[str, ...]
2224

2325

24-
class CppTestFailure(object):
26+
class CppTestFailure(ABC):
2527
"""
2628
Represents a failure in a C++ test. Each framework
2729
must implement the abstract functions to build the final exception
2830
message that will be displayed in the terminal.
2931
"""
3032

33+
@abstractmethod
3134
def get_lines(self) -> list[tuple[str, Markup]]:
3235
"""
3336
Returns list of (line, markup) that will be displayed to the user,
@@ -38,13 +41,12 @@ def get_lines(self) -> list[tuple[str, Markup]]:
3841
'blue', 'purple', 'cyan', 'white',
3942
'bold', 'light', 'blink', 'invert'
4043
"""
41-
raise NotImplementedError # pragma: no cover
4244

45+
@abstractmethod
4346
def get_file_reference(self) -> tuple[str, int]:
4447
"""
4548
Return tuple of filename, linenum of the failure.
4649
"""
47-
raise NotImplementedError # pragma: no cover
4850

4951

5052
class CppFailureRepr(object):

src/pytest_cpp/google.py

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -71,39 +71,40 @@ def run_test(
7171
test_args: Sequence[str] = (),
7272
harness: Sequence[str] = (),
7373
) -> tuple[list[GoogleTestFailure] | None, str]:
74-
xml_filename = self._get_temp_xml_filename()
75-
args = list(harness) + [
76-
executable,
77-
"--gtest_filter=" + test_id,
78-
"--gtest_output=xml:%s" % xml_filename,
79-
]
80-
args.extend(test_args)
81-
82-
try:
83-
output = subprocess.check_output(
84-
args, stderr=subprocess.STDOUT, universal_newlines=True
85-
)
86-
except subprocess.CalledProcessError as e:
87-
output = e.output
88-
if e.returncode != 1:
89-
msg = (
90-
"Internal Error: calling {executable} "
91-
"for test {test_id} failed (returncode={returncode}):\n"
92-
"{output}"
74+
with tempfile.TemporaryDirectory(prefix="pytest-cpp") as tmp_dir:
75+
xml_filename = os.path.join(tmp_dir, "cpp-report.xml")
76+
args = list(harness) + [
77+
executable,
78+
"--gtest_filter=" + test_id,
79+
"--gtest_output=xml:%s" % xml_filename,
80+
]
81+
args.extend(test_args)
82+
83+
try:
84+
output = subprocess.check_output(
85+
args, stderr=subprocess.STDOUT, universal_newlines=True
9386
)
94-
failure = GoogleTestFailure(
95-
msg.format(
96-
executable=executable,
97-
test_id=test_id,
98-
output=e.output,
99-
returncode=e.returncode,
87+
except subprocess.CalledProcessError as e:
88+
output = e.output
89+
if e.returncode != 1:
90+
msg = (
91+
"Internal Error: calling {executable} "
92+
"for test {test_id} failed (returncode={returncode}):\n"
93+
"{output}"
94+
)
95+
failure = GoogleTestFailure(
96+
msg.format(
97+
executable=executable,
98+
test_id=test_id,
99+
output=e.output,
100+
returncode=e.returncode,
101+
)
100102
)
101-
)
102103

103-
return [failure], output
104+
return [failure], output
105+
106+
results = self._parse_xml(xml_filename)
104107

105-
results = self._parse_xml(xml_filename)
106-
os.remove(xml_filename)
107108
for (executed_test_id, failures, skipped) in results:
108109
if executed_test_id == test_id:
109110
if failures:
@@ -118,9 +119,6 @@ def run_test(
118119
failure = GoogleTestFailure(msg.format(test_id=test_id, results=results_list))
119120
return [failure], output
120121

121-
def _get_temp_xml_filename(self) -> str:
122-
return tempfile.mktemp()
123-
124122
def _parse_xml(
125123
self, xml_filename: str
126124
) -> Sequence[tuple[str, Sequence[str], Sequence[str]]]:

tests/test_pytest_cpp.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import subprocess
22
import sys
3+
import tempfile
34

45
import pytest
56
from distutils.spawn import find_executable
@@ -247,11 +248,11 @@ def raise_error(*args, **kwargs):
247248
assert "Internal Error: calling" in str(rep.longrepr)
248249

249250
mocked.side_effect = None
250-
xml_file = tmp_path.joinpath("results.xml")
251+
xml_file = tmp_path.joinpath("cpp-report.xml")
251252
xml_file.write_text("<empty/>")
252-
mocker.patch.object(
253-
GoogleTestFacade, "_get_temp_xml_filename", return_value=str(xml_file)
254-
)
253+
temp_mock = mocker.patch.object(tempfile, "TemporaryDirectory")
254+
temp_mock().__enter__.return_value = str(tmp_path)
255+
255256
result = testdir.inline_run("-v", exes.get("gtest", "test_gtest"))
256257
rep = result.matchreport(exes.exe_name("test_gtest"), "pytest_runtest_logreport")
257258

0 commit comments

Comments
 (0)