`python -m unittest discover` does not discover tests
Asked Answered
F

4

66

Python's unittest discover does not find my tests!

I have been using nose to discover my unit tests and it is working fine. From the top level of my project, if I run nosetests I get:

Ran 31 tests in 0.390s

Now that Python 2.7 unittest has discovery, I have tried using

python -m unittest discover

but I get

Ran 0 tests in 0.000s

My directory structure is:

myproj/
    reporter/
    __init__.py
    report.py
    [other app modules]
        tests/
        __init__.py
        test-report.py
        [other test modules]

Do you have any ideas why unittest's discovery algorithm can't find the tests?

I'm using Python 2.7.1 and nose 1.0.0 on Windows 7.

Ferric answered 23/2, 2011 at 9:20 Comment(2)
I just found that the tests are discovered if I rename test-report.py to test_report.py. Unless someone can shed some light on this, I'll file a bug report to the unittest module maintainer.Ferric
I surprised that this works in nose, since test-report would not be importable.Alisander
J
70

The behaviour is intentional, but the documentation could make this clearer. If you look at the first paragraph in the test discovery section, it says:

For a project’s tests to be compatible with test discovery they must all be importable from the top level directory of the project (in other words, they must all be in Python packages).

A corollary to that is that the file names must also be valid Python module names. test-report.py fails that test, since test-report is not a legal Python identifier.

A docs bug suggesting that this be mentioned explicitly in the documentation for the -p pattern option would probably be a good way forward.

Jedjedd answered 23/2, 2011 at 10:58 Comment(7)
Also note the default discovery pattern looks for test-modules prefixed with the string "test" ... This is what got me.Lemberg
Where in the documentation does it say we must prefix the test module with "test_" keyword?Shivers
Another gotcha I've hit in the past is having tests with invalid module names. Specifically putting a . in e.g. test_this_works_with_version_9.1 is an invalid module name so will be ignored. Running the file directly works, since the OS has no problems with it. TLDR: Don't forget to avoid . in your module names (and other invalid characters)Gerontology
Missing __init__.py can also be a reason why some level is not a python package.Emulsion
I also had problems that I used unit test module names that were appended with "_test" instead of being preppended... (i.e. "data_convert_test" would not be discovered while "test_data_convert" was discovered and ran successfully)Exsert
It is nowhere in the document, but it seems that only files starts with "test" would be discovered. Also, any import in init.py could cause the test to be run multiple times. That module is not well maintained.Fructify
Creating __init__.py in the tests directory worked for me.Icbm
G
29

I had this problem because some directories in a project were missing __init__.py. I thought I don't need them in Python 3.7.

Just add __init__.py to every directory and python3 -m unittest will find tests automatically.

Gottfried answered 25/12, 2019 at 19:14 Comment(1)
Slight nitpick, but OP did have __init__.py in the tests directory.Jueta
T
16

As someone relatively new to Python, the naming convention in the docs implied the opposite. Ben's comment was very helpful: the default discovery pattern looks for test-modules prefixed with the string "test"

I thought the introspection would just look for class names and not require a specific file naming convention.

Here is what the docs say: https://docs.python.org/3/library/unittest.html python -m unittest discover -s project_directory -p "_test.py" I couldn't get this to work, but by changing my file names to be "test_.py" - success!

Tripoli answered 25/4, 2019 at 14:5 Comment(4)
This work! But where in the documentation does it say we must prefix the test module with "test_" keyword?Shivers
python -m unittest -h says for -p pattern under "Alternative Usage": Pattern to match test files ('test*.py' default)Cornhusking
To be super specific, to get this to work with "_test" you need to run it as python -m unittest discover -p '*_test.py' when you run your tests, instead of just python -m unittest which discovers tests with the naming convention of "test_" automatically. It's a tradeoff that makes sense to me because I would rather see the test files next to the other files because then I can see if I'm missing a test file easier.Venerable
You need "*_test.py" instead of "_test.py"Mahoney
S
1

This got me as well. This explains the unittest discovery in detail https://docs.python.org/3/library/unittest.html#test-discovery

To make python -m unittest auto find your tests, you need to do 2 things. 1) add a blank __init__.py file to the tests folder, and 2) name your test 'test_some_name.py'. unittest looks for the file name to START with 'test'. You can change that with the '-p' flag if you want, which is explained in the link above.

Here is my folder strucutre.

MyProject
  /src
    my_file.py
  /tests
    __init__.py
    test_my_file.py

Then I run 'python -m unittest' from the MyProject directory.

Here is an example of refrencing the src file from test_my_file.py:

import unittest
from src import my_file as MF

class TestMyFileMethods(unittest.TestCase):

    def test_some_method(self) :
        self.assertTrue(True)

    #... more tests ...

if __name__ == '__main__':
    unittest.main()
Steel answered 29/12, 2023 at 17:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.