如何使用tox + pytest

时间:2018-07-28 16:27:24

标签: pytest tox

多年来,我一直在定期针对多个Python版本使用ruamel.yamltox测试pytest。在第一个Python 3.7 beta发布后不久,我将其包含在内,并针对3.7的发布版本进行了升级测试。我仍然在日常工作中一直使用Python 3.6(必要时使用2.7)。

因此,对于DeprecationWarning而言,在Bitbucket上记录问题令我感到非常惊讶,因为ruamel.yaml仍从collections的Python 2.X方式导入内容(从3.8开始,这些< strong>已经要从已经居住的collections.abc导入)。我本来希望我的tox运行在几个月前就已经流行了,这是我的工具链中必须能够将新版本推送到PyPI的强制性先决条件。

从命令行中可以看到警告,例如当您这样做时:

python3.7 -W always -c "import ruamel.yaml"

经过一番研究,我补充说:

[pytest]
filterwarnings =
    error::DeprecationWarning
    error::PendingDeprecationWarning

到达我的tox.ini,后者没有更改目标py37的测试结果(321次通过/ 2次跳过/ 7次失败)。

然后我添加了:

setenv =     PYTHONWARNINGS =错误

设置为默认([testenv])目标。由于tox / pytest / virtualenv工具链本身中的弃用警告,测试崩溃了,结果使结果产生了一些有趣的变化。

我手动修复了这些问题(打算在干净的tox -r运行之后将其自动化),看看这样做是否至少会在ruamel.yaml本身的毒理上产生错误,但是没有没错如果您改为添加:

setenv =
    PYTHONWARNINGS=always::DeprecationWarning

[testenv],您会看到工具链具有:

  

不建议使用警告:不建议使用“ U”模式
  DeprecationWarning:不推荐使用imp模块,而推荐使用importlib
  DeprecationWarning:不建议使用“集合”而不是“ collections.abc”中的ABC或从中导入ABC,并且在3.8中它将停止工作

最后一个实际上是我正在寻找的东西,但是那些错误是由于tox依赖项pyparsing中的代码...

然后通过一次测试创建新文件test_import.py

def test_import():
    from ruamel.yaml

并再次确认tox已执行测试(322个测试通过),但未显示任何消息或警告,即使将-ra添加到{{1} }。

我一直期望pytest能够帮助我尽早发现弃用,但实际上似乎根本无法触发它们。我当然可以在我的tox中添加上面显示的命令行作为附加命令。但是某些弃用操作可能不太容易触发,我不想重复测试工作,只是为了捕捉潜在的弃用操作。

如何使用tox.ini触发代码中的DeprecationWarning

1 个答案:

答案 0 :(得分:1)

如果您以最小的tox

开头
test_one.py

简单的def test_one(): from collections import Hashable

setup.py

还有一个基本的from setuptools import setup, find_packages if __name__ == '__main__': setup( name="depwarntest", version="0.0.1", description="test to get DeprecationWarning in code on 3.7", long_description = "more details soon", author_email="a.van.der.neut@ruamel.eu", author="Anthon van der Neut", license="MIT", url="", packages=find_packages(), )

tox.ini

并运行[tox] envlist = py37,py36,py27 [testenv] commands = /bin/bash -c 'pytest test_*.py' deps = pytest [pytest] filterwarnings = error::DeprecationWarning error::PendingDeprecationWarning ,由于您的tox,您会得到一个很好的异常:

import

==================================================================================== FAILURES ===================================================================================== ____________________________________________________________________________________ test_one _____________________________________________________________________________________ def test_one(): > from collections import Hashable test_one.py:6: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ <frozen importlib._bootstrap>:1032: in _handle_fromlist ??? _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ name = 'Hashable' def __getattr__(name): # For backwards compatibility, continue to make the collections ABCs # through Python 3.6 available through the collections module. # Note, no new collections ABCs were added in Python 3.7 if name in _collections_abc.__all__: obj = getattr(_collections_abc, name) import warnings warnings.warn("Using or importing the ABCs from 'collections' instead " "of from 'collections.abc' is deprecated, " "and in 3.8 it will stop working", > DeprecationWarning, stacklevel=2) E DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated, and in 3.8 it will stop working .tox/py37/lib/python3.7/collections/__init__.py:52: DeprecationWarning ============================================================================ 1 failed in 0.31 seconds ============================================================================= 上运行,而py37py36运行良好。

如果将测试文件更改为要读取,则足够有趣

py27

运行from collections import Hashable def test_one(): from collections import Hashable 也会在tox上正常运行。 如果将模块级别的导入移动到另一个py37文件中,甚至是这种情况

对于test_XYZ.py,这意味着测试文件中所有ruamel.yaml的模块级别导入都需要移到方法/函数中。测试中的任何根级别类都取决于,例如在ruamel.yaml上需要使用生成器;并且模块级别ruamel.yaml.YAML()也需要以特殊方式处理。

额外的yaml_object()目标通过进行一致性测试来帮助测试渐进式运动:

tox

此处,将针对已改编的模块还原已更正的源# deprecation warning fail [testenv:dwf] basepython = python3.7 commands = /bin/sed 's/collections.abc/collections/' -i .tox/dwf/lib/python3.7/site-packages/ruamel/yaml/comments.py /bin/bash -c 'pytest --maxfail=2 _test/test_[a-cz]*.py' comments.py应该通过第一个(通过321次测试才可以通过),并且在第二个目标上失败。