我有一个使用subprocess.check_output
命令的脚本。在某些情况下,此命令可能会失败并引发subprocess.CalledProcessError
。
我正在尝试为此函数编写一个单元测试(使用pytest来运行测试)并测试异常条件。
pytest 3.1.2
Python 3.5.3
我写了一小段代码来探索无济于事。
# mytest.py
import subprocess
def test_sub():
try:
command_output = subprocess.check_output("unzip x".split())
# unzip x is used to raise the exception when running with python
# but would be replaced by proper command that may fail
output = command_output
except subprocess.CalledProcessError as cpe:
#except Exception as cpe:
print("\nType of error:", type(cpe))
print(cpe.args)
output = "unzip"
return output
if __name__ == '__main__':
print(test_sub())
当使用python mytest.py
运行时,输出为unzip
,因为unzip
命令将失败并引发错误。
这是测试函数的代码
# test.py
import unittest
import unittest.mock as mock
from mytest import test_sub
import subprocess
class SubErrorTest(unittest.TestCase):
@mock.patch('mytest.subprocess', autospec=True)
def test_subprocess_error_thrown(self, mock_subprocess):
mock_subprocess.check_output.side_effect = subprocess.CalledProcessError(returncode=2,cmd=["bad"])
output = test_sub()
self.assertEqual("unzip", output)
运行pytest test.py
时,测试失败并显示错误
output = test_sub() #error thrown from here in test
test.py:
def test_sub(): try: command_output = subprocess.check_output("unzip x".split()) output = command_output except subprocess.CalledProcessError as cpe: #error is indicated here
E TypeError:不允许捕获不从BaseException继承的类
如果我发表评论except subprocess.CalledProcessError as cpe:
并取消注释#except Exception as cpe:
,则测试会通过ouptut传递:
test.py
错误类型:< class' subprocess.CalledProcessError'>
()
这似乎告诉我,错误是在mock和catch中指定的,并且执行了异常块。那么问题是,为什么在捕捉subprocess.CalledProcessError
时它不起作用。
这会返回True
isinstance(subprocess.CalledProcessError(returncode=2,cmd=["bad"]), BaseException)
此时我猜测在整个过程中我遗漏了一些东西。
我错过了什么?
答案 0 :(得分:1)
我认为你正在修补错误的道路。
@mock.patch('mytest.subprocess', autospec=True)
路径应该是被测模块的路径而不是测试本身。我认为正在发生的是你在test.py命名空间中的模拟子进程,所以当你将side_effect设置为subprocess.CalledProcessError
时,你将它设置为模拟。您可以在设置side_effect后记录它来验证这一点。