2017-08-02 33 views
1

我有一個函數,我正在使用pytest編寫單元測試。唯一的問題是,因爲我正在爲同一個函數編寫多個測試,所以有幾個測試因cachetools.ttl_cache修飾器而失敗。這個裝飾器使得函數在每次運行時都會返回相同的值,從而混淆了測試。這個裝飾器不存在於我測試的函數中,而是存在於我正在測試的函數中調用的函數中。我無法從我測試的函數中刪除這個裝飾器。下面是測試:Pytest單元測試失敗,因爲目標函數具有cachetools.ttl_cache修飾器

@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函數。

對於示例代碼下測試:

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()) 

這將是我的方法(假定pytest> = 3,否則使用yield_fixture裝飾):

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

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

clear_cache燈具使用了產率每次測試後自動使用夾具(autouse=True)在每次測試後執行清理。您也可以使用the request fixture and request.addfinalizer來運行清理功能。

+0

感謝您的建議,但是當我運行上述設備時出現此錯誤:'AttributeError:'function'object has no attribute'clear_cache''有沒有其他方法可以清除緩存? –

+0

哎呀,我倒過來了,它是'cache_clear()'。我會更新我的答案。 順便說一句,除非你正在運行不同版本的cachetools,你的例子應該顯示'cachetools.func.ttl_cache'作爲裝飾器。我測試了cachetools版本2.0.0 –

+0

你擊中了頭部。非常感謝 –