I am having trouble capturing the stderr and stdout for pytest when I am using a fixture. It works okay if the test is just directly called. The reason I want it in a fixture is because I need to call it multiple times based on a file that I will be reading.
Here's a working example, lets say this content is in ' test_something.py
':
import sys
import pytest
def printing():
print("testing only")
print("erroring", file=sys.stderr)
sys.exit(1)
def test_print(capsys):
with pytest.raises(SystemExit) as excinfo:
printing()
stdout, errout = capsys.readouterr()
assert stdout == "testing only\n"
assert errout == "erroring\n"
assert excinfo.type == SystemExit
class TestPrint():
@pytest.fixture(name="getResponse", scope="class", params=[0])
def getResponse(self, request):
with pytest.raises(SystemExit) as excinfo:
printing()
return excinfo
def test_print_class(self, getResponse, capsys):
excinfo = getResponse
stdout, errout = capsys.readouterr()
assert stdout == "testing only\n"
assert errout == "erroring\n"
assert excinfo.type == SystemExit
if you run 'pytest -v' for the above, you get:
tests/test_something.py::test_print PASSED [ 50%]
tests/test_something.py::TestPrint::test_print_class[0] FAILED [100%]
The 'test_print_class' reads empty stdout and stderr, why is that? How can I make it work? Thanks for the help!
The main problem is that you cannot easily mix function and class scope fixtures. A function scope fixture would work:
class TestPrint:
@pytest.fixture(name="getResponse")
def getResponse(self):
with pytest.raises(SystemExit):
printing()
def test_print_class(self, capsys, getResponse):
stdout, errout = capsys.readouterr()
assert stdout == "testing only\n"
assert errout == "erroring\n"
The class scoped fixture is run before the function scoped capsys
is invoked, so it will not the catch stdout/stderr from the fixture.
The problem is also shown if you try to add capsys
to the fixture itself. In this case pytest will complain:
ScopeMismatch: You tried to access the 'function' scoped fixture 'capsys' with a 'class' scoped request object, involved factories
Note that I also removed the return excinfo
part, as this will never be reached - the context manager scope is left as soon as the exception occurs. The check is also unneeded, because it is already done in the fixture.
So the answer is: it is not possible to achieve what you want this way. Fixtures are there to provide setup/teardown and data for the test, not part of the test itself.
I'm not sure about your actual use case, depending on that you can
printing
for every test, which is what I understood from your question)printing
exception handling (as you do in the first test), and just use it in the fixture to setup it once for all other tests, if that is what you need
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.