从setup.py安装tox的测试依赖项

42

我使用setuptools创建了项目,想使用tox进行测试。我将依赖项列在变量中,并添加到setup()参数(tests_requireextras_require)。我的项目需要安装tests_require中列出的所有依赖项进行测试,但pip install未安装它们。

我尝试过以下方法,但没有成功:

install_command = pip install {opts} {packages}[tests]

我如何在不必管理多个依赖列表的情况下安装测试依赖项(例如,在test_requirements.txttests_require变量中同时列出所有依赖项)?


1
我不确定你是否可以这样做——我看到的所有有 tox 集成的项目都只有一个特定的测试要求文件,并在 tox.ini 中设置 deps = -r whatever_file.txt - jonrsharpe
@jonrsharpe 我只想制作一个没有依赖的文本文件。如果我这样做,我必须管理两个依赖列表。 - item4
是的,我理解你为什么不想这样做,但我告诉你我不确定你能避免它。另一个选择是从setup.py文件中读取测试依赖项,而不是硬编码它们;这将使您回到单个DRY列表。 - jonrsharpe
1
对于现在遇到这个问题的任何人:截至2021年,setup.py testtests_require已经被弃用(问题文档)。因此,下面涉及extras的答案不再只是解决方法,而是实现仅限测试依赖项的唯一官方非弃用方式。 - smheidrich
4个回答

63

我通过对额外要求的轻微滥用来实现这一点。你已经接近成功尝试了extras语法,只是tests_require依赖项不能自动使用该方式。

像这样有一个setup.py

from setuptools import setup

test_deps = [
    'coverage',
    'pytest',
]
extras = {
    'test': test_deps,
}

setup(
    # Other metadata...
    tests_require=test_deps,
    extras_require=extras,
)
你可以使用 extras 语法来安装测试依赖项,例如在项目根目录中执行以下命令:
$ pip install .[test]

将相同的语法提供给 tox.ini 中的 Tox,无需调整默认的 install_command

[testenv]
commands = {posargs:pytest}
deps = .[test]

现在,您不需要在两个地方维护依赖关系列表,并且它们会按照应该发布的软件包的方式表达:在打包元数据中而不是requirements.txt文件中。

看起来,这个小技巧并不那么普遍


1
似乎这不仅安装依赖项,还包括当前项目。 - tkruse
1
@tkruse 是的,这就是 pip install . 的本质,无论是否使用 [extras] 语法。我通常觉得这并不重要,因为我通常在虚拟环境中开发,甚至有益,因为你的测试可以使用模块导入你的被测试代码,并帮助捕获你没有相对导入问题等。@Guy Gangemi 在他的回答中提出了一个警告,这可能是一个有效的警告,但这不是我个人在实践中遇到的情况。基于 Tox 的新功能,他的回答可能是一个好的选择——我不想对 setuptools python setup.py test 的争议发表意见。 - ches

17

解决方��

Tox 2.6引入了extras选项。这将仅为该sdist安装extras,并在正常的sdist安装时进行构建,仅限于该sdist和当时的时间。

setup.py应如下所示:

setuptools.setup(
    ...
    extras_require={
        'tests': ['pytest>=3.7.0', 'more_packages'],
    },
    ...
 )

tox.ini 应该长这样:

[testenv]
...
extras = tests
...

问题

其他方法可能会得到类似的结果,但会引入不必要的风险并限制其他功能的使用:

deps =.[tests] 有点像一个hack。该字段用于环境所需的软件包。如果setup.py install_requires引用您开发的另一个软件包,则可以使用它来拉取其预发布版本。如所示,它将从您的工作目录(无论处于什么状态)安装整个软件包,以获取tests中的软件包列表。接下来将运行install_command,安装您新创建的sdist。简而言之,由于您已经从工作副本中安装了软件包,因此可能掩盖了与sdist相关的问题。

编辑install_command是过度的。它将覆盖通过deps安装的项目。(也许您使用它来安装软件包的特定版本)。

tests_require在运行python setup.py test时使用。Tox建议避免使用python setup.py test,这样您就可以完全忽略tests_require


如果不鼓励使用 python setup.py testpip install .[test],那么将这些测试定义为 setuptools 的额外功能有什么用处呢?难道我们不应该将 Tox 定义与 setup.py 完全分开吗? - Robin Winslow
@RobinWinslow 我们同意。pip install <package>[test] 安装的软件包用于运行测试,可能是通过 pytest 或类似工具。用户可以选择在他们打算运行您的软件包的环境中运行测试。它应该独立于 Tox。开发人员使用 Tox 在多个环境下运行这些测试,所示的 .ini 示例是以最小副作用进行 pip install 调用的最佳方式。 - Guy Gangemi

4
您可以创建一个名为test_requirements.txt的文件,列出测试依赖项的清单,如下所示:
dnspython==1.12.0
easydev==0.8.3
enum34==1.0.4
fabric==1.10.1
...

然后,在setup.py中,解析并将文件内容存储在一个列表中,并将该列表传递给setup

tests_require = [line.strip() for line in 
                 open('test_requirements.txt')
                 if line.strip() and not line.strip().startswith('--')]

setuptools.setup(
    ...
    tests_require=tests_require,
    ...
)

2
如果您使用以下命令,Tox将在运行测试之前安装test_requires
commands = {envpython} setup.py test

您还需要在 setup.py 中添加以下代码以指定测试位置:

test_suite="tests_module"

最后,这里有一个类似问题的答案,它有一个很好的例子。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接