使用pytest capsys捕获print输出失败,遇AttributeError/TypeError错误求助
问题:使用pytest capsys fixture捕获print输出时遇属性错误和参数错误
问题场景
尝试用pytest的capsys fixture捕获代码中print语句的输出,但遇到两类错误:
- 通过自动注入的fixture给测试类实例绑定
capsys时,报AttributeError: 'TestCoffeeMachine' object has no attribute 'capsys' - 直接在测试方法中传入
capsys参数时,报TypeError: test_cost_calculation() missing 1 required positional argument: 'capsys'
相关代码
导入与测试类定义
import pytest import unittest from CoffeeMachine import CoffeeMachine class TestCoffeeMachine(unittest.TestCase): def setUp(self): self.coffee_1 = CoffeeMachine(200, 300, 20, 0)
自动注入的Fixture尝试
@pytest.fixture(autouse=True) def _pass_fixtures(self, capsys): self.capfd = capsys
第一种测试方法(报错)
def test_cost_calculation(self): return_value = self.coffee_1.cost_calculation(CoffeeMachine.coffee_type[0], 10.50) captured = self.capsys.readouterr() self.assertEqual("Total Money Loaded is: 10.5", captured.out) self.assertEqual(return_value[0], True) self.assertEqual(return_value[1], 4.95)
第二种测试方法(报错)
def test_cost_calculation(self, capsys): return_value = self.coffee_1.cost_calculation(CoffeeMachine.coffee_type[0], 10.50) captured = capsys.readouterr() self.assertEqual("Total Money Loaded is: 10.5", captured.out) self.assertEqual(return_value[0], True) self.assertEqual(return_value[1], 4.95)
错误信息
第一种方法的错误
captured = self.capsys.readouterr() AttributeError: 'TestCoffeeMachine' object has no attribute 'capsys'
第二种方法的错误
Traceback (most recent call last): TypeError: test_cost_calculation() missing 1 required positional argument: 'capsys'
问题原因与解决方案
核心原因
- 第一种方法中,fixture里将
capsys赋值给了self.capfd,但测试方法中访问的是self.capsys,变量名不匹配;同时unittest测试类的实例在pytest fixture中的注入逻辑需要调整。 - 第二种方法中,unittest的测试方法不支持直接接收pytest fixture作为参数,因为unittest框架调用测试方法时不会自动注入pytest的fixture参数。
解决方案1:改用纯pytest测试风格(推荐)
放弃继承unittest.TestCase,使用pytest原生的测试类写法,这样可以直接使用fixture参数:
import pytest from CoffeeMachine import CoffeeMachine class TestCoffeeMachine: def setup_method(self): # 替代unittest的setUp self.coffee_1 = CoffeeMachine(200, 300, 20, 0) def test_cost_calculation(self, capsys): return_value = self.coffee_1.cost_calculation(CoffeeMachine.coffee_type[0], 10.50) captured = capsys.readouterr() # 注意strip()处理输出中的换行符 assert "Total Money Loaded is: 10.5" == captured.out.strip() assert return_value[0] is True assert return_value[1] == 4.95
解决方案2:保留unittest.TestCase的兼容写法
如果需要继续使用unittest测试类,可将fixture作用域设为类级别,并绑定到类属性:
import pytest import unittest from CoffeeMachine import CoffeeMachine @pytest.fixture(autouse=True, scope='class') def _pass_fixtures(cls, capsys): # cls指向测试类本身 cls.capsys = capsys class TestCoffeeMachine(unittest.TestCase): def setUp(self): self.coffee_1 = CoffeeMachine(200, 300, 20, 0) def test_cost_calculation(self): return_value = self.coffee_1.cost_calculation(CoffeeMachine.coffee_type[0], 10.50) captured = self.capsys.readouterr() self.assertEqual("Total Money Loaded is: 10.5", captured.out.strip()) self.assertEqual(return_value[0], True) self.assertEqual(return_value[1], 4.95)
内容的提问来源于stack exchange,提问作者Nirmalgautham
相关产品推荐
相关产品推荐

