24

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.

Timothée Jeannin
  • 9,652
  • 2
  • 56
  • 65
  • 1
    seems related [bug#17457](https://bugs.python.org/issue17457) which was fixed in python 3.4. which version of python you are using? – skadya Dec 29 '18 at 07:03

4 Answers4

9

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.

SimonF
  • 1,855
  • 10
  • 23
0

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

methane
  • 469
  • 3
  • 5
  • 11
0

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'))
Gabriel Devillers
  • 3,155
  • 2
  • 30
  • 53
-2

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.

Aleksandr Borisov
  • 2,136
  • 1
  • 13
  • 14