Keep on moving

あんまりまとまってないことを書きますよ

Pythonでのテストツールtox入門

libuvPython実装であるpyuvのPython3対応しているときに、Python2.6/2.7/3.0/3.1/3.2で個別にテストする必要がありました。
各バージョンのPythonを入れるのも割と大変だし、各バージョンごとに確認するのも非常に手間です。
lazyな私にはこんなのやってられません。がおー。めんどくせー。
というわけでいろいろテストツールをいろいろ探していたら、79.pyで @ さんにtoxを教えていただきました。
早速使ってみたので、軽くメモを残しておきます。

ドキュメント

↓を読めば大体わかるはず。
Welcome to the tox automation project — tox 1.4.2-1 documentation

ざっくり説明すると

Pythonライブラリを複数バージョンでテストするツールです。
CI(Jenkinsなど)で使うことも想定しているようです。(Jenkinsでの使い方はここを参照)
mock, greenlet ,pylibなどで使われています。
私はやったことないですが、きちんと設定すれば、Sphinxのdoctestを実行することも可能です。(General tips and tricks — tox 1.4.2-1 documentation)

動作の仕組み

PATHからバージョン付きのpythonコマンド(例: python2.6)を探し、バージョンごとにvirtualenvで環境を作って
各バージョンごとにテストしてくれます。つまり、もとの環境は汚れません。
なお、各バージョンのPATHは設定ファイルで、設定することができます。(ここを参照)

インストール

以下のコマンドのどちらかを使いましょう。ここでは easy_install or pipの説明はしません。

$ easy_install tox
$ pip install tox

実行方法

tox.iniを作る

設定ファイルを作ります。おなじみのini形式です。
toxのexampleでは py.testですが、ここでは私が使い慣れているnoseで記述しています。
他のテストランナー(unit2コマンドなど)を使うこともできます。

# content of: tox.ini , put in same dir as setup.py
[tox]
envlist = py31, py32
[testenv]
deps=nose           # テストで使うライブラリ
commands=nosetests  # テスト時に実行するコマンド
コマンド実行

以下のコマンドをたたけば実行できます。

$ tox
$ tox -e py32 # py32だけのテストをしたい場合

ちょっと進んだ使い方

Python2.6 /3.0では unittest2 を使いたい場合の設定を紹介します。

[tox]
envlist = py26, py27, py30, py31, py32

[testenv]
deps = nose
commands = nosetests -v -w tests []

[testenv:py26]
deps = 
  unittest2
  nose
commands = nosetests -v -w tests []

[testenv:py30]
deps =
  unittest2py3k
  nose
commands = nosetests -v -w tests []

Python2,3両方に対応する場合

今回は幸いなことに対象となるライブラリで"2to3"コマンドを使わずにすみました。*1
そうでない場合は、わりと大変だと思います。

commands で"2to3" or "3to2" を追加する必要があるのですが、ドキュメントには書かれていません。
実際に処理を行っているtoxを探してみるといいと思います。

3to2コマンドを使ってる例を紹介しておきます。
ここで使われているライブラリはPython3.2向けに書かれていて2系は3to2して使うという先進的なものです。
https://github.com/EnigmaCurry/blogofile/blob/plugins/tox.ini

使い方の想定

toxコマンド実行の度にライブラリのパッケージング&テストがはしります。
ですので、まず1バージョンのテストをすませた後で、最後にtoxテストを実行できるようにするといいと思いました。
ライブラリの対応バージョンが少なく,CIでのテストを考えない, Windows/Unix両方で動かすことを考えない場合は別に使わなくてもいいかもしれません。
今回の私の仕様用途にはばっちりあっていたので使っていて非常に楽でした。
むしろ、もとのテストがvirtualenvを考えない作りで書かれていたので、動くように書き直す方が大変でしたOTZ

まとめ

複数バージョンでのテストが楽になるので、toxはライブラリ作者には非常に福音となるツールになると思います。
テストはきちんと書きましょうね :-)

その他

というわけで、pyuvの作者にtox化したテストをPull/Requestしたところ取り込んでもらえました。
これで今年2勝目だ!作者さんに喜んでもらえたみたいですげー嬉しい。
https://github.com/saghul/pyuv/pull/6

*1: 2.6以降しか対応してない and テスト以外はCAPIのみ