如何对子进程进行单元测试.CalledProcessError
我有一个使用命令subprocess.check_output
的脚本。有些情况下,这个命令可能会失败并引发subprocess.CalledProcessError
。如何对子进程进行单元测试.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: catching classes that do not inherit from BaseException is not allowed
如果我评论except subprocess.CalledProcessError as cpe:
并取消#except Exception as cpe:
测试通过与ouptut:
test.py
Type of error: <class 'subprocess.CalledProcessError'>
()
这似乎是建议让我明白错误是按照模拟中指定的方式抛出,并捕获异常块并执行。那么问题是,为什么在捕获subprocess.CalledProcessError
时不起作用。
这将返回True
isinstance(subprocess.CalledProcessError(returncode=2,cmd=["bad"]), BaseException)
在这一点上我猜,有我在整个过程中我失去了一些东西。
我错过了什么?
我认为你正在修补错误的路径。
@mock.patch('mytest.subprocess', autospec=True)
该路径应该是被测模块的路径而不是测试本身。我认为正在发生的是test.py命名空间中的模拟子进程,所以当您将side_effect设置为subprocess.CalledProcessError
时,您将其设置为模拟。您可以在设置后记录side_effect来验证这一点。