2011-11-17 44 views
13

Która metoda jest właściwa do wyśmiewania i testowania kodu, który wyświetla obiekt zwracany przez open(), używając biblioteki mock?Naśmiewanie obiektów plików lub iterables w pythonie

whitelist_data.py:

WHITELIST_FILE = "testdata.txt" 

format_str = lambda s: s.rstrip().lstrip('www.') 
whitelist = None 

with open(WHITELIST_FILE) as whitelist_data: 
    whitelist = set(format_str(line) for line in whitelist_data) 

if not whitelist: 
    raise RuntimeError("Can't read data from %s file" % WHITELIST_FILE) 

def is_whitelisted(substr): 
    return 1 if format_str(substr) in whitelist else 0 

Oto jak próbuję go przetestować.

import unittest 
import mock 

TEST_DATA = """ 
domain1.com 
domain2.com 
domain3.com 
""" 

class TestCheckerFunctions(unittest.TestCase): 

    def test_is_whitelisted_method(self): 
     open_mock = mock.MagicMock() 
     with mock.patch('__builtin__.open',open_mock): 
      manager = open_mock.return_value.__enter__.return_value 
      manager.__iter__ = lambda s: iter(TEST_DATA.splitlines()) 
      from whitelist_data import is_whitelisted 
      self.assertTrue(is_whitelisted('domain1.com')) 

if __name__ == '__main__': 
    unittest.main() 

Wynik python tests.py jest:

$ python tests.py 

E 
====================================================================== 
ERROR: test_is_whitelisted_method (__main__.TestCheckerFunctions) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "tests.py", line 39, in test_is_whitelisted_method 
    from whitelist_data import is_whitelisted 
    File "/Users/supa/Devel/python/whitelist/whitelist_data.py", line 20, in <module> 
    whitelist = set(format_str(line) for line in whitelist_data) 
TypeError: 'Mock' object is not iterable 

---------------------------------------------------------------------- 
Ran 1 test in 0.001s 

UPD: Dzięki Adam, mam ponownie zainstalować biblioteki (pip install -e hg+https://code.google.com/p/mock#egg=mock makiety) i zaktualizowane tests.py. Działa jak marzenie.

Odpowiedz

15

Poszukujesz numeru MagicMock. To obsługuje iterację.

W próbce 0.80beta4, patch zwraca wartość MagicMock. Więc to prosty przykład działa:

import mock 

def foo(): 
    for line in open('myfile'): 
     print line 

@mock.patch('__builtin__.open') 
def test_foo(open_mock): 
    foo() 
    assert open_mock.called 

Jeśli używasz makiety 0.7.x (Wygląda jak Ty), nie sądzę, że można to osiągnąć z patchem sam. Musisz utworzyć makiety oddzielnie, a następnie przekazać go do patcha:

import mock 

def foo(): 
    for line in open('myfile'): 
     print line 

def test_foo(): 
    open_mock = mock.MagicMock() 
    with mock.patch('__builtin__.open', open_mock): 
     foo() 
     assert open_mock.called 

Uwaga - Zabrakło mi te z py.test jednak te same podejścia będzie współpracować z unittest również.

Powiązane problemy