読者です 読者をやめる 読者になる 読者になる

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

py.testのおすすめプラグイン

サーバーエンジニアの原です。

今回は、Python製テスティングフレームワークpy.testの数あるプラグインのうち、おすすめプラグインをご紹介します。

Python 3.4、pytest 2.7.0を前提とします。

pytest-flakes

pytest-flakesは、Pythonの文法/コードスタイルチェッカーであるpyflakesをテスト時に実行できるようになるプラグインです。

例えばこのような(全く役に立たない)テストコードがあったとします。

# -*- coding: utf-8 -*-

def test():  
    a = 5  
    assert 1+2 == 3

これを--flakesオプションを付けてテストを実行すると、未使用の変数があるため、テストが失敗します。

$ py.test --flakes  
===================================== test session starts ==============================  
platform darwin -- Python 3.4.2 -- py-1.4.27 -- pytest-2.7.1  
rootdir: /Users/hara/work/pytest, inifile:  
plugins: cache, flakes  
collected 2 items  
  
tests/test_app.py F.  
  
========================================== FAILURES ====================================  
_______________________________________ pyflakes-check _________________________________  
/Users/hara/work/pytest/tests/test_app.py:5: UnusedVariable  
local variable 'a' is assigned to but never used  
============================= 1 failed, 1 passed in 0.02 seconds =======================

これにより、CIでコードスタイルもチェックできるようになります。

特定のスタイルチェックを無効化したり、特定のファイルのみにスタイルチェックを実行するなどの設定もできるので、プロジェクトの特性に応じて設定しておくとよいでしょう。

pytest-echo

pytest-echoは、テスト実行時に環境変数やパッケージのバージョンなどを出力するプラグインです。

以下のようなオプションを付けて実行すると、テスト結果に環境変数やパッケージのバージョンなどが含まれるようになります。

$ py.test --echo-env PWD --echo-version pip --echo-version pytest  
================================= test session starts ==================================  
platform darwin -- Python 3.4.2 -- py-1.4.27 -- pytest-2.7.1  
Environment:  
    PWD: /Users/hara/work/pytest  
Package version:  
    pip: 1.5.6  
    pytest: 2.7.1  
rootdir: /Users/hara/work/pytest, inifile:  
plugins: cache, cov, echo, flakes  
collected 1 items  
  
tests/test_app.py .  
  
=============================== 1 passed in 0.02 seconds ===============================

テスト実行環境の情報を出力しておくことで、テスト失敗時の原因追求がしやすくなります。 引数が多くなってしまう場合は、以下のようにpytest.iniのaddoptsに予めオプションを指定しておくと毎回オプションを指定する必要がなくなります。

addopts = --echo-env PWD  
          --echo-version pip  
          --echo-version pytest

pytest-cov

pytest-covは、テスト実行時にテストカバレッジを取得するプラグインです。

--covオプションの後ろには、カバレッジを取得する対象ディレクトリを指定します。

$ py.test tests --cov .  
================================= test session starts ==================================  
platform darwin -- Python 3.4.2 -- py-1.4.27 -- pytest-2.7.1  
rootdir: /Users/hara/work/pytest/tests, inifile:  
plugins: cache, cov, echo, flakes  
collected 1 items  
   
tests/test_app.py .  
------------------- coverage: platform darwin, python 3.4.2-final-0 --------------------  
Name             Stmts   Miss  Cover  
------------------------------------  
sample               2      2     0%  
tests/test_app       3      0   100%  
------------------------------------  
TOTAL                5      2    60%  
   
=============================== 1 passed in 0.03 seconds ===============================

テストの実行結果には影響を与えませんが、テストカバレッジを手軽に取得することができます。

pytest-describe

pytest-describeは、RSpecやJasmineのようなDescribeスタイルと呼ばれるテストコード記法をサポートするプラグインです。

py.testにはクラスを使用することで複数のテスト関数(メソッド)をまとめることができますが、そのクラスにはTestというプレフィックスを付けなければならなかったり、テスト関数(メソッド)ごとにselfを引数に取る必要があったりとスマートに記述することができませんでした。

pytest-describeを使用することで複数のテスト関数を関数でまとめることができるため、特別なルールなしに記述することが可能となっています。

以下に一例を載せます(READMEからの引用です)。

# -*- coding: utf-8 -*-  
import pytest
  
def describe_list():  
  
    @pytest.fixture  
    def list():  
        return []  
  
    def describe_append():  
  
        def adds_to_end_of_list(list):  
            list.append('foo')  
            list.append('bar')  
            assert list == ['foo', 'bar']  
  
    def describe_remove():  
  
        @pytest.fixture  
        def list():  
            return ['foo', 'bar']  
  
        def removes_item_from_list(list):  
            list.remove('foo')  
            assert list == ['bar']

以下のようなテスト結果になります。

$ py.test -v  
================================= test session starts ==================================  
platform darwin -- Python 3.4.2 -- py-1.4.27 -- pytest-2.7.1 -- /Users/hara/.pyenv/versions/engineer_blog/bin/python3.4  
cachedir: /Users/hara/work/pytest/.cache  
rootdir: /Users/hara/work/pytest, inifile:  
plugins: cache, cov, describe, echo, flakes  
collected 2 items  
  
tests/test_list.py::describe_list::describe_append::adds_to_end_of_list PASSED  
tests/test_list.py::describe_list::describe_remove::removes_item_from_list PASSED  
  
=============================== 2 passed in 0.02 seconds ===============================

describeというプレフィックスの関数が、テストをまとめる関数であることを表しています。


このプレフィックスは、pytest.iniにdescribe_prefixesという設定を追加することで自分の好きなように修正することができます。

まとめ

4点のpy.testプラグインをご紹介しました。

Pythonを初めとするLLの良さの一つとして、コンパイルという手順が無いことによるユニットテスト等のフィードバックループの回しやすさが挙げることができます。LLの力を最大限に活かし、より良いユニットテストを行なうためにも、テスト手法の改善に努めていきたいものです。

py.testには他にもプラグインがたくさんあります。こちらにプラグイン一覧がありますので、興味がある方は調べてみてください。