趣味プログラマです、こんにちわ。一応生きてます。
さて、Pythonista各位におかれましてはmoratoriumをエンジョイされていますでしょうか。そろそろライブラリも著名なものはPython3に対応してきましたし、そろそろ本格的にPython3、となっているころ合いですね。というか、Python3に対応してないとちょっと恥ずかしくなってきましたね。
とはいえ、Python2は根強く残るでしょう。というわけでPython2とPython3両方で動くコードを書きましょう。テストも書くのは当たり前ですし、せっかくなのでCIもしましょう。
と私も最近思ったので快適に開発を進めるための環境についてメモです。
- github : 言わずもがなですね。
- travis : githubと連携してCIできるサービス。P言語にも対応していて、最近アツいです。
- tox : 複数のPython処理系でvirtualenvを作りテストを流せる。
- distribute : 改良版setuptools。
- pytest : toxと親和性の高いテストツール。noseでもよいですが私はpytestを押します。
Python2とPython3のインストール
あたりまえですが、Python2系とPython3系両方入れておきましょう。
toxのインストール
さて、早速toxを入れていくわけですがこれにはPython2系を使います。
$ wget http://python-distribute.org/distribute_setup.py$ python27 distribute_setup.py$ easy_install virtualenv tox
簡単ですね。
プロジェクトを始める - ファイル・ディレクトリ構成
次に、プロジェクトの基本形を作りましょう。私は以下のような構成にしています。
/+ - .tox : toxにより生成されるディレクトリ。+ - docs : ドキュメント系はココ。+ - source : ドキュメントのソース。+ - build+ - html(link to gh-pages): sphinxで生成されたHTMLドキュメント。gh-pagesブランチへのリンク。+ - src : ソースファイル類。+ - プロジェクト名+ - tests- tox.ini : tox設定ファイル。- .travis.yml : travis設定ファイル。- setup.py : セットアップスクリプト。- MANIFEST.in : 配布パッケージ生成用定義ファイル。- README.rst : 私を読んで。- CHANGES.rst : 変更履歴。
普通です。ポイントはdocs/build/htmlをgh-pagesへのリンクにすること。これでドキュメントの管理が非常に楽になります。
tox.iniの作成
tox.iniに依存関係と、どの処理系でテストするか、テストはなにを使ってやるかを書きましょう。だいたいの場合、それだけで十分です。
[tox]envlist = py27,py32[testenv]changedir=src/testsdeps=pytestpytest-covその他依存パッケージcommands=py.test \-rxs \--cov-report term-missing \--cov テスト対象パッケージ名\--basetemp={envtmpdir} \[]
見ての通りの内容です。Pytnon27とPython32でテストします、と。この時処理系のパス(python.exeやpython27などのパス)はOSごとにデフォルトの場所が使われます。--configureでprefixを指定していたり、Windowsで別フォルダにインストールしている場合は以下のようにします。
[tox]envlist = py27,py32[testenv:py27]basepython=処理系へのパス[testenv:py32]basepython=処理系へのパス[testenv]changedir=src/testsdeps=pytestpytest-covその他依存パッケージcommands=py.test \-rxs \--cov-report term-missing \--cov テスト対象パッケージ名\--basetemp={envtmpdir} \[]
とりあえず開発
とりあえず何かコードを書いて、テストも書きましょう。
toxでテスト
ではtoxでテストしましょう。tox.iniがあるディレクトリに移動してから
$ tox
これで
- それぞれの処理系のvirtualenvの作成
- 依存ライブラリのインストール
- テストの実行
が行われ、結果が表示されます。py27だけ流したい場合はtox -e py27とするか環境変数TOXENV=py27を設定したうえでtoxとすればOK.
拙作のwebフレームワークraypheですと以下のような感じです(長いのでpy32の結果のみ)。pytest-covを入れているのでC0カバレッジも表示されます。
_________________________________________________________________________________________ [tox sdist] __________________________________________________________________________________________[TOX] ***creating sdist package[TOX] /home/yuin/github/rayphe$ /opt/python2.7.2/bin/python2.7 setup.py sdist --formats=zip --dist-dir .tox/dist >.tox/log/0.log[TOX] ***copying new sdistfile to '/home/yuin/.tox/distshare/rayphe-0.4.0.zip'______________________________________________________________________________________ [tox testenv:py32] ______________________________________________________________________________________[TOX] ***creating virtualenv py32[TOX] /home/yuin/github/rayphe/.tox$ /opt/python3.2.2/bin/python3.2 /opt/python2.7.2/lib/python2.7/site-packages/virtualenv-1.7.1.2-py2.7.egg/virtualenv.py --no-site-packages py32 >py32/log/0.log[TOX] ***installing dependencies: pytest, pytest-cov, webtest, sphinx[TOX] /home/yuin/github/rayphe/.tox/py32/log$ ../bin/pip install --download-cache=/home/yuin/github/rayphe/.tox/_download pytest pytest-cov webtest sphinx >1.log[TOX] ***installing sdist[TOX] /home/yuin/github/rayphe/.tox/py32/log$ ../bin/pip install --download-cache=/home/yuin/github/rayphe/.tox/_download /home/yuin/github/rayphe/.tox/dist/rayphe-0.4.0.zip >2.log[TOX] /home/yuin/github/rayphe/src/tests$ ../../.tox/py32/bin/py.test -rxs --cov-report term-missing --cov rayphe --basetemp=/home/yuin/github/rayphe/.tox/py32/tmp===================================================================================== test session starts ======================================================================================platform linux2 -- Python 3.2.2 -- pytest-2.2.3collected 120 itemstest_application.py ........................test_async_extension.py ssstest_database.py .......test_defaultattrdict.py .....test_extension.py .test_functions.py .........test_hookable.py .....test_request.py .....................test_response.py ...............test_session.py ............test_staticfile_extension.py .....test_templating.py .............----------------------------------------------------------------------- coverage: platform linux2, python 3.2.2-final-0 ------------------------------------------------------------------------Name Stmts Miss Cover Missing----------------------------------------------------------------------------/home/yuin/github/rayphe/src/rayphe/__init__ 1648 190 88% 82, 259, 807-808, 824-839, 842-888, 892-901, 909-917, 925-933, 946-954, 1408, 1509, 1595-1597, 1934-1943, 1973, 2033-2063, 2088-2089, 2547-2560, 2563-2571, 2574-2575, 2579-2585, 2589, 2593-2596, 2600, 2604-2615/home/yuin/github/rayphe/src/rayphe/compat 98 42 57% 11-13, 17, 19-20, 67-118----------------------------------------------------------------------------TOTAL 1746 232 87%=================================================================================== short test summary info ====================================================================================SKIP [3] /home/yuin/github/rayphe/.tox/py32/lib/python3.2/site-packages/_pytest/skipping.py:118: condition: SkipIf._no_gevent============================================================================ 117 passed, 3 skipped in 14.81 seconds ============================================================================________________________________________________________________________________________ [tox summary] _________________________________________________________________________________________
.travis.ymlの作成
無事、複数のインタプリタでテストできました。次はCIです。Travis CIを使うと、githubにpushしたタイミングでビルド&テストが自動でできます。
まずは、Travis CIにgithubのアカウントでログインして、対象のレポジトリでCIを有効にします。
次に、Travis CIでのビルド&テスト設定を.travis.ymlに書きます。ここではtoxを使っていますから、以下のようになります。
language: pythonenv:- TOXENV=py27- TOXENV=py32install:- pip install --use-mirrors toxscript: tox
TOXENVでテストする環境を指定します。今回の例ではpy27とpy32です。
これでgithubにpushするとTravis CIが動くようになりました。テストが終わると以下のようにそれぞれの環境が緑色になります。
Travis CI + tox快適です
ガンガンPython3対応をしましょう!