Travis CIのmatrixでtoxを実行する

Djangoフレームワークに依存するPythonのモジュールを作っていると、複数のPythonバージョンと複数のDjangoバージョンでテストコードを実行する必要があります。

手元で実行する場合はtoxを使うのですが、CIツールでもテストを実行したいです。

Welcome to the tox automation project — tox 2.7.0 documentation

GitHubで公開しているプロジェクトの場合、Travis CIを使うのが簡単でした。

Travis CI - Test and Deploy Your Code with Confidence

Travis CIは、複数の実行環境で並列してテストを実行し、テスト結果を分けて表示してくれます。

設定例

toxはTOXENVで実行する環境を指定できるので、.travis.ymlのmatrixでこれを指定します。

Pythonのバージョンを変えつつ環境変数を指定する設定の書き方がわかりづらくて試行錯誤した結果、次のように落ち着きました。

.travis.yml:

sudo: false
language: python
matrix:
  include:
    - python: '2.7'
      env: TOXENV=py27-dj18
    - python: '2.7'
      env: TOXENV=py27-dj19
    - python: '2.7'
      env: TOXENV=py27-dj110
    - python: '2.7'
      env: TOXENV=py27-dj111
    - python: '3.4'
      env: TOXENV=py34-dj18
    - python: '3.4'
      env: TOXENV=py34-dj19
    - python: '3.4'
      env: TOXENV=py34-dj110
    - python: '3.4'
      env: TOXENV=py34-dj111
    - python: '3.5'
      env: TOXENV=py35-dj19
    - python: '3.5'
      env: TOXENV=py35-dj110
    - python: '3.5'
      env: TOXENV=py35-dj111
    - python: '3.6'
      env: TOXENV=py36-dj110
    - python: '3.6'
      env: TOXENV=py36-dj111
    - python: '3.6'
      env: TOXENV=flake8
    - python: '3.6'
      env: TOXENV=coverage
script:
  - tox
install:
  - pip install tox

tox.ini:

[tox]
envlist =
  py27-dj18,
  py27-dj19,
  py27-dj110,
  py27-dj111,
  py34-dj18,
  py34-dj19,
  py34-dj110,
  py34-dj111,
  py35-dj19,
  py35-dj110,
  py35-dj111,
  py36-dj110,
  py36-dj111,
  coverage,
  flake8

[testenv]
commands = nosetests
deps =
  pyftpdlib
  nose

[testenv:py27-dj18]
basepython = python2.7
deps =
  django>=1.8,<1.9
  {[testenv]deps}

[testenv:py27-dj19]
basepython = python2.7
deps =
  django>=1.9,<1.10
  {[testenv]deps}

[testenv:py27-dj110]
basepython = python2.7
deps =
  django>=1.10,<1.11
  {[testenv]deps}

[testenv:py27-dj111]
basepython = python2.7
deps =
  django>=1.11,<1.12
  {[testenv]deps}

[testenv:py34-dj18]
basepython = python3.4
deps =
  django>=1.8,<1.9
  {[testenv]deps}

[testenv:py34-dj19]
basepython = python3.4
deps =
  django>=1.9,<1.10
  {[testenv]deps}

[testenv:py34-dj110]
basepython = python3.4
deps =
  django>=1.10,<1.11
  {[testenv]deps}

[testenv:py34-dj111]
basepython = python3.4
deps =
  django>=1.11,<1.12
  {[testenv]deps}

[testenv:py35-dj19]
basepython = python3.5
deps =
  django>=1.9,<1.10
  {[testenv]deps}

[testenv:py35-dj110]
basepython = python3.5
deps =
  django>=1.10,<1.11
  {[testenv]deps}

[testenv:py35-dj111]
basepython = python3.5
deps =
  django>=1.11,<1.12
  {[testenv]deps}

[testenv:py36-dj110]
basepython = python3.6
deps =
  django>=1.10,<1.11
  {[testenv]deps}

[testenv:py36-dj111]
basepython = python3.6
deps =
  django>=1.11,<1.12
  {[testenv]deps}

[testenv:flake8]
basepython = python3.6
deps =
  flake8
commands =
  flake8 src/

[testenv:coverage]
basepython = python3.6
deps =
  django>=1.11,<1.12
  coverage
  {[testenv]deps}
commands =
  nosetests --with-coverage

実行結果

tokibito/django-ftpserver - Travis CI

f:id:nullpobug:20170415154656p:plain

ハマった点

  • Pythonのバージョンを3.6にすると、Python3.5が入っていない
  • Pythonのバージョンを3.5にすると、Python3.6が入っていない