首页 > 解决方案 > 使用来自通用测试功能的 pytest 夹具

问题描述

我有一些unittest基于代码的代码,目前看起来像这样

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调用被测“主”程序并手动捕获其标准输出。

我正在将此项目转换为pytest,但最后一块已经突破了我对 pytest 固定装置的理解的极限。

我知道 pytest 完全支持捕获 stdout/stderr,我想利用它。

问题是,他们的示例在测试功能级别上工作:

def test_myoutput(capfd):
    do_something
    captured = capsys.readouterr()
    assert captured.out == "hello\n"
    assert captured.err == "world\n"

在我的情况下,run_prog使用了 42 次,所以我尝试使用从 - 开始的夹具run_prog- 理想情况下,调用函数不需要打扰capsys/ capfd

有没有办法从我的run_prog助手“调用”夹具?还是我需要添加capfd到所有 42 个测试并将其传递给run_prog

标签: pythonpytest

解决方案


您可以定义一个 autouse 固定装置,它将CaptureFixture对象(由capsys固定装置返回)存储为实例属性:

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'

每次测试都会重新运行夹具,TestMain.inject_capsys以保证测试隔离(不会test_one泄漏任何输出test_two等)。


推荐阅读