classification
Title: unittest discovery doesn't detect namespace packages when given no parameters
Type: behavior Stage: patch review
Components: Versions: Python 3.6, Python 3.5
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: Claudiu.Popa, Florian.Apolloner, Zbynek.Winkler, ashkop, eric.snow, ezio.melotti, michael.foord, pconnell, rbcollins, rgammans
Priority: normal Keywords: patch

Created on 2015-04-07 11:36 by Florian.Apolloner, last changed 2020-03-24 09:37 by Zbynek.Winkler.

Files
File name Uploaded Description Edit
console_log.txt Florian.Apolloner, 2015-04-07 11:36
issue_23882_test_case.sh ashkop, 2015-04-20 07:12
issue23882_find_all.patch ashkop, 2015-04-28 09:28 review
issue23882_find_one_level.patch ashkop, 2015-04-28 09:29 review
Messages (15)
msg240205 - (view) Author: Florian Apolloner (Florian.Apolloner) Date: 2015-04-07 11:36
Unittest discovery does not seem to work if the tests package is  a namespace package. The attached file should have all details to reproduce, as soon as I readd an __init__.py everything works fine. 

Test was done using python3.4.2 and 3.4.3
msg240254 - (view) Author: Alex Shkop (ashkop) * Date: 2015-04-08 09:57
Spent some time looking into this one. Looks like the problem is in TestLoader.discover() method. There are couple of issues I found in it, all caused by same assumption.

Documentation [1] states that all test modules found by discover() method should be importable from top_level_dir. Whenever this method finds a subdirectory of start_dir it checks for __init__.py file. If there's no __init__.py then finder assumes that files within this package is not importable and stops recursion. This kind of 'importablity' check is not valid since we have namespace packages.

I'm not sure what should be done to fix this issue. We can change documentation to state that only regular packages with tests will be discovered. Or we can fix 'importability' checks, which will mean that all tests in all subdirectories will be discovered.

[1] https://docs.python.org/3.4/library/unittest.html#unittest.TestLoader.discover
msg240264 - (view) Author: Eric Snow (eric.snow) * (Python committer) Date: 2015-04-08 13:00
Is there any reason for unittest to not use pkgutil.iter_modules or pkgutil.walk_packages?  Either should work.
msg241331 - (view) Author: PCManticore (Claudiu.Popa) * (Python triager) Date: 2015-04-17 13:58
Isn't this already supported by the patch added in issue17457?
msg241334 - (view) Author: Alex Shkop (ashkop) * Date: 2015-04-17 14:25
Not fully. Patch for issue17457 fixed discovery when you explicitly specified namespace package as a target for discovery. I.e. when you run

python -m unittest namespace_pkg

But it didn't recurse into any namespace packages inside namespace_pkg. So when you run

python -m unittest

it doesn't go under all namespace packages (basically folders) in cwd.
msg241351 - (view) Author: Robert Collins (rbcollins) * (Python committer) Date: 2015-04-17 18:40
Hi. I'd be happy enough to use pkgutil helpers if they (like walkdirs) allowed trimming the output: part of the definition of discovery is that one can control it, to stop it importing or processing part of the tree that one doesn't want processed.

Alex: can you create a test case please - just a small script, python or shell or whatever, that will setup a demonstration of the bug? Thanks.
msg241619 - (view) Author: Alex Shkop (ashkop) * Date: 2015-04-20 07:12
This script creates following directory structure

issue_23882\
  tests\
    test_fail.py

If you run from issue_23882 directory

python -m unittest

it doesn't find any tests. If there is __init__.py inside tests folder, same command finds test_fail.py and runs it.

I'm not sure yet about using pkgutil cause looks like iter_modules and walk_packages do not find namespace packages as well.
msg241621 - (view) Author: Robert Collins (rbcollins) * (Python committer) Date: 2015-04-20 07:51
Ok, so here's whats happening:
the default behaviour is to do discovery of '.', which bypasses the namespace support code.

Running with tests as the first parameter works because it doesn't require the directory being directly scanned to be a package.

Equally, if the namespace isn't mapped to a local directory, 'python -m unittest tests' will load tests from the tests namespace.

So - this seems to be acting as designed. Namespace packages working fine.

However, I think what you're asking for is that namespace packages in your cwd are picked up and tested, without you having to supply the namespace name?

I think what we'd need for that to work sanely is a patch to teach loader.discover to determine the local namespaces which are present under start_dir. Right now this code:
        elif os.path.isdir(full_path):
            if (not namespace and
                not os.path.isfile(os.path.join(full_path, '__init__.py'))):
                return None, False

gets in your way: we assume that either we're processing a namespace, or there are no namespaces at all.

I think some more detangling of the generator could address this fairly cleanly.
msg241627 - (view) Author: Alex Shkop (ashkop) * Date: 2015-04-20 09:50
Thanks. I understand the code pretty well and I saw issue17457 that fixes discovery for explicitly specified namespace package.

What I need is to know how discovery has to work. Do we need to discover namespace packages inside discovery path? And should we do that recursively? I.e. should we pick namespace packages inside namespace packages? This will lead to recursive scan of all directories under discovery path.
msg242170 - (view) Author: Alex Shkop (ashkop) * Date: 2015-04-28 09:28
I'm still not sure which solution is the best. So I attach two simple patches.

First one enables full recursive scan of start_dir for namespace packages.

Second one loads tests only from top level namespace packages.
msg242203 - (view) Author: Robert Collins (rbcollins) * (Python committer) Date: 2015-04-28 19:02
Ah the user model? 

I think the following:

If I run 'python -m unittest' in a directory, then I expect to run all of the tests contained within that directory tree, and no others.

Does that definition help?
msg242213 - (view) Author: Alex Shkop (ashkop) * Date: 2015-04-29 06:13
Yes. That is how issue23882_find_all.patch works. I just removed hte condition

        if (not namespace and
            not os.path.isfile(os.path.join(full_path, '__init__.py'))):
            return None, False
 
This makes namespace parameter redundant. Can I remove it?
msg242967 - (view) Author: Alex Shkop (ashkop) * Date: 2015-05-12 12:57
Please, review the patch.
msg248935 - (view) Author: Robert Collins (rbcollins) * (Python committer) Date: 2015-08-21 00:57
reviewed in rietvald, but here too just in case.

The hunk that saves/restores _top_level_dir feels wrong to me - and not part of this bug, please remove it.

The rest of the patch is fine today.

But it also needs to add two specifically namespace tests: concretely we need the following cases covered:


a) namespace subdir/namespace subdir/test_foo.py gets loaded
b) namespace subdir/test_foo.py with another instance of the namespace subdir on sys.path also containing e.g. test_bar.py, test_bar.py is not loaded.
msg248936 - (view) Author: Robert Collins (rbcollins) * (Python committer) Date: 2015-08-21 00:57
(for the trivial case of CLI discover without a parameter - so translate that to the lower level API and then test that)
History
Date User Action Args
2020-03-24 09:37:47Zbynek.Winklersetnosy: + Zbynek.Winkler
2019-10-28 20:48:25pconnellsetnosy: + pconnell
2019-08-19 21:43:04rgammanssetnosy: + rgammans
2015-08-21 00:57:46rbcollinssetmessages: + msg248936
2015-08-21 00:57:17rbcollinssetmessages: + msg248935
2015-05-12 20:10:50ned.deilysetstage: needs patch -> patch review
2015-05-12 12:57:41ashkopsetmessages: + msg242967
2015-04-29 06:13:41ashkopsetmessages: + msg242213
2015-04-28 19:02:22rbcollinssetmessages: + msg242203
2015-04-28 09:29:03ashkopsetfiles: + issue23882_find_one_level.patch
2015-04-28 09:28:54ashkopsetfiles: + issue23882_find_all.patch
keywords: + patch
messages: + msg242170
2015-04-20 09:50:08ashkopsetmessages: + msg241627
2015-04-20 07:51:42rbcollinssettitle: unittest discovery and namespaced packages -> unittest discovery doesn't detect namespace packages when given no parameters
stage: needs patch
messages: + msg241621
versions: + Python 3.5, Python 3.6, - Python 3.4
2015-04-20 07:12:50ashkopsetfiles: + issue_23882_test_case.sh

messages: + msg241619
2015-04-17 18:40:21rbcollinssetmessages: + msg241351
2015-04-17 14:25:30ashkopsetmessages: + msg241334
2015-04-17 13:58:26Claudiu.Popasetnosy: + Claudiu.Popa
messages: + msg241331
2015-04-08 13:00:44eric.snowsetmessages: + msg240264
2015-04-08 09:57:53ashkopsetnosy: + ashkop
messages: + msg240254
2015-04-07 14:54:53eric.snowsetnosy: + eric.snow
2015-04-07 11:43:33ezio.melottisetnosy: + rbcollins, ezio.melotti, michael.foord
type: behavior
2015-04-07 11:36:35Florian.Apollonercreate