Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8f3e7b4

Browse files
committedFeb 9, 2023
fix: only write "Wrote report" message if report succeeded.
For example, see [issue 1554](#1554) for the previous misleading behavior when the exception being raised wasn't a CoverageException.
1 parent 423fa59 commit 8f3e7b4

File tree

3 files changed

+22
-18
lines changed

3 files changed

+22
-18
lines changed
 

‎CHANGES.rst

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ Unreleased
2323
- Added a :meth:`.CoverageData.purge_files` method to remove recorded data for
2424
a particular file. Contributed by `Stephan Deibel <pull 1547_>`_.
2525

26+
- Fix: when reporting commands fail, they will no longer congratulate
27+
themselves with messages like "Wrote XML report to file.xml" before spewing a
28+
traceback about their failure.
29+
2630
- Fix: In some embedded environments, an IndexError could occur on stop() when
2731
the originating thread exits before completion. This is now fixed, thanks to
2832
`Russell Keith-Magee <pull 1543_>`_, closing `issue 1542`_.

‎coverage/report.py

+11-12
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from typing import Callable, Iterable, Iterator, IO, Optional, Tuple, TYPE_CHECKING
1111

12-
from coverage.exceptions import CoverageException, NoDataError, NotPython
12+
from coverage.exceptions import NoDataError, NotPython
1313
from coverage.files import prep_patterns, GlobMatcher
1414
from coverage.misc import ensure_dir_for_file, file_be_gone
1515
from coverage.plugin import FileReporter
@@ -47,26 +47,25 @@ def render_report(
4747
if output_path == "-":
4848
outfile = sys.stdout
4949
else:
50-
# Ensure that the output directory is created; done here
51-
# because this report pre-opens the output file.
52-
# HTMLReport does this using the Report plumbing because
53-
# its task is more complex, being multiple files.
50+
# Ensure that the output directory is created; done here because this
51+
# report pre-opens the output file. HtmlReporter does this on its own
52+
# because its task is more complex, being multiple files.
5453
ensure_dir_for_file(output_path)
5554
outfile = open(output_path, "w", encoding="utf-8")
5655
file_to_close = outfile
56+
delete_file = True
5757

5858
try:
59-
return reporter.report(morfs, outfile=outfile)
60-
except CoverageException:
61-
delete_file = True
62-
raise
59+
ret = reporter.report(morfs, outfile=outfile)
60+
if file_to_close is not None:
61+
msgfn(f"Wrote {reporter.report_type} to {output_path}")
62+
delete_file = False
63+
return ret
6364
finally:
64-
if file_to_close:
65+
if file_to_close is not None:
6566
file_to_close.close()
6667
if delete_file:
6768
file_be_gone(output_path) # pragma: part covered (doesn't return)
68-
else:
69-
msgfn(f"Wrote {reporter.report_type} to {output_path}")
7069

7170

7271
def get_analysis_to_report(

‎tests/test_report.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from __future__ import annotations
77

8-
from typing import IO, Iterable, List, Optional
8+
from typing import IO, Iterable, List, Optional, Type
99

1010
import pytest
1111

@@ -21,7 +21,7 @@ class FakeReporter:
2121

2222
report_type = "fake report file"
2323

24-
def __init__(self, output: str = "", error: bool = False) -> None:
24+
def __init__(self, output: str = "", error: Optional[Type[Exception]] = None) -> None:
2525
self.output = output
2626
self.error = error
2727
self.morfs: Optional[Iterable[TMorf]] = None
@@ -31,7 +31,7 @@ def report(self, morfs: Optional[Iterable[TMorf]], outfile: IO[str]) -> float:
3131
self.morfs = morfs
3232
outfile.write(self.output)
3333
if self.error:
34-
raise CoverageException("You asked for it!")
34+
raise self.error("You asked for it!")
3535
return 17.25
3636

3737

@@ -57,10 +57,11 @@ def test_file(self) -> None:
5757
assert f.read().rstrip() == b"Gr\xc3\xa9\xc3\xa8tings!"
5858
assert msgs == ["Wrote fake report file to output.txt"]
5959

60-
def test_exception(self) -> None:
61-
fake = FakeReporter(error=True)
60+
@pytest.mark.parametrize("error", [CoverageException, ZeroDivisionError])
61+
def test_exception(self, error: Type[Exception]) -> None:
62+
fake = FakeReporter(error=error)
6263
msgs: List[str] = []
63-
with pytest.raises(CoverageException, match="You asked for it!"):
64+
with pytest.raises(error, match="You asked for it!"):
6465
render_report("output.txt", fake, [], msgs.append)
6566
assert self.stdout() == ""
6667
self.assert_doesnt_exist("output.txt")

0 commit comments

Comments
 (0)
Please sign in to comment.