Как включить тестирование для DeprecationWarning и PendingDeprecationWarning с использованием tox+pytest
На протяжении многих лет я тестировал ruamel.yaml
с tox
а также pytest
на регулярной основе для нескольких версий Python. Вскоре после того, как вышла первая бета-версия Python 3.7, я включил ее и обновил тестирование до версии 3.7, когда она была выпущена. Я все еще выполнял большую часть своей повседневной работы с Python 3.6 (и 2.7, где это необходимо).
Поэтому я был очень удивлен тем, что проблема вошла в bitbucket, для DeprecationWarning
так как ruamel.yaml
все еще импортировал вещи из collections
путь Python 2.X (начиная с 3.8 они должны быть импортированы из collections.abc
где они уже живут). Я бы ожидал, что мой tox
запуски, которые являются обязательным условием в моем наборе инструментов для возможности выдвинуть новую версию в PyPI, чтобы понять это несколько месяцев назад.
Из командной строки вы можете увидеть предупреждения, например, когда вы делаете:
python3.7 -W always -c "import ruamel.yaml"
После некоторых исследований я добавил:
[pytest]
filterwarnings =
error::DeprecationWarning
error::PendingDeprecationWarning
к моему tox.ini
, который не изменил результаты теста для цели py37
(321 проходов /2 пропущенных /7 xfail).
Затем я добавил:
setenv = PYTHONWARNINGS = ошибка
по умолчанию ([testenv]
) цель. Это дало некоторые интересные изменения в результате, так как тестирование завершилось сбоем из-за предупреждений об устаревании в tox
/pytest
/virtualenv
сам набор инструментов
Я исправил их вручную (намереваясь автоматизировать это после tox -r
запустить), чтобы увидеть, если с этим по крайней мере получить ошибку на токсина для ruamel.yaml
сам, но это не так. Если вы вместо этого добавите:
setenv =
PYTHONWARNINGS=always::DeprecationWarning
в [testenv]
вы увидите, что набор инструментов имеет:
DeprecationWarning: режим 'U' устарел
DeprecationWarning: модуль imp устарел в пользу importlib
DeprecationWarning: Использование или импорт ABC из "коллекций" вместо "коллекций.abc" устарело, и в 3.8 он перестанет работать
Последнее, на самом деле, - то, что я искал, но эта ошибка была из-за кода в pyparsing зависимости tox...
Тогда я новый файл test_import.py
с одним тестом:
def test_import():
from ruamel.yaml
и дважды проверил, что tox
выполняет тест (прохождение 322 тестов), но никакие сообщения или предупреждения не отображаются, даже при добавлении -ra
в pytest
,
Я ожидал tox
чтобы помочь мне найти амортизацию на ранней стадии, но на самом деле кажется невозможным заставить их срабатывать вообще. Конечно, я могу добавить командную строку, показанную выше, в качестве дополнительной команды в моем tox.ini
, Но некоторое устаревание может быть вызвано не так легко, и я не хочу дублировать мои усилия по тестированию, просто чтобы поймать потенциальные амортизации.
Как я могу вызвать DeprecationWarning
в моем коде с помощью tox
?
1 ответ
Если вы начнете с минимальной 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 =============================================================================
на py37
, в то время как py36
а также 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
перевернут, только для протестированных модулей. ted -e py37,dwf
должен пройти первый (еще раз с прохождением 321 теста) и потерпеть неудачу на второй цели.