generating test parameters using wrapper for collected partial parameters like test scenario, without metafunc
pytest | URL |
---|---|
xdistの-nオプションについて | https://qiita.com/cielavenir/items/3f3319f3fa153c16c703 |
デコレータの作り方 | https://qiita.com/cielavenir/items/542f7eaa612c6bb9ed90 |
デコレータに引数を渡す | https://qiita.com/cielavenir/items/2c971ca4bc138c375d17 |
部分テストパラメータの値を使ってテストパラメータを生成する | https://qiita.com/cielavenir/items/ce328313a9f0f498cbcb |
pytestのfixtureを別の箇所でライブラリとして読み込みたい (当該環境にはpytestが存在しない可能性がある) |
https://qiita.com/cielavenir/items/8144774a6ac2eca2e2ce |
基底データをさまざまな角度からテストしたいということはそれなりにあると思う。
何も考えずに作ると、基底データをパラメータにして、テストの中でループさせることになると思う。
loop.py
import pytest
def collect_data():
return [1,2,3]
@pytest.mark.parametrize('num',collect_data())
def test_0(num):
for idx in range(0,num):
print([idx,num])
@pytest.mark.parametrize('num',collect_data())
def test_1(num):
for idx in range(1,num):
print([idx,num])
しかし、これはループ中にテストが失敗した場合にテストケース全体が失敗してしまうため、テストの作法としてはよろしくないとされる。
基底データを受け取ってテストパラメータを生成する関数を噛ませればよいのではないかと思った。
wrap.py
import pytest
def collect_data():
return [1,2,3]
def collect_test0():
tests = []
for num in collect_data():
for idx in range(0,num):
tests.append((idx,num))
return tests
def collect_test1():
tests = []
for num in collect_data():
for idx in range(1,num):
tests.append((idx,num))
return tests
@pytest.mark.parametrize(('idx','num'),collect_test0())
def test_0(idx,num):
print([idx,num])
@pytest.mark.parametrize(('idx','num'),collect_test1())
def test_1(idx,num):
print([idx,num])
行数は長くなったが、実際にはcollect_test0/1の処理はより複雑になると思われるので(たとえばcollect_dataがdatとjsonを返してtest1でだけjsonを読むとか)、誤差の範囲だと思われる。
2つのテストの出力は同じだが、前者のテスト数は6、後者のテスト数は9になった。idxについてもテストケースが分離されたことが確認できた。
collected 6 items
loop.py [0, 1]
.[0, 2]
[1, 2]
.[0, 3]
[1, 3]
[2, 3]
..[1, 2]
.[1, 3]
[2, 3]
.
collected 9 items
wrap.py [0, 1]
.[0, 2]
.[1, 2]
.[0, 3]
.[1, 3]
.[2, 3]
.[1, 2]
.[1, 3]
.[2, 3]
.
余談:これぐらいテスター的には常識なのかもしれないが、私はこの方法を思いつくのに半日かかってしまった。