Timothée Jeannin
Timothée Jeannin

Reputation: 9912

Recursive unittest discovery with python3 and without __init__.py files

I have project with the following directory structure:

.
├── requirements.txt
├── main.py
├── tests
    ├── unit
    │   └── test_thing1.py
    │   └── test_thing2.py
    └── integration
        └── test_integration_thing1.py
        └── test_integration_thing2.py

I want to run all tests with one command. If I do python -m unittest discover, no tests are executed.

I found this question that suggest adding a __init__.py file to make packages out of the unit and integration folders. The solution works, and all tests are running this way.

But since I'm using python3 and __init__.py files are not required with implicit namespace packages, I was wondering if there was a way to make this works without those __init__.py files.

Upvotes: 26

Views: 3303

Answers (4)

Gabriel Devillers
Gabriel Devillers

Reputation: 4002

I do not see the point of forcing the creation of __init__.py in each subdirectory, at least in my case: I am testing a Python wrapper of C++ code, so I am not testing a Python module that I have implemented. Also there is a risk that I will forget to create some __init__.py files which would lead to silently skipped tests.

So here is a solution to not have to create __init__.py in each subdirectory:

import glob
import os
import unittest

def test_suite_from_recursive_discover(pattern):
    test_files = glob.glob('**/{}'.format(pattern), recursive=True)
    test_dirs = list(set(([os.path.dirname(os.path.abspath(test_file)) for test_file in test_files])))

    suites = [unittest.TestLoader().discover(start_dir=d, pattern=pattern) for d in test_dirs]
    suite = unittest.TestSuite(suites)
    return suite

if __name__ == "__main__":
    unittest.TextTestRunner().run(test_suite_from_recursive_discover('test*.py'))

Upvotes: 0

methane
methane

Reputation: 479

Note that namespace package is regular package. You must not expect namespace package is treated same to regular package.

Read this article too. https://dev.to/methane/don-t-omit-init-py-3hga

Upvotes: 0

SimonF
SimonF

Reputation: 1885

I looked into it, and think its most likely a bug.

So I created a python bug report and a PR which fixes the issue for me.

Clone it and see if it works for you as well, with the fix the best way of running discover was python -m unittest discover -s tests. Otherwise it will look in for example virtual environments that are below the top dir.

Upvotes: 10

Aleksandr Borisov
Aleksandr Borisov

Reputation: 2212

Use pytest. It does discover tests in folders.

In your case you just need to install in via pip (pip install pytest) and then run in your root folder pytest tests.

Upvotes: -3

Related Questions