2017-08-02 12 views
1

pytestを使用するための単体テストを書く機能があります。唯一の問題は、同じ関数に対して複数のテストを書いているので、cachetools.ttl_cacheデコレータのために2つのテストが失敗するということです。このデコレータは、関数が実行されるたびに同じ値を返すようにします。このデコレータは、私がテストしている関数には存在しませんが、テストしている関数で呼び出されます。私はテストしている機能からこのデコレータを削除できません。ここでのテストは、次のとおりです。ターゲット関数にcachetools.ttl_cacheデコレータがあるため、Pytestユニットテストが失敗します

@patch('load_balancer.model_helpers.DBSession') 
def test_returns_true_if_split_test_is_external(self, dbsession, group_ctx): 
    group_ctx.group_id = '{}-{}'.format('2222222222', '123456789') 
    split_test = Mock() 
    split_test.state = 'external' 
    config = { 
     'query.return_value.filter.return_value.first.return_value': split_test 
    } 
    dbsession.configure_mock(**config) 
    assert group_ctx.is_in_variation_group('foo') == True 

そしてここでは、テスト対象の関数である。

def is_in_variation_group(self, split_test=None): 
    try: 
     split_test = get_split_test(split_test) # This function has the 
     #decorator 
     log.info('Split test {} is set to {}'.format(split_test.name, 
                split_test.state)) 
     if not split_test or split_test.state == 'off': 
      return False 

     phone_number = int(self.group_id.split('-')[0]) 
     if split_test.state == 'internal': 
      return True if str(phone_number) in INTERNAL_GUINEA_PIGS else False 
     if split_test.state == 'external': 
      return True if phone_number % 2 == 0 else False 
    except Exception as e: 
     log.warning("A {} occurred while evaluating membership into {}'s variation " 
        "group".format(e.__class__.__name__, split_test)) 

スプリットテスト関数を取得します。

@cachetools.ttl_cache(maxsize=1024, ttl=60) 
    def get_split_test(name): 
     return (DBSession.query(SplitTest) 
       .filter(SplitTest.name == name) 
       .first()) 

どのように私はそれはので、このキャッシュデコレータがあることを確認することができます無視される?どのような助けも大いにありがたいです

+0

テストを実行する前に 'cachetools'をパッチし、' ttl_cache'を何もキャッシュしない関数に置き換える必要があると思います。 – phd

答えて

1

各テストの実行後に関数のキャッシュをクリアすることをお勧めします。

cachetools documentationはこれについて言及していませんが、the source codeからは、cache_clearの機能を公開しているようです。

試験の下にコード例について

clear_cache固定具が降伏を使用すること

@pytest.fixture(autouse=True) 
def clear_cache(): 
    yield 
    get_split_test.cache_clear() 

def test_foo(): 
    pass # Test your function like normal. 

import cachetools.func 

@cachetools.func.ttl_cache(maxsize=1024, ttl=60) 
def get_split_test(name): 
    return (DBSession.query(SplitTest) 
      .filter(SplitTest.name == name) 
      .first()) 

これは私のアプローチであろうが(そうでなければyield_fixtureデコレータを使用して、> = 3 pytestを想定します)各テスト後に自動的に使用されるフィクスチャ(autouse=True)を使用して、各テスト後にクリーンアップを実行します。 the request fixture and request.addfinalizerを使用してクリーンアップ機能を実行することもできます。

+0

あなたの提案に感謝しますが、上記のフィクスチャを実行するとこのエラーが発生します: 'AttributeError: 'function'オブジェクトに属性 'clear_cache''がありません。キャッシュをクリアする他の方法はありますか? –

+0

おっと、私はそれを逆にしました、それは 'cache_clear()'です。私は私の答えを更新します。 あなたは別のバージョンのcachetoolsを実行していない限り、例ではデコレータとして 'cachetools.func.ttl_cache'が表示されます。私はcachetoolsのバージョン2.0.0を試しました –

+0

あなたは頭の爪を打つ。本当にありがとう –

関連する問題