Условные команды в tox? (tox, travis-ci и комбинезоны)

tl;dr:

Я настраиваю CI для своего проекта, размещенного на github, используя tox и travis-ci. В конце сборки я запускаю converalls, чтобы отправить отчеты о покрытии в coveralls.io. Я хотел бы сделать эту команду «условной» - для выполнения только тогда, когда тесты запускаются на travis; не тогда, когда они запускаются на моей локальной машине. Есть ли способ сделать это?

Подробности:

Пакет, который я пытаюсь протестировать, представляет собой пакет Python. Я использую/планирую использовать следующую «инфраструктуру» для настройки тестов:

  • Сами тесты относятся к типу py.test.
  • Сценарии CI, так сказать, из tox. Это позволяет мне запускать тесты локально, что очень важно для меня. Я не хочу заходить на github каждый раз, когда мне нужен тестовый прогон. Я также использую numpy и matplotlib в своем пакете, поэтому запускать бессмысленное количество тестовых циклов на travis-ci мне кажется чрезмерно расточительным. Таким образом, отказаться от tox и просто использовать только .travis.yml не вариант.
  • CI-сервер travis-ci

Соответствующие тестовые сценарии выглядят примерно так:

.travis.yml

language: python
python: 2.7
env:
  - TOX_ENV=py27
install:
  - pip install tox
script:
  - tox -e $TOX_ENV

tox.ini

[tox]
envlist = py27

[testenv]
passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH
deps =
    pytest
    coverage
    pytest-cov
    coveralls
commands =
    py.test --cov={envsitepackagesdir}/mypackage --cov-report=term --basetemp={envtmpdir}
    coveralls

Этот файл позволяет мне запускать тесты локально. Однако из-за последнего вызова coveralls тест в принципе не проходит:

py27 runtests: commands[1] | coveralls
You have to provide either repo_token in .coveralls.yml, or launch via Travis
ERROR: InvocationError: ...coveralls'

Это ожидаемая ошибка. Бит passenv отправляет необходимую информацию из travis, чтобы можно было записать в coveralls, и без travis для предоставления этой информации команда должна завершиться ошибкой. Я также не хочу, чтобы результаты отправлялись на сайт coveralls.io. Я бы хотел, чтобы coveralls запускался только в том случае, если тест проводится travis-ci. Есть ли способ, которым я могу запустить эту команду условно или настроить конфигурацию сборки, которая достигает того же эффекта?

Я уже пытался переместить часть комбинезона в .travis.yml, но когда это выполняется, coveralls, похоже, не может найти соответствующий файл .coverage для отправки. Я предпринял различные попытки в этом направлении, ни одна из которых не привела к успешной подаче на coveralls.io, за исключением комбинации, указанной выше. Я надеялся, что следующее сработает, учитывая, что когда я запускаю tox локально, я получаю файл .coverage там, где и ожидал - в корневой папке моего исходного дерева.

Нет отправки на сайт coveralls.io

language: python
python: 2.7
env:
  - TOX_ENV=py27
install:
  - pip install tox
  - pip install python-coveralls
script:
  - tox -e $TOX_ENV
after_success:
  - coveralls

person Chintalagiri Shashank    schedule 24.09.2015    source источник


Ответы (4)


У меня похожая установка с Трэвисом, токсом и комбинезоном. Моя идея заключалась в том, чтобы выполнять coveralls только в том случае, если установлена ​​переменная среды TRAVIS. Однако кажется, что это не так просто сделать, поскольку у tox есть проблемы с разбором команд с кавычками и амперсандами. Кроме того, это Travis меня сильно смутило.

В конце концов я написал простой скрипт на Python run_coveralls.py:

#!/bin/env/python

import os

from subprocess import call


if __name__ == '__main__':
    if 'TRAVIS' in os.environ:
        rc = call('coveralls')
        raise SystemExit(rc)

В tox.ini замените команду coveralls на python {toxinidir}/run_coveralls.py.

person Brecht Machiels    schedule 08.10.2015
comment
Хорошее решение! Но лучше назвать скрипт run_coveralls.py, чтобы избежать конфликта имен с реальным пакетом coveralls. - person alexanderlukanin13; 07.11.2015
comment
Интересно, как наиболее удобно включать/вызывать run_coveralls.py? Появляется сообщение об ошибке can't open file 'run_coveralls.py': [Errno 2] No such file or directory, так как файл не копируется в виртуальную среду tox. Я полагаю, что это не должно быть включено в пакет. - person Finn Årup Nielsen; 11.11.2015
comment
Думаю, мне удалось найти решение самому. python {toxinidir}/run_coveralls.py вроде работает. - person Finn Årup Nielsen; 11.11.2015
comment
Вы должны удалить import sys, потому что это не требуется для вашего решения... - person aschipfl; 11.11.2015
comment
См. citeproc-py для примера tox.ini и более сложного coveralls.py. - person Brecht Machiels; 11.11.2015

Альтернативным решением было бы поставить перед командой coveralls тире (-), чтобы указать tox игнорировать код выхода, как объяснено в документации. Таким образом, даже отказы от coveralls будут игнорироваться, а tox будет считать выполнение теста успешным при локальном выполнении.

Используя приведенный выше пример конфигурации, это будет следующим образом:

[tox]
envlist = py27

[testenv]
passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH
deps =
    pytest
    coverage
    pytest-cov
    coveralls
commands =
    py.test --cov={envsitepackagesdir}/mypackage --cov-report=term --basetemp={envtmpdir}
    - coveralls
person jcollado    schedule 25.11.2016

Я использую переменную среды для запуска дополнительных команд.

tox.ini

commands =
    coverage run runtests.py
    {env:POST_COMMAND:python --version}

.travis.yml

language: python
python:
  - "3.6"
install: pip install tox-travis
script: tox
env:
  - POST_COMMAND=codecov -e TOX_ENV

Теперь в моей локальной настройке он печатает версию Python. При запуске из Travis запускается codecov.

person Federico JM    schedule 19.02.2018
comment
Вот так. {env:POST_COMMAND:python --version} — это воплощение гениальности, потому что он молча сводится к нулевой точке, когда эта переменная среды не определена. Да. - person Cecil Curry; 28.03.2021

Альтернативное решение, если вы используете Makefile и не хотите новый файл py:

define COVERALL_PYSCRIPT
import os
from subprocess import call

if __name__ == '__main__':
    if 'TRAVIS' in os.environ:
        rc = call('coveralls')
        raise SystemExit(rc)
    print("Not in Travis CI, skipping coveralls")
endef
export COVERALL_PYSCRIPT

coveralls: ## runs coveralls if TRAVIS in env
    @python -c "$$COVERALL_PYSCRIPT"

В tox.ini добавьте make coveralls к commands

person Marcus Santos    schedule 26.02.2020