Python で書く代数 - pytest で test class 編

前回 は pytest を使ってパラメータ化されたテストを実行しました.

実際に使ったテスト対象コードは, 群を Python で実装したコードでした. ABC モジュールと pytest によるテストを使って, 代数の公理的な定義を擬似的に表現しました.

ただし前回のテストコードではテスト関数が多く, 分類したい気持ちになってきます.

pytest のドキュメント を眺めると, 2.4.5 Parametrizing test methods through per-class configuration にクラスを使ってテスト関数をまとめる方法が書いてあります. 早速これを使います.

test hook

ここで使用するのはテストの前に実行される pytest_generate_tests 関数です. この関数でテスト実行前に, モジュールの中にあるクラスとそのメソッドからパラメータ化されたテストを生成しています.

def pytest_generate_tests(metafunc):
    """Collect and parameterize classes in this module as test cases.

    This test-case collecting function ignores module level functions.

    c.f. 2.4.5 Parametrizing test methods through per-class configuration
    """

    if metafunc.cls is None: # ignore module level functions
        return
    funcarglist = metafunc.cls.params[metafunc.function.__name__]
    argnames = list(funcarglist[0])
    metafunc.parametrize(argnames, [[funcargs[name] for name in argnames]
                                    for funcargs in funcarglist])

テストクラスには, テストコードを記述した関数をメソッドとして記述します.

class TestEquality:
    params = {
        'test_equals_reflexive_law': single_params,
        'test_equals_symmetric_law': double_params,
        'test_equals_transitive_law': triple_params
        }

    def test_equals_reflexive_law(self, a):
        assert a == a

    def test_equals_symmetric_law(self, a, b):
        if a == b:
            assert b == a

    def test_equals_transitive_law(self, a, b, c):
        if a == b and b == c:
            assert a == c

パラメータ化されたテストを実装するためにテストクラスには仕掛けが施されています. その仕掛けは params というクラスフィールドで, テストメソッドとそれが使用するパラメータの対応付けが辞書で設定されています. params 辞書の値は辞書のリストになっていて, 個々のテストケースが列挙されています.

single_params = [{'a': a} for a
                 in integer_values +
                 rational_values +
                 intint_values]

(ここでは single_params の書き方だけを載せましたが, モジュール全体は BitBucket のレポジトリ を参照してください)

前回の pytest.mark.parametrize デコレータとはパラメータ値の指定の方法が異るので注意してください.

pytest_generate_tests やその引数 metafunc の裏側については, また調べてブログに書くことにします.

それでは.

Comments

blog comments powered by Disqus

Licenses