63

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.

ndmeiri
  • 4,979
  • 12
  • 37
  • 45
blokeley
  • 6,726
  • 9
  • 53
  • 75
  • 3
    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. – blokeley Feb 23 '11 at 09:56
  • I surprised that this works in nose, since test-report would not be importable. – dbn Jan 16 '13 at 20:55

3 Answers3

68

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.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
ncoghlan
  • 40,168
  • 10
  • 71
  • 80
  • 39
    Also note the default discovery pattern looks for test-modules prefixed with the string "test" ... This is what got me. – Ben DeMott Jan 29 '14 at 02:32
  • Where in the documentation does it say we must prefix the test module with "test_" keyword? – variable Oct 17 '19 at 11:30
  • 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) – WaffleSouffle Oct 21 '19 at 14:07
  • 10
    Missing `__init__.py` can also be a reason why some level is not a python package. – user61034 Mar 06 '20 at 17:52
  • 1
    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) – Andrei Rînea Mar 26 '20 at 23:33
  • 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. – c0redumb Sep 01 '22 at 00:35
  • Creating `__init__.py` in the tests directory worked for me. – Loner Feb 04 '23 at 17:25
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.

Max Malysh
  • 29,384
  • 19
  • 111
  • 115
14

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!

Bill K
  • 141
  • 1
  • 2
  • This work! But where in the documentation does it say we must prefix the test module with "test_" keyword? – variable Oct 17 '19 at 11:30
  • `python -m unittest -h` says for `-p pattern` under "Alternative Usage": `Pattern to match test files ('test*.py' default)` – jrc Oct 24 '19 at 14:17
  • 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. – Michael Davidson Sep 12 '21 at 21:29
  • You need "*_test.py" instead of "_test.py" – Harry Jones Mar 01 '23 at 10:55