I have some unittest
-based code that currently looks like this :
class TestMain(TestCase):
def run_prog(self, args):
with TemporaryFile() as stdout:
old_stdout = sys.stdout
try:
main.main()
stdout.seek(0)
stdout_data = stdout.read()
finally:
sys.stdout = old_stdout
return stdout_data
def test_one(self):
out = self.run_prog(...)
def test_two(self):
out = self.run_prog(...)
def test_three(self):
out = self.run_prog(...)
run_prog
invokes the "main" program under test and manually captures its stdout.
I'm in the process of converting this project to pytest
, but this last piece has pushed the limits of my understanding of pytest fixtures.
I understand that pytest has full support for capturing stdout/stderr and I would like to leverage this.
The problem is, their examples work on a test-function level:
def test_myoutput(capfd):
do_something
captured = capsys.readouterr()
assert captured.out == "hello\n"
assert captured.err == "world\n"
In my case, run_prog
is used 42 times, so I'm trying to use the fixture starting at run_prog
-- the calling functions ideally don't need to bother with capsys
/ capfd
.
Is there a way to "invoke" the fixture from my run_prog
helper? Or do I need to add capfd
to all 42 tests and pass it to run_prog
?
You can define an autouse fixture that will store the CaptureFixture
object (returned by the capsys
fixture) as an instance property:
class TestMain(TestCase):
@pytest.fixture(autouse=True)
def inject_capsys(self, capsys):
self._capsys = capsys
def run_prog(self, args):
main.main()
return self._capsys.out
def test_out(self):
assert self.run_prog('spam') == 'eggs'
The TestMain.inject_capsys
fixture will be rerun for each test, guaranteeing the test isolation (no output from test_one
will be leaked in test_two
etc).
Here's a slight variation on hoefling's answer that gives a little more control over the scope of the capsys
fixture.
It uses request.getfixturevalue()
to retrieve the fixture at function invocation time:
import pytest
import sys
class TestMain:
@pytest.fixture(autouse=True)
def inject_request(self, request):
self.request = request
def run_prog(self, message):
capfd = self.request.getfixturevalue('capfd')
sys.stdout.write(message)
captured = capfd.readouterr()
assert captured.out == message
def test_one(self):
self.run_prog("Hello world!")
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.