4

In Python's typing module, they have a really helpful constant that's True when type checking, but False otherwise. This means, for example, that you can import classes dynamically if TYPE_CHECKING evaluates to True.

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from module import Class

It would be super useful if unittest had something similar. I can see in the __init__.py file, there exists a variable defined as __unittest = True:

__all__ = ['TestResult', 'TestCase', 'TestSuite',
           'TextTestRunner', 'TestLoader', 'FunctionTestCase', 'main',
           'defaultTestLoader', 'SkipTest', 'skip', 'skipIf', 'skipUnless',
           'expectedFailure', 'TextTestResult', 'installHandler',

__unittest = True

Is there any way to use __unittest in the same way as TYPE_CHECKING from typing?

Reason for this: I have some user examples in my code-base which can be run and plot graphs. I would like to run these examples as part of the unit tests to see when they break and need fixing. I need a dynamic way of stopping the examples trying to open a plotting window and blocking the unit tests, however.

Any help very much appreciated!

henryJack
  • 4,220
  • 2
  • 20
  • 24
  • What exactly do you want to check? That `unittest` has been imported or something else? – Chris_Rands Sep 11 '17 at 14:13
  • Just suggesting an extremely simple approach: adding a `**kwargs` to all the methods that need to change their behavior during unit test (and this is already a bad way to do unit testing, since you are changing in some way functionalities in your code - e.g. the plot you are doing are not compatible anymore with the data representation in your function), so that in the tests you add to the call the argument `unittest=True` may be a good solution for you? – Matteo Ragni Sep 11 '17 at 14:18
  • To check what you are asking (that seems if `unittest` has been imported) you can check if the key `"unittest"` is in `sys.modules` – Matteo Ragni Sep 11 '17 at 14:21
  • Yes @MatteoRagni! You can use `'unittest' in sys.modules` to determine whether a unittest has been imported. – henryJack Sep 11 '17 at 14:33
  • If you make this into an answer I will accept it and shower you in glory – henryJack Sep 11 '17 at 14:35
  • Oh thank you! I'll do it :) – Matteo Ragni Sep 11 '17 at 14:47
  • Actually it is better to accept @mseifert answer. It is way better than mine. But it is your call. – Matteo Ragni Sep 12 '17 at 11:56

3 Answers3

3

Reason for this: I have some user examples in my code-base which can be run and plot graphs. I would like to run these examples as part of the unit tests to see when they break and need fixing. I need a dynamic way of stopping the examples trying to open a plotting window and blocking the unit tests, however.

The best way to achieve that is by mocking. This will replace functionality with some "mocked" functionality. This is generally used for "plotting code" or code that makes "requests" and such like. Because you can disable certain functionality that you don't need/want while testing.

It also avoids cluttering the production code with unittest-related stuff. For type checking this is needed because that happens at runtime but unittests generally don't happen at runtime or should have any effect at runtime.

You haven't said what kind of plotting you used but in case it's matplotlib they do have some documentation to facilitate testing or see this QA.

MSeifert
  • 145,886
  • 38
  • 333
  • 352
1

To check what you are asking (that seems if unittest has been imported) you can check if the key "unittest" is in sys.modules

import sys
import unittest

if "unittest" in sys.modules:
    print("I'm unittest-ing")
Matteo Ragni
  • 2,837
  • 1
  • 20
  • 34
0

For situations like this, I'd suggest using command-line arguments to control whether code is run or not.

In this case, you could have a simple module that defines a value like is_unit_testing based on whether the -unittest argument has been passed to the python process.

To handle commandline arguments, please look here: How do I access command line arguments in Python?

import sys
# sys.argv is a list of all commandline arguments you can check through
command_line_arguments_list = sys.argv # e.g. ["arg1", "arg2", "-unittest"]
is_unit_testing = "-unittest" in command_line_arguments_list

You can then pass the arguments as you'd expect via command-line:

python myModule.py  arg1  arg2  -unittest

This works well for anything like this where you want multiple 'builds' from the same code base. Such as having a 'no database'/'no gui' mode etc.