Python 3.x 尝试使用pytest和capsys访问stdout时出现ValueError

Python 3.x 尝试使用pytest和capsys访问stdout时出现ValueError,python-3.x,mocking,pytest,stdout,valueerror,Python 3.x,Mocking,Pytest,Stdout,Valueerror,尝试在验证用户帐户的对象中测试本地方法的标准输出 例如, Foo类: def uuu init uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu self.bar=bar 如果是baz: self.something=self.load\u something() 其他: 打印('初始化错误') def load_某物(自身): 返回“” def make_子流程_调用(自): 返回'stdout','std

尝试在验证用户帐户的对象中测试本地方法的标准输出

例如,

Foo类:
def uuu init uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
self.bar=bar
如果是baz:
self.something=self.load\u something()
其他:
打印('初始化错误')
def load_某物(自身):
返回“”
def make_子流程_调用(自):
返回'stdout','stderr'
def确认(自我):
subprocess\u stdout,subprocess\u stderr=self.make\u subprocess\u call()
如果子流程不成功:
打印(“良好输出”)
其他:
打印('err output',subprocess\u stderr)
然后进行测试:

从Foo\u类文件导入Foo
导入模拟
导入pytest
@补丁('Foo_Class_File.Foo.load_something',返回值={'a':'b'})
@mock.patch('Foo_Class_File.Foo.make_subprocess_call',返回值=('more stdout','more stderr'))
def测试确认(测试目录、capsys):
test_foo=foo(testdir,True)
测试\u foo.确认\u某物()
out,err=capsys.readouterr()
assert out==“更多标准输出”
断言错误=='more\u stderr'
然后运行:

python3-m pytest test\u foo\u file.py
给出:

============================================================================== FAILURES ===============================================================================
_______________________________________________________________________ test_confirm_something ________________________________________________________________________

testdir = <MagicMock name='make_subprocess_call' id='140533346667632'>, capsys = <MagicMock name='load_something' id='140533346970400'>

    @mock.patch('Foo_Class_File.Foo.load_something', return_value = {'a': 'b'})
    @mock.patch('Foo_Class_File.Foo.make_subprocess_call', return_value=('more stdout', 'more_stderr'))
    def test_confirm_something(testdir, capsys):
        test_foo = Foo(testdir, True)
        test_foo.confirm_something()
>       out, err = capsys.readouterr()
E       ValueError: not enough values to unpack (expected 2, got 0)

blah.py:10: ValueError
------------------------------------------------------------------------ Captured stdout call -------------------------------------------------------------------------
good output
======================================================================= short test summary info =======================================================================
FAILED test_foo_file.py::test_confirm_something - ValueError: not enough values to unpack (expected 2, got 0)
========================================================================== 1 failed in 0.11s ==========================================================================
==========================================================================================================================================失败===============================================================================
_______________________________________________________________________测试确认某事________________________________________________________________________
testdir=,capsys=
@补丁('Foo_Class_File.Foo.load_something',返回值={'a':'b'})
@mock.patch('Foo_Class_File.Foo.make_subprocess_call',返回值=('more stdout','more stderr'))
def测试确认(测试目录、capsys):
test_foo=foo(testdir,True)
测试\u foo.确认\u某物()
>out,err=capsys.readouterr()
E ValueError:没有足够的值来解包(应为2,得到0)
blah.py:10:ValueError
------------------------------------------------------------------------捕获的stdout调用-------------------------------------------------------------------------
正品产出量
===================================================================================================================================================简短测试摘要信息=======================================================================
失败的test\u foo\u file.py::test\u confirm\u something-ValueError:没有足够的值来解包(预期为2,得到0)
================================================================================================================1在0.11秒内失败==========================================================================
我真的很困惑,因为上面说这是在抓取stdout

我认为这与实例化对象然后调用方法有关,因为如果只有对象,我可以用capsys捕获,但只要我尝试实例化它并调用方法,你在上面看到的就会发生什么。我在网上或文档中找不到类似的案例,不是因为缺乏尝试(或者可能是因为我的GoogleFoo现在很弱)


如果我做了一些愚蠢的事情,我向你道歉,但现在我担心我键盘的安全,我想我会伸出援手的。欢迎提供任何帮助/建议。您可以运行我发布的这个测试用例,它会给出与发布的相同的错误。

您的问题是您提供了补丁装饰程序,但没有向测试函数添加相应的参数。这是正确的:

@mock.patch('Foo\u Class\u File.Foo.load\u something',返回值={'a':'b'})
@mock.patch('Foo_Class_File.Foo.make_subprocess_call',返回值=('more stdout','more stderr'))
def test_confirm_something(mocked_调用、mocked_加载、testdir、capsys):#注意其他参数
test_foo=foo(testdir,True)
测试\u foo.确认\u某物()
out,err=capsys.readouterr()
assert out=='good output\n'
断言错误=“”
或者,或者:

@mock.patch('Foo\u Class\u File.Foo.load\u something')
@mock.patch('Foo\u Class\u File.Foo.make\u subprocess\u call')
def test_confirm_something(模拟调用、模拟加载、testdir、capsys):
mocked_call.return_value=('more stdout','more_stderr')
mocked_load.return_value={'a':'b'}
test_foo=foo(testdir,True)
...
代码中出现的情况是,fixture
testdir
capsys
被用作模拟参数(预期作为测试函数中的第一个参数),这导致两者都是模拟对象,而不是fixture

旁注:如果pytest在这种情况下给出一个警告,比如“您正在使用一个fixture名称作为修补对象的名称,可能您忘记添加修补对象参数了?”


请注意,我已将示例代码中的断言替换为使用您的代码实际传递的断言。

回想起来,我可能已经注意到testdir和capsys被分配了与装饰器相关的MagicMock类型。无论如何,感谢您的帮助和详细的解决方案:)。回想起来,一切似乎都更清楚了;)很高兴我能帮忙!事实上,同样有趣的是,我刚刚关闭了装饰程序并安装了mocker夹具,但非常感谢您帮助我理解pytest:)