2017-10-24 1 views
1

私はいくつかのテストケースとテスト関数を持っています。そして、テストケースのリストは異なる関数で異なります。これはpytest.mark.parametrizeで簡単に行うことができます。余分に必要なのは、リソース(私の場合はファイル)をロードすることです。このファイルをテストセッションごとに一度だけロードしてキャッシュに入れたいと思います。pytest異なるケースのパラメータ化されたフィクスチャ

以下は、私が望むものを例示したものです。動作していますが、pytest fixturesや他のキャッシュメカニズムを使用して自分自身でキャッシュを行う必要がなく、各テスト関数にpars=load_file(pars)行を持つ方法を見つけたいと思います。

誰かがpytestでこれを行う方法を説明できますか?

import pytest 

case_1 = dict(label='case_1', spam=1) 
case_2 = dict(label='case_2', spam=2) 
case_3 = dict(label='case_3', spam=3) 

_cache = {} 


def load_file(pars): 
    if pars['label'] in _cache: 
     print('load_file from cache', pars) 
     return _cache[pars['label']] 
    else: 
     print('load_file loading', pars) 
     pars['file'] = pars['label'] + ' spam!' 
     _cache[pars['label']] = pars 
     return pars 


@pytest.mark.parametrize('pars', [case_1, case_2]) 
def test_a(pars): 
    pars = load_file(pars) 
    print('test_a', pars) 


@pytest.mark.parametrize('pars', [case_2, case_3]) 
def test_b(pars): 
    pars = load_file(pars) 
    print('test_b', pars) 


@pytest.mark.parametrize('pars', [case1, case_2, case_3]) 
def test_c(pars): 
    pars = load_file(pars) 
    print('test_c', pars) 

### more tests here for various combinations of test cases 

答えて

0

最初の明らかな解決策は、セッションスコープのフィクスチャを使用することです。ただし、テストファイルの再構築が必要であり、事前にすべての既知のファイルをロードする必要があります。

import pytest 

@pytest.fixture(scope='session') 
def pars_all(): 
    cache = {} 
    for case in [case_1, case_2, case_3]: 
     cache[case['label']] = 'case {} content'.format(case) 

    yield cache 

    # optionally destroy or unload or unlock here. 

@pytest.fixture(scope='function') 
def pars(request, pars_all): 
    label = request.param 
    yield pars_all[label] 

@pytest.mark.parametrize('pars', ['case_1', 'case_2'], indirect=True) 
def test(pars): 
    pass 

間接的パラメータ化に注意してください。これは、代わりにparsフィクスチャが用意され、パラメータ値がrequest.paramになることを意味します。パラメータ名とフィクスチャは同じ名前でなければなりません。

セッションスコープのフィクスチャ(またはモジュールスコープまたは望むならクラススコープ)は、すべてのテストに対して1回だけ準備されます。より広い範囲の器具は、より狭い範囲の器具または同じスコープの器具に使用できますが、反対方向には使用できないことに注意することが重要です。

例は、その明確に定義されていない場合は、それが簡単に同じで、単にキャッシュがオンデマンドで読み込まれる:それはセッションですので{}オブジェクトは、一度だけ作成されていることを

import pytest 

@pytest.fixture(scope='session') 
def pars_all(): 
    yield {} 

@pytest.fixture(scope='function') 
def pars(request, pars_all): 
    label = request.param 
    if label not in pars_all: 
     print('[[[{}]]]'.format(request.param)) 
     pars_all[label] = 'content of {}'.format(label) 
    yield pars_all[label] 

@pytest.mark.parametrize('pars', ['case_1', 'case_2'], indirect=True) 
def test_1(pars): 
    print(pars) 

@pytest.mark.parametrize('pars', ['case_1', 'case_3'], indirect=True) 
def test_2(pars): 
    print(pars) 

注意、スコープは、すべてのテストで共有されます& callspecs。だから、ある灯具が何かを加えると、他の灯具もそれを見るでしょう。どのようにcase_1test_2で再利用されているかを知ることができます:

$ pytest -s -v -ra test_me.py 
======= test session starts ========== 
... 
collected 4 items                     

test_me.py::test_1[case_1] [[[case_1]]] 
content of case_1 
PASSED 
test_me.py::test_1[case_2] [[[case_2]]] 
content of case_2 
PASSED 
test_me.py::test_2[case_1] content of case_1 
PASSED 
test_me.py::test_2[case_3] [[[case_3]]] 
content of case_3 
PASSED 

======== 4 passed in 0.01 seconds ========== 
関連する問題