2015-01-19 24 views
6

Nie jestem nie mówi o funkcji Parameterizing a fixture, która pozwala na uruchomienie urządzenia wiele razy dla zakodowanego zestawu parametrów.Jakikolwiek sposób przekazywania parametrów do urządzenia pytest?

Mam wiele testów, które następują wzór takiego:

httpcode = 401 # this is different per call 
message = 'some message' # this is different per call 
url = 'some url' # this is different per call 


mock_req = mock.MagicMock(spec_set=urllib2.Request) 
with mock.patch('package.module.urllib2.urlopen', autospec=True) as mock_urlopen, \ 
    mock.patch('package.module.urllib2.Request', autospec=True) as mock_request: 
    mock_request.return_value = mock_req 
    mock_urlopen.side_effect = urllib2.HTTPError(url, httpcode, message, {}, None) 
    connection = MyClass() 
    with pytest.raises(MyException): 
     connection.some_function() # this changes 

Zasadniczo mam klasy, która jest klientem API i zawiera niestandardowe, znaczące wyjątki owinąć urllib2 błędy w czymś API specyficznych. Tak więc mam ten jeden wzór - łatanie niektórych metod i ustawianie efektów ubocznych na jednym z nich. Używam go w prawdopodobnie kilkunastu różnych testach, a jedyne różnice to trzy zmienne, które są używane w części side_effect i metoda MyClass(), którą nazywam.

Czy jest jakiś sposób, aby uczynić to pytonem i przekazać te zmienne?

Odpowiedz

15

Można użyć pośrednich Spotkań parametryzacji http://pytest.org/latest/example/parametrize.html#deferring-the-setup-of-parametrized-resources

@pytest.fixture() 
def your_fixture(request): 
    httpcode, message, url = request.param 
    mock_req = mock.MagicMock(spec_set=urllib2.Request) 
    with mock.patch('package.module.urllib2.urlopen', autospec=True) as mock_urlopen, \ 
     mock.patch('package.module.urllib2.Request', autospec=True) as mock_request: 
     mock_request.return_value = mock_req 
     mock_urlopen.side_effect = urllib2.HTTPError(url, httpcode, message, {}, None) 
     connection = MyClass() 
     with pytest.raises(MyException): 
      connection.some_function() # this changes 


@pytest.mark.parametrize('your_fixture', [ 
    (403, 'some message', 'some url') 
], indirect=True) 
def test(your_fixture): 
    ... 

i your_fixture będą uruchamiane przed testem z żądanych params

+0

Powiedziałem, że to nie jest to, czego chcę ... Nie chcę, aby urządzenie było tworzone wiele razy, po prostu chcę przekazać do niego parametry. –

+1

W moim kodzie urządzenie działa tylko raz w teście. W rzeczywistości mój kod działa tak samo jak twój. Różnica polega na przekazywaniu parametrów. Jeśli chcesz wygenerować parametry w teście, a następnie przekazać je do urządzenia - twój kod to tylko sposób na zrobienie tego. Jeśli parametry są wstępnie zdefiniowane w teście, mój kod również pasuje do –

+0

OK, wystarczy. –

6

Zrobiłem grono więcej badań na ten temat od opublikowania moje pytanie, a najlepszym Mogę wymyślić:

Lampy nie działają w ten sposób. Wystarczy użyć zwykłej funkcji, a mianowicie:

def my_fixture(httpcode, message, url): 
    mock_req = mock.MagicMock(spec_set=urllib2.Request) 
    with mock.patch('package.module.urllib2.urlopen', autospec=True) as mock_urlopen, \ 
     mock.patch('package.module.urllib2.Request', autospec=True) as mock_request: 
     mock_request.return_value = mock_req 
     mock_urlopen.side_effect = urllib2.HTTPError(url, httpcode, message, {}, None) 
     connection = MyClass() 
     return (connection, mock_request, mock_urlopen) 

def test_something(): 
    connection, mock_req, mock_urlopen = my_fixture(401, 'some message', 'some url') 
    with pytest.raises(MyException): 
     connection.some_function() # this changes 
1

wiem, że to jest stary, ale może to pomoże komuś, kto potyka na to znowu

@pytest.fixture 
def data_patcher(request): 

    def get_output_test_data(filename, as_of_date=None): 
     # a bunch of stuff to configure output 
     return output 

    def teardown(): 
     pass 

    request.addfinalizer(teardown) 

    return get_output_test_data 

a następnie wewnątrz funkcji:

with patch('function to patch', new=data_patcher):