How do I run unit tests in package directory

时间:2018-03-23 00:50:00

标签: python unit-testing

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)

2 个答案:

答案 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并非全部删除并重新生成。