协慌网

登录 贡献 社区

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

即使是一个简单的 Python 模块,最常见的目录结构似乎也是将单元测试分成各自的test目录:

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

例如,参见此Python 项目 howto

我的问题是,实际上运行测试的通常方法是什么?我怀疑这对除我以外的所有人来说都是显而易见的,但您不能仅从python test_antigravity.py ,因为其import antigravity将失败,因为模块不在路径上。

我知道我可以修改 PYTHONPATH 和其他与搜索路径有关的技巧,但是我不敢相信这是最简单的方法 - 如果您是开发人员,那很好,但如果用户只是想检查测试结果,就不能期望用户使用通过。

另一种选择是将测试文件复制到另一个目录中,但似乎有点愚蠢,并且错过了将它们放在一个单独目录中的意义。

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

答案

我认为最好的解决方案是使用unittest 命令行界面,该界面会将目录添加到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*.py模块或软件包(可以通过-p, --pattern标志进行更改):

$ cd new_project
$ python -m unittest discover
$ # Also works without discover for Python 3
$ # as suggested by @Burrito in the comments
$ python -m unittest

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

对用户来说,最简单的解决方案是提供一个可执行脚本( 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定位在正确的位置即可。

另外, Python 2.7 + 中的 unittest 模块(已反向移植为 Python 2.6 及更早版本的unittest2 )现在具有内置的测试发现功能,因此,如果您要进行自动测试发现,则不再需要鼻子:您的用户说明可以很简单python -m unittest discover

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

run_tests.py:

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

test / all_tests.py(来自我如何在目录中运行所有 Python 单元测试?

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不利的一面是您需要更多的支持代码来执行特定的测试…… 我每次都运行它们。