diff --git a/tests/helpers.py b/tests/helpers.py index 9e6e2e8de..03e694db2 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -397,3 +397,8 @@ def __init__(self, options: Iterable[str]) -> None: def get_output(self) -> str: """Get the output text from the `DebugControl`.""" return self.io.getvalue() + + +def without_color(text: str) -> str: + """Remove ANSI color-setting escape sequences.""" + return re.sub(r"\033\[[\d;]+m", "", text) diff --git a/tests/test_execfile.py b/tests/test_execfile.py index 908857942..c3791e635 100644 --- a/tests/test_execfile.py +++ b/tests/test_execfile.py @@ -23,6 +23,7 @@ from coverage.files import python_reported_file from tests.coveragetest import CoverageTest, TESTS_DIR, UsingModulesMixin +from tests.helpers import without_color TRY_EXECFILE = os.path.join(TESTS_DIR, "modules/process_test/try_execfile.py") @@ -188,7 +189,7 @@ def excepthook(*args): run_python_file(["excepthook_throw.py"]) # The _ExceptionDuringRun exception has the RuntimeError as its argument. assert exc_info.value.args[1].args[0] == "Error Outside" - stderr = self.stderr() + stderr = without_color(self.stderr()) assert "in excepthook\n" in stderr assert "Error in sys.excepthook:\n" in stderr assert "RuntimeError: Error Inside" in stderr diff --git a/tests/test_process.py b/tests/test_process.py index 5aeb49744..a5db56b69 100644 --- a/tests/test_process.py +++ b/tests/test_process.py @@ -27,7 +27,7 @@ from tests import testenv from tests.coveragetest import CoverageTest, TESTS_DIR -from tests.helpers import re_line, re_lines, re_lines_text +from tests.helpers import re_line, re_lines, re_lines_text, without_color class ProcessTest(CoverageTest): @@ -318,6 +318,7 @@ def f2(): assert out == out2 # But also make sure that the output is what we expect. + out = without_color(out) path = python_reported_file('throw.py') msg = f'File "{re.escape(path)}", line 8, in f2' assert re.search(msg, out) @@ -969,8 +970,11 @@ def excepthook(*args): py_st, py_out = self.run_command_status("python excepthook_throw.py") assert cov_st == py_st assert cov_st == 1 - assert "in excepthook" in py_out - assert cov_out == py_out + assert "in excepthook" in without_color(py_out) + # Don't know why: the Python output shows "Error in sys.excepthook" and + # "Original exception" in color. The coverage output has the first in + # color and "Original" without color? Strip all the color. + assert without_color(cov_out) == without_color(py_out) class AliasedCommandTest(CoverageTest): @@ -1177,6 +1181,7 @@ def test_removing_directory(self) -> None: def test_removing_directory_with_error(self) -> None: self.make_file("bug806.py", self.BUG_806) out = self.run_command("coverage run bug806.py") + out = without_color(out) path = python_reported_file('bug806.py') # Python 3.11 adds an extra line to the traceback. # Check that the lines we expect are there. diff --git a/tests/test_testing.py b/tests/test_testing.py index 3c3b0622e..1af6613ea 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -24,7 +24,7 @@ from tests.helpers import ( CheckUniqueFilenames, FailingProxy, arcs_to_arcz_repr, arcz_to_arcs, assert_count_equal, assert_coverage_warnings, - re_lines, re_lines_text, re_line, + re_lines, re_lines_text, re_line, without_color, ) @@ -472,3 +472,15 @@ def subtract(self, a, b): # type: ignore[no-untyped-def] proxy.add(3, 4) # then add starts working assert proxy.add(5, 6) == 11 + + +@pytest.mark.parametrize("text, result", [ + ("", ""), + ("Nothing to see here", "Nothing to see here"), + ("Oh no! \x1b[1;35mRuntimeError\x1b[0m. Fix it.", "Oh no! RuntimeError. Fix it."), + ("Fancy: \x1b[48;5;95mBkgd\x1b[38;2;100;200;25mRGB\x1b[0m", "Fancy: BkgdRGB"), + # Other escape sequences are unaffected. + ("X\x1b[2J\x1b[1mBold\x1b[22m\x1b[=3hZ", "X\x1b[2JBold\x1b[=3hZ"), +]) +def test_without_color(text: str, result: str) -> None: + assert without_color(text) == result