-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
When executing pytester.runpytest in an environment containing a pytest plugin that modifies the output, the result is that vanilla pytester tries and fails to parse the modified output, yielding failed assert_outcomes.
For example, the following test suite, in an environment with pytest-pretty installed:
import pytest
@pytest.mark.parametrize('params', [[], ['-p pretty'], ['-p no:pretty']])
def test_rec(testdir, params):
testdir.makepyfile(
"""
import pytest
def test_noop():
assert True is True
"""
)
result = testdir.runpytest(*params)
result.assert_outcomes(passed=1)
if __name__ == '__main__':
print('default')
pytest.main(plugins=['pytester'])
print('-p pretty')
pytest.main(plugins=['pytester', 'pretty'])
print('-p no:pretty')
pytest.main(['-p', 'no:pretty'], plugins=['pytester'])succeeds only when the internal testsuite is passed -p no:pretty, regardless of the flags with which pytest.main is invoked
This is an issue in certain contexts, eg kiwicom/pytest-recording#169 In that case, packaging guidelines for Arch Linux mandate running the builders without venvs. And while guidelines there mandate building packages in a chroot with only the dependencies the package needs, it is common for users to build packages outside such a chroot, and so they pick up such plugins.
One additional factor here is that diagnosing this incompatibility is difficult -- none of the plugins involved advertise this incompatibility, and the code itself doesn't suggest anything might be wrong.
Several mitigations suggest themselves, in increasing order of complexity and safety:
- Explicitly specifying the plugins to use -- this is what Gentoo does, and
I'm currently writing up a proposalhave proposed that Arch should do the same. This was enabled by Option to disable plugin autoload entirely #3784 - Document prominently in the
pytesterdocumentation that it is incompatible with any plugin that modifiespytest's output - Standardize an interface for overriding the output to ensure that any fixture that calls
runpytestwill have a coherent set of bindings. eg enable explicitly setting which reporterpytestuses for its reporting, and then haverunpytestexplicitly but overridably set the reporter (so it's always parsing the report with the reporter it was expecting to be using) - Give
pytesta way to emit a machine-readable version of the log, so it's not dependent on its output not being modified (eg have a flag for machine-readable output, and use that withrunpytestunder the hood)
pytest version: 8.3.5