There are several unit testing tools for Python. This documentation topic describes the basic unittest module. Other testing tools include py.test and nosetests. This python documentation about testing compares several of these tools without going into depth.
Asserting on Exceptions
You can test that a function throws an exception with the built-in unittest through two different methods.
This will run the code inside of the context manager and, if it succeeds, it will fail the test because the exception was not raised. If the code raises an exception of the correct type, the test will continue.
You can also get the content of the raised exception if you want to execute additional assertions against it.
By providing a callable function
The exception to check for must be the first parameter, and a callable function must be passed as the second parameter. Any other parameters specified will be passed directly to the function that is being called, allowing you to specify the parameters that trigger the exception.
Choosing Assertions Within Unittests
While Python has an assert statement, the Python unit testing framework has better assertions specialized for tests: they are more informative on failures, and do not depend on the execution's debug mode.
Perhaps the simplest assertion is assertTrue, which can be used like this:
This will run fine, but replacing the line above with
The assertTrue assertion is quite likely the most general assertion, as anything tested can be cast as some boolean condition, but often there are better alternatives. When testing for equality, as above, it is better to write
When the former fails, the message is
but when the latter fails, the message is
which is more informative (it actually evaluated the result of the left hand side).
You can find the list of assertions in the standard documentation. In general, it is a good idea to choose the assertion that is the most specifically fitting the condition. Thus, as shown above, for asserting that 1 + 1 == 2 it is better to use assertEqual than assertTrue. Similarly, for asserting that a is None, it is better to use assertIsNone than assertEqual.
Note also that the assertions have negative forms. Thus assertEqual has its negative counterpart assertNotEqual, and assertIsNone has its negative counterpart assertIsNotNone. Once again, using the negative counterparts when appropriate, will lead to clearer error messages.
Mocking functions with unittest.mock.create_autospec
One way to mock a function is to use the create_autospec function, which will mock out an object according to its specs. With functions, we can use this to ensure that they are called appropriately.
With a function multiply in custom_math.py:
And a function multiples_of in process_math.py:
We can test multiples_of alone by mocking out multiply. The below example uses the Python standard library unittest, but this can be used with other testing frameworks as well, like pytest or nose:
Test Setup and Teardown within a unittest.TestCase
Sometimes we want to prepare a context for each test to be run under. The setUp method is run prior to each test in the class. tearDown is run at the end of every test. These methods are optional. Remember that TestCases are often used in cooperative multiple inheritance so you should be careful to always call super in these methods so that base class's setUp and tearDown methods also get called. The base implementation of TestCase provides empty setUp and tearDown methods so that they can be called without raising exceptions:
Note that in python2.7+, there is also the addCleanup method that registers functions to be called after the test is run. In contrast to tearDown which only gets called if setUp succeeds, functions registered via addCleanup will be called even in the event of an unhandled exception in setUp. As a concrete example, this method can frequently be seen removing various mocks that were registered while the test was running:
Another benefit of registering cleanups this way is that it allows the programmer to put the cleanup code next to the setup code and it protects you in the event that a subclasser forgets to call super in tearDown.
Programs throw errors when for instance wrong input is given. Because of this, one needs to make sure that an error is thrown when actual wrong input is given. Because of that we need to check for an exact exception, for this example we will use the following exception:
This exception is raised when wrong input is given, in the following context where we always expect a number as text input.
To check whether an exception has been raised, we use assertRaises to check for that exception. assertRaises can be used in two ways:
Using the regular function call. The first argument takes the exception type, second a callable (usually a function) and the rest of arguments are passed to this callable.
Using a with clause, giving only the exception type to the function. This has as advantage that more code can be executed, but should be used with care since multiple functions can use the same exception which can be problematic. An example:
convert2number("not a number")
This first has been implemented in the following test case:
There also may be a need to check for an exception which should not have been thrown. However, a test will automatically fail when an exception is thrown and thus may not be necessary at all. Just to show the options, the second test method shows a case on how one can check for an exception not to be thrown. Basically, this is catching the exception and then failing the test using the fail method.
Unit tests with pytest
getting the tests ready:
Functions to test in docker_something/helpers.py:
The test imports test_docker.py:
mocking a file like object in test_docker.py:
Monkey patching with pytest in test_docker.py:
Example tests, must start with the prefix test_ in the test_docker.py file:
running the tests one at a time:
running all the tests in the tests folder:
This modified text is an extract of the original Stack Overflow Documentation created by following contributors and released under CC BY-SA 3.0