pytest-dev / pytest-dev/pytest

ASCII color chars leaking into xml report file when using verbose flag

Open
#12,365 7 comments 2 reactions 1 assignee View on GitHub

@leonarduschen is already working on this.

Since Dec 1, 2024.

plugin: junitxml type: bug
Dominant language
Python
Stars
14.5k
Forks
3.4k
Avg merge
2d 9h
Merged PRs (30d)
35

Description

Problem description

A bug was noticed when displaying failing tests on CI with the -vv flag: the ASCII color characters are being printed inside the detailed diff.

image

The displayed output comes directly from xml file (generated with the --junitxml flag), which in fact carries the undesired characters as shown in the minimal example below. This happens only when pygments is also installed, with both -v and -vv flags.

This undesired behavior was noticed in all 8.* versions but not in 7.4, so it probably was introduced in 8.0 together with the improved verbose diffs change (changelog).

Output of pip list
Package        Version
-------------- -------
exceptiongroup 1.2.1
iniconfig      2.0.0
packaging      24.0
pip            21.2.4
pluggy         1.5.0
Pygments       2.18.0
pytest         8.2.1
setuptools     58.1.0
tomli          2.0.1
pytest and operating system versions
  • SO (uname -a): Linux FLDEVWSV032 6.5.0-35-generic #35~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue May 7 09:00:52 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
  • Python: 3.10.2
  • pytest: 8.0.0, 8.1.0, 8.2.1
Minimal example

test_foo.py:

def test_foo() -> None:
    assert [1,2,3] == [3,2,1]

Running it:

image

foo.xml:

<?xml version="1.0" encoding="utf-8"?>
<testsuites>
	<testsuite name="pytest" errors="0" failures="1" skipped="0" tests="1" time="0.082" timestamp="2024-05-24T14:19:42.491202" hostname="FLDEVWSV032">
		<testcase classname="test_foo" name="test_foo" time="0.055">
			<failure message="assert [1, 2, 3] == [3, 2, 1]&#10;  &#10;  At index 0 diff: #x1B[0m#x1B[94m1#x1B[39;49;00m#x1B[90m#x1B[39;49;00m != #x1B[0m#x1B[94m3#x1B[39;49;00m#x1B[90m#x1B[39;49;00m&#10;  &#10;  Full diff:&#10;  #x1B[0m#x1B[90m #x1B[39;49;00m [#x1B[90m#x1B[39;49;00m&#10;  #x1B[92m+     1,#x1B[39;49;00m#x1B[90m#x1B[39;49;00m&#10;  #x1B[92m+     2,#x1B[39;49;00m#x1B[90m#x1B[39;49;00m&#10;  #x1B[90m #x1B[39;49;00m     3,#x1B[90m#x1B[39;49;00m&#10;  #x1B[91m-     2,#x1B[39;49;00m#x1B[90m#x1B[39;49;00m&#10;  #x1B[91m-     1,#x1B[39;49;00m#x1B[90m#x1B[39;49;00m&#10;  #x1B[90m #x1B[39;49;00m ]#x1B[90m#x1B[39;49;00m">def test_foo() -&gt; None:
&gt;       assert [1,2,3] == [3,2,1]
E       assert [1, 2, 3] == [3, 2, 1]
E         
E         At index 0 diff: #x1B[0m#x1B[94m1#x1B[39;49;00m#x1B[90m#x1B[39;49;00m != #x1B[0m#x1B[94m3#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E         
E         Full diff:
E         #x1B[0m#x1B[90m #x1B[39;49;00m [#x1B[90m#x1B[39;49;00m
E         #x1B[92m+     1,#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E         #x1B[92m+     2,#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E         #x1B[90m #x1B[39;49;00m     3,#x1B[90m#x1B[39;49;00m
E         #x1B[91m-     2,#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E         #x1B[91m-     1,#x1B[39;49;00m#x1B[90m#x1B[39;49;00m
E         #x1B[90m #x1B[39;49;00m ]#x1B[90m#x1B[39;49;00m

test_foo.py:2: AssertionError</failure>
		</testcase>
	</testsuite>
</testsuites

For comparison, without having pygments installed the xml looks like this:

<?xml version="1.0" encoding="utf-8"?>
<testsuites>
	<testsuite name="pytest" errors="0" failures="1" skipped="0" tests="1" time="0.028" timestamp="2024-05-24T14:22:36.093080" hostname="FLDEVWSV032">
		<testcase classname="test_foo" name="test_foo" time="0.001">
			<failure message="assert [1, 2, 3] == [3, 2, 1]&#10;  &#10;  At index 0 diff: 1 != 3&#10;  &#10;  Full diff:&#10;    [&#10;  +     1,&#10;  +     2,&#10;        3,&#10;  -     2,&#10;  -     1,&#10;    ]">def test_foo() -&gt; None:
&gt;       assert [1,2,3] == [3,2,1]
E       assert [1, 2, 3] == [3, 2, 1]
E         
E         At index 0 diff: 1 != 3
E         
E         Full diff:
E           [
E         +     1,
E         +     2,
E               3,
E         -     2,
E         -     1,
E           ]

test_foo.py:2: AssertionError</failure>
		</testcase>
	</testsuite>
</testsuites>

If confirmed, I'd be happy to submit a PR fixing this.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.