pythonのテストにpytestを使ってみた

April 5, 2013 - python

pytestを使い始めました。

まだまだ機能は把握しきれていませんが、良いと思ったことは3つ。

  1. テストがコケた箇所のコードがレポート内容に表示される
  2. テスト対象を初期化したものの受け渡し方をスマートにできる
  3. pytest.vimがなかなか使える

1.テストがコケた箇所のコードがレポート内容に表示される

これが巷でよく聞く一番のメリットかとは思いますが、コケたときの情報が全然違います。 pytestはかなり詳細に表示してくれるので、レポートの内容だけでどこをどう直せば良いか把握できます。

unittestの実行結果(-vオプション付き)

unittest

pytestの実行結果(-vオプション付き)

pytest

文字列比較の場合は差分表示してくれたりするので便利です。

2. テスト対象を初期化したものの受け渡し方をスマートにできる

これが結構良い感じだと思いました。

かなり単純なクラスを対象にして例を書きます。

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

class Hoge(object):

    def __init__(self, v):
        self.val = v

    def update(self, v):
        self.val = v

python同梱のunittestで書く

こんな感じで、self.hogeを使ってテスト対象を受け渡します。

# -*- coding: utf-8 -*-
from hoge import Hoge
import unittest

class TestHoge1(unittest.TestCase):

    def setUp(self):
        self.hoge = Hoge(1)

    def test_type(self):
        self.assertIsInstance(self.hoge, Hoge)

    def test_val(self):
        self.assertEqual(self.hoge.val, 1)

        self.hoge.update('hoge')
        self.assertEqual(self.hoge.val, 'hige')

if __name__ == '__main__':
    unittest.main()

pytestで書くとこんな感じになります。

# -*- coding: utf-8 -*-
from hoge import Hoge
import pytest

class TestHoge1(object):

    def pytest_funcarg__hoge(request):
        return Hoge(1)

    def test_type(self, hoge):
        assert isinstance(hoge, Hoge)

    def test_val(self, hoge):
        assert hoge.val == 1

        hoge.update('hoge')
        assert hoge.val == 'hige'

if __name__ == '__main__':
    pytest.main()

何が良いかっていうと、各テストメソッドで必要な初期化済みHogeインスタンスを、pytest_funcarghoge()で作って渡してやることができます。pytest_funcargNAMEを定義すれば、各テストメソッドでNAMEとして引数にとることができるわけです。(テスト関数 (funcargs) にオブジェクトを注入)

unittest.TestCaseのsetUpを使う場合、self.hogeに一旦入れてやらないといけないし、各テストメソッドではself.hogeでアクセスする必要も出てきます。

見た目が簡潔になるのはとても良いことです。

3. pytest.vimがなかなか使える

vimのプラグインにpytest.vimっていうのがありました。 これもなかなか使い勝手が良いです。

詳しくは下記動画を御覧ください。

pytestの概要は以下スライドにて。

Funcargs & other fun with pytest from Brianna Laugher
他の機能は触りながらおいおい掴んでいければなと。