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

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

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

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

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

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


当前回答

这个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文件来增加包/内存开销。

其他回答

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

以下是我的项目结构:

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()

这种方式将允许您从任何您想要的地方运行测试脚本,而不会从命令行中破坏系统变量。

这将把主项目文件夹添加到python路径中,其位置相对于脚本本身,而不是相对于当前工作目录。

import sys, os

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

将其添加到所有测试脚本的顶部。这将把主项目文件夹添加到系统路径中,因此从那里导入的任何模块现在都可以工作了。你在哪里做测试并不重要

显然,您可以更改project_path_hack文件以匹配您的主项目文件夹位置。

在我看来,最好的解决方案是使用unittest命令行界面,它会将目录添加到sys. exe目录。路径,因此您不必(在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

在测试包中的测试模块中,可以像往常一样导入反重力包及其模块:

# 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*.py模块。

如果你使用VS Code,并且你的测试与你的项目位于同一级别,那么运行和调试你的代码就不能开箱即用。你能做的就是改变启动方式。json文件:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python",
            "type": "python",
            "request": "launch",
            "stopOnEntry": false,
            "pythonPath": "${config:python.pythonPath}",
            "program": "${file}",
            "cwd": "${workspaceRoot}",
            "env": {},
            "envFile": "${workspaceRoot}/.env",
            "debugOptions": [
                "WaitOnAbnormalExit",
                "WaitOnNormalExit",
                "RedirectOutput"
            ]
        }    
    ]
}

这里的关键行是envFile

"envFile": "${workspaceRoot}/.env",

在项目的根目录中添加.env文件

在.env文件中添加项目根目录的路径。这将临时添加

PYTHONPATH = C: \ \ PYTHON项目\ \ ROOT_DIRECTORY

路径到你的项目,你将能够使用调试单元测试从VS Code