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

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

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

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

另一种替代方法是将测试文件复制到另一个目录中,但这似乎有点愚蠢,并且没有注意到将它们放在一个单独的目录中。

那么,如果您刚刚下载源代码到我的新项目,您将如何运行单元测试?我更喜欢这样的答案:“要运行单元测试,请执行x。”


当前回答

*nix系统(macOS, Linux)的简单解决方案;也可能是Git bash在Windows上。

PYTHONPATH=$PWD python test/test_antigravity.py

Print语句很容易工作,不像pytest test/test_antigravity.py。对于“脚本”来说,这是一种完美的方法,但对于单元测试来说却不是。

当然,我想做一个适当的自动化测试,我会考虑使用适当设置的pytest。

其他回答

以下是我的项目结构:

ProjectFolder:
 - project:
     - __init__.py
     - item.py
 - tests:
     - test_item.py

我发现最好在setUp()方法中导入:

import unittest
import sys    

class ItemTest(unittest.TestCase):

    def setUp(self):
        sys.path.insert(0, "../project")
        from project import item
        # further setup using this import

    def test_item_props(self):
        # do my assertions

if __name__ == "__main__":
    unittest.main()

可以使用包装器来运行选定的或所有测试。

例如:

./run_tests antigravity/*.py

或者递归地运行所有测试使用globbing (tests/**/*.py)(通过shop -s globstar启用)。

包装器基本上可以使用argparse来解析参数,比如:

parser = argparse.ArgumentParser()
parser.add_argument('files', nargs='*')

然后加载所有测试:

for filename in args.files:
    exec(open(filename).read())

然后将它们添加到你的测试套件中(使用inspect):

alltests = unittest.TestSuite()
for name, obj in inspect.getmembers(sys.modules[__name__]):
    if inspect.isclass(obj) and name.startswith("FooTest"):
        alltests.addTest(unittest.makeSuite(obj))

并运行它们:

result = unittest.TextTestRunner(verbosity=2).run(alltests)

查看这个示例了解更多细节。

请参见:如何在一个目录中运行所有Python单元测试?

使用cwd作为根项目的目录(在你的例子中是new_project),你可以在任何目录中不使用__init__.py运行以下命令:

python -m unittest discover -s test

但是你需要在test_antigravity.py中导入如下:

from antigravity import antigravity.your_object

而不是:

import antigravity.your_object

如果你不喜欢反重力条款,你可能会喜欢艾伦L的答案。

使用setup.py develop使您的工作目录成为已安装的Python环境的一部分,然后运行测试。

这个BASH脚本将从文件系统中的任何位置执行python unittest test目录,无论您在哪个工作目录中。

当你在。/src或。/example工作目录下,并且你需要一个快速的单元测试时,这是很有用的:

#!/bin/bash

this_program="$0"
dirname="`dirname $this_program`"
readlink="`readlink -e $dirname`"

python -m unittest discover -s "$readlink"/test -v

在生产过程中,不需要test/__init__.py文件来增加包/内存开销。