При планировании рефакторинга приложения мы увидели, что некоторые модули, которые были у нас в другом проекте, можно было повторно использовать для того, что нам было нужно. Я быстро подумал, что я могу просто переместить это в отдельный пакет, добавить его в оба проекта в качестве зависимости, и боги DRY будут довольны мной.
Позже в тот же день совершенно неожиданно я понял, что проект рефакторинга - последний из имеющихся у нас, работающий на Python 2.7 (я знаю #SHAME), в то время как все остальные используют 3.5. Попытка обновить версию python - не вариант (эй, у нас еще есть два года согласно pythonclock), так что это была прекрасная возможность попробовать tox.
tox - это универсальный инструмент командной строки для управления и тестирования virtualenv, который можно использовать для:
- проверка правильности установки вашего пакета с разными версиями Python и интерпретаторами
- запуск тестов в каждой из сред, настройка выбранного инструмента тестирования
- выступает в качестве внешнего интерфейса к серверам непрерывной интеграции, значительно сокращая шаблонный код и объединяя тестирование на основе CI и оболочки.
Чтобы начать использовать tox, нам нужно сделать три вещи:
- Установите tox с
pip install tox
. - Создайте файл setup.py для нашего пакета.
- Создайте файл tox.ini на том же уровне каталога, что и файл setup.py.
Установить
Первый шаг - это просто выполнение команды pip install tox
, вы можете установить ее в собственном virtualenv с остальными требованиями к пакету.
setup.py
Следующим шагом будет создание файла setup.py, наш выглядит примерно так:
from setuptools import find_packages, setup setup( name='my-tox-tested-package', version='0.0.1', packages=find_packages(exclude=['tests']), # Include all the python modules except `tests`. description='My custom package tested with tox', long_description='A long description of my custom package tested with tox', install_requires=[ 'Django>=1.11.0', 'djangorestframework>=3.6.0', # Additional requirements, or parse the requirements file and add it here ], classifiers=[ 'Programming Language :: Python', ], entry_points={ 'pytest11': [ 'tox_tested_package = tox_tested_package.fixtures' ] }, )
Это действительно просто, он определяет метаданные пакета и его требования. Этот файл позволит нам установить наш пакет как зависимость в других проектах, что мы можем сделать локально с pip install -e <path_to_package>
, или загрузить его на GitHub или pypi и добавить в наш файл требований. Вы можете найти больше информации об упаковке в Руководстве пользователя Python Packaging и в документации по инструментам установки.
Вам может быть интересно узнать об аргументе entry_point
, переданном функции setup
, запись pytest11
используется для того, чтобы плагины pytest могли устанавливаться другими, в нашем случае он предоставляет настраиваемые фикстуры pytests, которые могут использоваться проектами, устанавливающими наш пакет.
tox.ini
Наконец, нам нужно создать файл tox.ini, опять же, вот пример того, который мы используем:
# tox (https://tox.readthedocs.io/) is a tool for running tests # in multiple virtualenvs. This configuration file will run the # test suite on all supported python versions. To use it, "pip install tox" # and then run "tox" from this directory. [tox] envlist = py27, py35 [testenv] commands = pytest {posargs: tests} isort --check-only --diff --recursive --skip .tox --skip migrations flake8 deps = -rrequirements.txt
Это действительно простой пример. envlist в разделе tox указывает, что мы хотим запускать команды раздела testenv для двух версий python, в этом примере наши цели - 2.7 и 3.5. Tox будет работать, создав отдельный виртуальный сервер для каждой версии и установив наш пакет в них обоих.
Если мы хотим тестировать одну среду за раз, мы можем передать флаг -e
с именем среды, например, чтобы протестировать только python 3.5, который мы выполняем:
$ tox -e py35
Свойство commands в разделе testenv определяет, какой tox будет выполняться для тестирования нашего кода. Для каждой среды будет вызвано следующее:
- pytest для unittest.
- isort для проверки порядка импорта.
- flake8 для линтинга.
Следует отметить, что команда pytest сопровождается символом {posargs: tests}
, который захватывает аргументы команды tox после --
, передает их в pytest и добавляет tests
в список аргументов.
Звонок вроде:
$ tox -- -x
Выполнит команду:
pytest -x tests
Последний имеющийся у нас элемент - это свойство deps, вот зависимости нашего проекта. Вы можете добавлять их по одному, параметризовать их в соответствии со средой или, в нашем случае, устанавливать все, что есть в файле requirements.txt.
Каждый раз, когда мы меняем зависимости проекта, мы должны сказать tox воссоздать наши среды и установить новые зависимости, используя флаг --recreate
.
$ tox --recreate
Распараллеливание с Travis CI
Чтобы воспользоваться преимуществами матрицы сборки Travis CI, нам просто нужно добавить различные среды, которые мы хотим использовать, в файл travis.yml, таким образом мы запустим два задания и выполним тесты для каждой среды. в параллели.
language: python install: - pip install tox matrix: include: - python: 2.7 env: - TOX_ENV=py27 - python: 3.5 env: - TOX_ENV=py35 script: tox -e $TOX_ENV
Более сложные примеры
Если вы хотите проверить более сложные конфигурации, обратите внимание на репозитории django-braces и pytest-django, оба из них параметризуют свои среды с помощью python и django. версия, среди прочего.