I have a python code base where I have refactored a module (file) into a package (directory) as the file was getting a bit large and unmanageable. However, I cannot get my unit tests running as desired with the new structure.
I place my unit test files directly alongside the code it tests (this is a requirement and cannot change - no separate test
directories):
app/
+-- app.py
+-- config.py
+-- config_test.py
+-- model/
| +-- __init__.py
| +-- base.py
| +-- base_test.py
| +-- square.py
| +-- square_test.py
+-- test.py
+-- web.py
+-- web_test.py
Previously, the model
package was the model.py
module with a model_test.py
test suite.
There is a top-level test runner - test.py
and that works fine. It finds the test cases inside the model
directory and runs them successfully (it uses the discovery
feature of unittest
- see end of post for test.py
):
$ python test.py
However, I also want to be able to directly run the test cases in the model
directory:
$ python model/base_test.py
This does not work, because the test is inside the package directory. The imports in the code fail because they are either not in a module when imported directly by the test suite or the search path is wrong.
For instance, in model/square.py
, I can import base.py
in one of two ways:
from model import Base
or
from .base import Base
These both work fine when model
is imported. But when inside the model
test suites, I cannot import square
because square
cannot import base
.
square_test.py
contains imports like:
import unittest
from square import Square
... test cases ...
if __name__ == '__main__':
unittest.main()
For the first type of import in square.py
(from model import Base
), I get the error:
ModuleNotFoundError: No module named 'model'
Fair enough, sys.path
has /home/camh/app/model
and there is no model
module in there.
For the second type of import in square.py
(from .base import Base
), I get the error:
ImportError: attempted relative import with no known parent package
I cannot figure out how to do my imports that allows me to have tests alongside the unit-under-test and be directly runnable. I want directly runnable test suites as often I do not want to run the entire set of tests, but just target individual tests:
$ python model/square_test.py SquareTest.test_equal_sides
I cannot do that with my test runner because it just uses discovery to run all the tests and discovery is not compatible with specifying individual test suites or test functions.
My test runner (test.py
) is just:
import os, sys
sys.argv += ['discover', os.path.dirname(sys.argv[0]), '*_test.py']
unittest.main(module=None)
答案 0 :(得分:3)
您可以使用参数从命令行调用unittest
模块:
python -m unittest model.square_test
如果您使用的是python3,您也可以使用文件名:
python3 -m unittest model/square_test.py
答案 1 :(得分:0)
建议:
添加app/__init__.py
,并将app
视为包而不是model
一种方法是使用显式from app.model.square import Square
只要在nosetests -vw .
目录中使用app/
,相对导入就可以了。
这些都是以删除app/test.py
重新分解后的另一个常见错误是.pyc
并非全部删除并重新生成。