How do I run all Python unit tests in a directory?
With Python 2.7 and higher you don't have to write new code or use third-party tools to do this; recursive test execution via the command line is built-in. Put an __init__.py
in your test directory and:
python -m unittest discover <test_directory>
# or
python -m unittest discover -s <directory> -p '*_test.py'
You can read more in the python 2.7
or python 3.x unittest documentation.
Update for 2021:
Lots of modern python projects use more advanced tools like pytest. For example, pull down matplotlib or scikit-learn and you will see they both use it.
It is important to know about these newer tools because when you have more than 7000 tests you need:
- more advanced ways to summarize what passes, skipped, warnings, errors
- easy ways to see how they failed
- percent complete as it is running
- total run time
- ways to generate a test report
- etc etc
Running unittest with typical test directory structure
The best solution in my opinion is to use the unittest
command line interface which will add the directory to the sys.path
so you don't have to (done in the TestLoader
class).
For example for a directory structure like this:
new_project
├── antigravity.py
└── test_antigravity.py
You can just run:
$ cd new_project
$ python -m unittest test_antigravity
For a directory structure like yours:
new_project
├── antigravity
│ ├── __init__.py # make it a package
│ └── antigravity.py
└── test
├── __init__.py # also make test a package
└── test_antigravity.py
And in the test modules inside the test
package, you can import the antigravity
package and its modules as usual:
# import the package
import antigravity
# import the antigravity module
from antigravity import antigravity
# or an object inside the antigravity module
from antigravity.antigravity import my_object
Running a single test module:
To run a single test module, in this case test_antigravity.py
:
$ cd new_project
$ python -m unittest test.test_antigravity
Just reference the test module the same way you import it.
Running a single test case or test method:
Also you can run a single TestCase
or a single test method:
$ python -m unittest test.test_antigravity.GravityTestCase
$ python -m unittest test.test_antigravity.GravityTestCase.test_method
Running all tests:
You can also use test discovery which will discover and run all the tests for you, they must be modules or packages named test*.py
(can be changed with the -p, --pattern
flag):
$ cd new_project
$ python -m unittest discover
$ # Also works without discover for Python 3
$ # as suggested by @Burrito in the comments
$ python -m unittest
This will run all the test*.py
modules inside the test
package.
Run all tests from subdirectories in Python
So I had to do my own workaround but at least I can get them all to run with the above file structure. It requires that I reinstantiate the TestLoader and the TestSuite each time I give it a new file path, so first I need to collect all relevant file paths in the unittest directory.
import os
import unittest
import traceback
class UnitTestLauncher(object):
def runTests(self):
#logging.INFO("Running unit tests...")
lsPaths = []
#Find all relevant subdirectories that contain unit tests
#Exclude 'unittest' directory, but include subdirectories, with code `path != 'unittest'`
for path,subdirs,files in os.walk('unittest'):
if "pycache" not in path and path != 'unittest':
lsPaths.append(path)
#loop through subdirectories and run individually
for path in lsPaths:
loader = unittest.TestLoader()
suite = unittest.TestSuite()
suite = loader.discover(path)
unittest.TextTestRunner().run(suite)
This solution is not perfect and each different directory comes out as a line of output so you have to look through each line manually for failed tests.
Is it possible to run all unit test?
You could create a TestSuite
and run all your tests in it's if __name__ == '__main__'
block:
import unittest
def create_suite():
test_suite = unittest.TestSuite()
test_suite.addTest(fooTest())
test_suite.addTest(barTest())
return test_suite
if __name__ == '__main__':
suite = create_suite()
runner=unittest.TextTestRunner()
runner.run(suite)
If you do not want to create the test cases manually look at this quesiton/answer, which basically creates the test cases dynamically, or use some of the features of the unittest
module like test discovery feature and command line options ..
Run python unittest in context of specific directory
There is a os
function to change the directory, try adding os.chdir('src')
to your test.
import unittest
import os
from src.main import get_cwd
class TestMain(unittest.TestCase):
def test_get_cwd(self):
os.chdir('src')
print('testing get_cwd()')
current_dir = get_cwd()
self.assertIsNotNone(current_dir)
self.assertEqual(current_dir, 'src')
Related Topics
Why the Global Interpreter Lock
Strange Behavior of Lists in Python
How to Get Flask to Run on Port 80
What Is the _Dict_._Dict_ Attribute of a Python Class
Programmatically Searching Google in Python Using Custom Search
Getting One Value from a Tuple
E731 Do Not Assign a Lambda Expression, Use a Def
Parsing a JSON String Which Was Loaded from a CSV Using Pandas
Valueerror: Numpy.Dtype Has the Wrong Size, Try Recompiling
What Is the Most Pythonic Way to Check If an Object Is a Number
Which Is Faster in Python: X**.5 or Math.Sqrt(X)
Differencebetween Pylab and Pyplot
Can Existing Virtualenv Be Upgraded Gracefully
Dummy Variables When Not All Categories Are Present
Convert Floating Point Number to a Certain Precision, and Then Copy to String