I have a script that uses subprocess.check_output
of a command. There are instances where this command may fail and raise a subprocess.CalledProcessError
.
I am attempting to write a unit test (using pytest to run the test) for this function and test the exception condition.
pytest 3.1.2
Python 3.5.3
I wrote this small bit of code to explore with to no avail.
# 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())
When run with python mytest.py
the output is unzip
as expected since the unzip
command will fail and raise the error.
This is the code to test the function
# 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)
When run pytest test.py
the test fails with the error
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
If I comment except subprocess.CalledProcessError as cpe:
and uncomment #except Exception as cpe:
the test passes with the ouptut:
test.py
Type of error: <class 'subprocess.CalledProcessError'>
()
This seems to suggest to me that the error is thrown as specified in the mock and caught and the exception block is executed. The question is then, why doesn't it work when catching subprocess.CalledProcessError
.
This returns True
isinstance(subprocess.CalledProcessError(returncode=2,cmd=["bad"]), BaseException)
At this point I am guessing that there is something that I am missing in the whole process.
What am I missing?