python - unittest is not able to discover / run tests -
there some related questions, none apply.
this directory tree:
» tree abc_backend abc_backend/ ├── backend_main.py ├── funddatabase.db ├── healthcheck.py ├── __init__.py ├── init.py ├── portfolio.py ├── private.py ├── __pycache__ ├── questionnaire.py ├── recurring.py ├── registration.py ├── tests │ ├── config.py │ ├── __init__.py │ ├── __pycache__ │ ├── test_backend.py │ ├── test_healthcheck.py │ └── test_private.py ├── trading.py ├── users.db ├── version └── visualisation.py unittest not able find anything:
top » python -m unittest abc_backend ---------------------------------------------------------------------- ran 0 tests in 0.000s ok not within abc_backend:
abc_backend » python -m unittest tests ---------------------------------------------------------------------- ran 0 tests in 0.000s ok what have verified:
- my test methods named (
test_whatever) - my testcases extend
unittest.testcase - the
abc_backend,abc_backend/testsdirectories have (empty)__init__.py - all test modules importable (see below)
unittest discoverfinds tests, has problems relative imports (see below)noseable discover , run tests, no problems
i understand:
- why need pass
discoverunittestforce discover tests?unittestwithoutdiscoversub-command? (i thought unittest test discovery default). according documentation:
python -m unittest equivalent of python -m unittest discover
- once tests discovered (by forcing
discoversub-command), why have import issues?
test modules importable
» python python 3.4.3 (default, oct 14 2015, 20:28:29) [gcc 4.8.4] on linux type "help", "copyright", "credits" or "license" more information. >>> import abc_backend.tests >>> import abc_backend.tests.test_private >>> import abc_backend.tests.test_healthcheck >>> import abc_backend.tests.test_backend unittest discover has problems relative imports
if run top dir:
top » python -m unittest discover abc_backend ====================================================================== error: tests.test_private (unittest.loader.moduleimportfailure) ---------------------------------------------------------------------- traceback (most recent call last): file "/usr/lib/python3.4/unittest/case.py", line 58, in testpartexecutor yield file "/usr/lib/python3.4/unittest/case.py", line 577, in run testmethod() file "/usr/lib/python3.4/unittest/loader.py", line 32, in testfailure raise exception importerror: failed import test module: tests.test_private traceback (most recent call last): file "/usr/lib/python3.4/unittest/loader.py", line 312, in _find_tests module = self._get_module_from_name(name) file "/usr/lib/python3.4/unittest/loader.py", line 290, in _get_module_from_name __import__(name) file "/foo/bar/abc_backend/tests/test_private.py", line 6, in <module> .. import init valueerror: attempted relative import beyond top-level package if run within abc_backend:
abc_backend » python -m unittest discover tests ====================================================================== error: test_private (unittest.loader.moduleimportfailure) ---------------------------------------------------------------------- traceback (most recent call last): file "/usr/lib/python3.4/unittest/case.py", line 58, in testpartexecutor yield file "/usr/lib/python3.4/unittest/case.py", line 577, in run testmethod() file "/usr/lib/python3.4/unittest/loader.py", line 32, in testfailure raise exception importerror: failed import test module: test_private traceback (most recent call last): file "/usr/lib/python3.4/unittest/loader.py", line 312, in _find_tests module = self._get_module_from_name(name) file "/usr/lib/python3.4/unittest/loader.py", line 290, in _get_module_from_name __import__(name) file "/foo/bar/abc_backend/tests/test_private.py", line 6, in <module> .. import init systemerror: parent module '' not loaded, cannot perform relative import
i reproduced problems cpython 3.5, answer should relevant both 3.4 , 3.5.
relative import issues
the reason why there issues relative imports due specifics of invocations not import abc_backend package.
first, let’s take @
top» python3 -m unittest discover abc_backend when run tests top way, abc_backend not imported. because /home/user/top/abc_backend added sys.path instead of /home/user/top. solve problem, do
top» python3 -m unittest discover abc_backend -t . now, in-abc_backend invocation. when do
abc_backend» python3 -m unittest discover tests abc_backend not importable, /home/user/top/abc_backend/tests dir not contain abc_backend package. can solved with
abc_backend» python3 -m unittest discover tests -t ../ that correctly put /home/user/top dir (pun intended) sys.path.
the -t (or --top-level-directory) option sets top level directory of project , defaults start directory (which . default). so, in sys.path important, affects imports, affect test loading, discovery loads tests using import machinery.
difference between -m unittest , -m unittest discover
when do
top» python3 -m unittest abc_backend in reality running unittest/__main__.py file. there main(module=none) invoked, , loadtestsfrommodule does
tests = [] name in dir(module): obj = getattr(module, name) if isinstance(obj, type) , issubclass(obj, case.testcase): tests.append(self.loadtestsfromtestcase(obj)) as abc_backend/__init__.py not contain test cases, isinstance(obj, type) , issubclass(obj, case.testcase) returns false module members (so tests empty).
to make particular way of invocation work, you’ll have people did in pre-discover times (aside non-stdlib frameworks): manually import cases test modules (or maybe construct test suite according load_tests protocol).
so, how
top» python3 -m unittest discover abc_backend differs?
basically, differences may expressed following conditional:
if len(argv) > 1 , argv[1].lower() == 'discover': # -m unittest discover loader.discover(...) else: # -m unittest loader.loadtestsfromnames(...) when argv ['python3 -m unittest', 'discover', 'abc_backend'], actual discovery mechanism used. when argv ['python3 -m unittest', 'abc_backend'], loadtestsfromnames used, calls loadtestsfrommodule @ point, , no tests found. that’s way things in unittest/main.py.
Comments
Post a Comment