用典型的测试目录结构运行unittest

2020-12-04 15:59:00 发布

您现在位置:Python中文网/ 问答频道 /正文

对于一个简单的Python模块来说,非常常见的目录结构似乎是将单元测试分离到它们自己的test目录中:

new_project/
    antigravity/
        antigravity.py
    test/
        test_antigravity.py
    setup.py
    etc.

例如,请参见Python project howto

我的问题很简单,实际运行测试的通常方式是什么?我怀疑这对除了我之外的所有人都是显而易见的,但是不能从测试目录运行python test_antigravity.py,因为它的import antigravity将失败,因为模块不在路径上。

我知道我可以修改PYTHONPATH和其他与搜索路径相关的技巧,但我不能相信这是最简单的方法-如果你是开发人员,这是可以的,但如果你的用户只想检查测试是否通过,希望他们使用它是不现实的。

另一种选择是将测试文件复制到另一个目录中,但这似乎有点愚蠢,而且没有考虑到将它们放在一个单独的目录中。

所以,如果您刚刚将源代码下载到我的新项目中,您将如何运行单元测试?我希望得到一个答案,让我对我的用户说:“要运行单元测试,请执行X。”

3条回答
网友
1楼 ·

我通常在项目目录中创建一个“运行测试”脚本(源目录和加载“所有测试”套件的test都通用的脚本)。这通常是样板代码,因此我可以在项目之间重用它。

运行测试.py:

import unittest
import test.all_tests
testSuite = test.all_tests.create_test_suite()
text_runner = unittest.TextTestRunner().run(testSuite)

test/all_tests.py(来自How do I run all Python unit tests in a directory?

import glob
import unittest

def create_test_suite():
    test_file_strings = glob.glob('test/test_*.py')
    module_strings = ['test.'+str[5:len(str)-3] for str in test_file_strings]
    suites = [unittest.defaultTestLoader.loadTestsFromName(name) \
              for name in module_strings]
    testSuite = unittest.TestSuite(suites)
    return testSuite

通过这个设置,您确实可以在测试模块中include antigravity。缺点是需要更多的支持代码来执行特定的测试。。。我每次都在跑。

网友
2楼 ·

我认为最好的解决方案是使用unittestcommand line interface,它将把目录添加到sys.path中,这样就不必(在TestLoader类中完成)。

例如,对于这样的目录结构:

new_project
├── antigravity.py
└── test_antigravity.py

你可以跑:

$ cd new_project
$ python -m unittest test_antigravity

对于像您这样的目录结构:

new_project
├── antigravity
│   ├── __init__.py         # make it a package
│   └── antigravity.py
└── test
    ├── __init__.py         # also make test a package
    └── test_antigravity.py

test包中的测试模块中,您可以像往常一样导入antigravity包及其模块:

# import the package
import antigravity

# import the antigravity module
from antigravity import antigravity

# or an object inside the antigravity module
from antigravity.antigravity import my_object

运行单个测试模块:

要运行单个测试模块,在本例中为test_antigravity.py

$ cd new_project
$ python -m unittest test.test_antigravity

只需按照导入的方式引用测试模块。

运行单个测试用例或测试方法:

也可以运行单个TestCase或单个测试方法:

$ python -m unittest test.test_antigravity.GravityTestCase
$ python -m unittest test.test_antigravity.GravityTestCase.test_method

运行所有测试:

您还可以使用test discovery来发现并运行所有测试,它们必须是名为test*.py的模块或包(可以使用-p, --pattern标志进行更改):

$ cd new_project
$ python -m unittest discover

这将运行test包中的所有test*.py模块。

网友
3楼 ·

对于用户来说,最简单的解决方案是提供一个可执行脚本(runtests.py或类似的脚本),该脚本引导必要的测试环境,包括在需要时将根项目目录临时添加到sys.path。这不需要用户设置环境变量,在引导脚本中这样做很好:

import sys, os

sys.path.insert(0, os.path.dirname(__file__))

那么您对用户的指示可以简单到“python runtests.py”。

当然,如果您真正需要的路径是os.path.dirname(__file__),那么您根本不需要将其添加到sys.path;Python总是将当前运行脚本的目录放在sys.path的开头,因此根据您的目录结构,只需将runtests.py定位在正确的位置就可以了。

另外,unittest module in Python 2.7+(对于Python 2.6和更早版本,它的后端口是unittest2)现在已经内置了test discovery,因此如果您想要自动测试发现,就不再需要nose了:您的用户指令可以简单到python -m unittest discover

相关问题