When is the best time to start unit testing in your Python project? My answer is before you writing the first line of code of this project. Unit testing is the fundamental of Test-driven development, which specifically improves the quality and design of your project.
In this post, I’m writing about how could you do unit testing in Python with the unittest
module.
Python 2 (starting on version 2.1) and Python 3 now both have unittest
in the standard library. The unittest
module provides the unit testing framework, and it’s based on JUnit
, which is a unit testing framework for Java.
What unittest can do
A few main features that unittest
can do are:
- Automatically run the tests (by
test runner
) - Create test cases (by
test case
) - Sharing of setup and shutdown code for tests (by
test fixture
) - Aggrate tests into collections (by
test suite
) - Independence of the tests from the reporting framework
How does unittest work
Suppose I’m working on a project called demo
, and it has a file structure as:
1 2 3 4 |
|
Note the ___init___.py
file can be empty. The purpose of having this file is for other files outside this directory can easily import the module demoDev.py
.
To create unit tests for this project, I’ll need continue the following steps.
1. Create the test file
There is no particular required folder structure that you need to keep your test files. The way I usually do is separating the tests from the project source files. So, I create a test
folder in the same level as dev
. All my tests will be put into this folder. Now the project’s structure looks like:
1 2 3 4 5 6 |
|
2. Use unittest module in your project
The test file need import the unittest
module.
1 2 3 |
|
3. Include your project modules in the test
Surely you’ll need include the source files of the modules that you want to test in your test file. If your tests are in the same folder of your module sources, you can simply use import SomeModule
to pull the modules in. When your tests stay out of the module sources, you’ll need do a little configurations in your test file.
I found the way to import your own modules to your tests can be different depending your development environment. For example, if you run your Python projects within some IDE, like PyCharm from JetBrains. The following way always work:
1 2 3 |
|
However if you run through command line python test/test_demoDev.py
, you might see errors complaining no module called dev
and thus the import fails.
What you can do to resolve this problem, is adding the path of your Python modules to the sys.path
.
1 2 3 4 5 6 7 8 9 10 |
|
4. Create a test case
A test case can be created with unittest TestCase class. The setUp()
and tearDown()
methods can be overridden to provide initialization and cleanup for the fixture. Each instance of the TestCase will only be used to run a single test method. Multiple test methods share the same text fixture, but the test fixture are created for each test method when they are executed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
The TestCase
class provides several assert methods to check for and report failures, such as assertEqual
, assertNotEqual
, assertTrue
. Here is the complete assert list that Python 3 provides.
5. Create more tests and a test suites
TestSuite
class represents an aggregation of individual test cases and test suites. The addTest
and addTests
methods are available to add tests to your TestSuite instances.
1 2 3 4 5 6 7 8 |
|
6. Run your unit tests!
The easiest way to run your unit tests is executing the unittest.main()
method in the test file.
1 2 3 4 |
|
Then by running command python test_demoDev.py
, the tests defined in test_demoDev.py
will start running.
Unit tests can run from command line, because unittest
module can be used from the command line to run tests from modules, classes or individual test methods.
1
|
|
You’ll see the testing result like:
1 2 3 4 5 6 7 |
|
Behind the tests running, there is the run
method provided by TestCase
and TestCaseSuite
classes. This run
method implements the function of running the test, collecting the result into the TestResult
object passed as result.
Here you go! Enjoy unit testing in Python!