My current script calls an external script to perform some task. I want to check the code up to that point in a unittest, but not actually run the external script. Is there some way I can tell the script to effectively skip the following block IF the code is being run as part of a unit test?
-
Meaning you are importing the .py file you run in a unit test? – Mathieu Jul 11 '18 at 07:41
-
Mock out the external task and pass it as a parameter – Peter Wood Jul 11 '18 at 07:47
-
Hmm. Haven't looked at Mock yet - probably should if I am going to do some proper unit testing. – Chris Jul 11 '18 at 08:09
-
1You shouldn't have conditional test code mixed with production code. – Peter Wood Jul 11 '18 at 08:10
2 Answers
The unittest
package has extensive support for "mocking" functions and methods. Encapsulate the call to an external program in a simple function that your unit tests can override ("mock out") without modifying the structure of your program. Example:
Here is part of your program, in the module realcode.py
def internal_function_calling_exec(arg1):
"""The real thing"""
print("I am executing an external program")
def bigger_function_being_tested(arg1, arg2):
"""
A complex function with one or more calls to `internal_function_calling_exec`
"""
print("I will now call `internal_function_calling_exec()`")
internal_function_calling_exec(42)
Your unit test can then look like this:
import unittest
from unittest.mock import patch
import realcode
class MyTest(unittest.TestCase):
@patch("realcode.internal_function_calling_exec")
def test_something(self, mocked_func):
realcode.bigger_function_being_tested(1, 2)
mocked_func.assert_called_with(42)
This will never call the original internal_function_calling_exec()
. Instead, this will trigger a call to the mock object; your test can then query the object to confirm that it was called properly.
There are ways to mock class methods etc., so you could mock subprocess.call
instead, for example. But I think the above is the better pattern.

- 48,685
- 16
- 101
- 161
One possible approach is to set an environment variable in the unit test, and check for that environment variable in the script being tested.
For example, in unittest.py
:
os.environ["testing"] = "1"
And in script-to-be-tested.py
:
testing = os.environ["testing"]
... do stuff based on the testing variable
Since script-to-be-tested.py
will be called from unittest.py
, it should inherit the environment variables.
Possibly not the cleanest solution, but it should work.

- 73
- 7
-
This was along the lines of what I was thinking. DI was wondering whether unittest set any itself that I could query? – Chris Jul 11 '18 at 08:09
-
@Chris: As far as I know pyunit itself doesn't change any environment variables. Check out [this answer](https://stackoverflow.com/a/25025987/4287999) for some other helpful solutions? – populationzero Jul 11 '18 at 10:14