1

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?

4
  • Meaning you are importing the .py file you run in a unit test? Commented Jul 11, 2018 at 7:41
  • Mock out the external task and pass it as a parameter Commented Jul 11, 2018 at 7:47
  • Hmm. Haven't looked at Mock yet - probably should if I am going to do some proper unit testing. Commented Jul 11, 2018 at 8:09
  • 1
    You shouldn't have conditional test code mixed with production code. Commented Jul 11, 2018 at 8:10

2 Answers 2

7

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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.

2 Comments

This was along the lines of what I was thinking. DI was wondering whether unittest set any itself that I could query?
@Chris: As far as I know pyunit itself doesn't change any environment variables. Check out this answer for some other helpful solutions?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.