Bawiłem się jedynie MagicMock-iem, chociaż w bibliotece istnieje coś takiego jak Mock. Poniżej trzy, testy do trzech metod, których przetestowanie sprawiło mi problemy. Na początku ważna kwestia, MagicMock jest klasą, więc tworząc obiekt mock-a, należy pamiętać o nawiasach, aby wywołać konstruktor! Za pomocą parametru spec, wskazujemy też klasę, z które zaczerpnięty zostanie interfejs mock-owanej klasy.
Pierwszy z testów (test_show), miał wykazać sekwencyjne zawołanie metody Deciratir.rich(). Robi się to za pomocą dziwnego obiektu call, którego nasyca się atrybutami z jakimi zostanie wywołana mock-owana metoda. Inna kwestia to wartość zwracana. Za pomocą pola return_value, można ustalić jaka wartość będzie zawsze zwracana z mocka.
Drugi test, pokazuje w działaniu jedną z metod (asercji), dostarczoną przez bibliotekę. Tutaj oczekujemy, że metoda zostanie zawołana tylko raz z określonym parametrem (assert_called_once_with).
Trzeci test, również bada, czy mock-i zostały zawołane z określonymi parametrami, ale tym razem, każdy z nich zwraca inną wartość, aby przetestować bardzo specyficzną ścieżkę wykonania programu. Służy temu pole side_effect, z którego pobierane są kolejne zwracane wartości (można też podobna włożyć tam metody, które zostaną zawołane).
#!/usr/bin/env python3
# python -m unittest discover --pattern=test_unittest.py
import unittest
from unittest.mock import MagicMock
from unittest.mock import call
class TestPrinter(unittest.TestCase):
def setUp(self):
self.decorMock = MagicMock(spec=Decorator, name='decorator')()
def test_show(self):
self.decorMock.rich.return_value = True
sut = Printer(self.decorMock)
sut.show('asdf')
expected = [call.decorMock.attribute.rich('asdf'),
call.decorMock.attribute.rich('xxx')]
self.assertTrue(self.decorMock.rich.mock_calls == expected)
def test_show_once(self):
sut = Printer(self.decorMock)
sut.show_once()
self.decorMock.rich.assert_called_once_with('once')
def test_show_comlicated(self):
self.decorMock.rich.side_effect = [False, True]
sut = Printer(self.decorMock)
self.assertEqual(sut.show_complicated(), 2)
expected = [call.decorMock.attribute.rich('a'),
call.decorMock.attribute.rich('b')]
self.assertTrue(self.decorMock.rich.mock_calls == expected)
class Decorator():
def rich(self, descr):
raise Exception()
class Printer():
def __init__(self, decorator):
self._decorator = decorator
def show(self, descr):
self._decorator.rich(descr)
if self._decorator.rich('xxx'):
return True
return False
def show_once(self):
self._decorator.rich('once')
def show_complicated(self):
if self._decorator.rich('a'):
return 1
if self._decorator.rich('b'):
return 2
return 0
Z otwartych kwestii, wciąż nie wiem jak testować dowolne parametry przekazywane do mock-a. Testowanie biblioteki do testów trwa nadal.
Brak komentarzy:
Prześlij komentarz