Co to jest kpina? .
unit-testing
mocking
masoud ramezani
źródło
źródło
Odpowiedzi:
Prolog: Jeśli spojrzeć na rzeczownik makiety w słowniku okaże się, że jedna z definicji tego słowa jest czymś wykonany jako imitację .
Wyśmiewanie jest stosowane głównie w testach jednostkowych. Testowany obiekt może być zależny od innych (złożonych) obiektów. Aby wyizolować zachowanie obiektu, należy zastąpić inne obiekty próbnymi symulacjami zachowania rzeczywistych obiektów. Jest to przydatne, jeśli rzeczywiste obiekty nie są praktyczne do włączenia do testu jednostkowego.
Krótko mówiąc, kpina to tworzenie obiektów symulujących zachowanie rzeczywistych obiektów.
Czasami może chcesz odróżnić wyśmianie w przeciwieństwie do stubbing . Być może istnieje pewien spór na ten temat, ale moja definicja odcinka jest „minimalnym” symulowanym obiektem. Kod pośredniczący implementuje zachowanie wystarczające, aby umożliwić testowanemu obiektowi wykonanie testu.
Makieta jest jak kod pośredniczący, ale test sprawdzi również, czy testowany obiekt wywołuje makietę zgodnie z oczekiwaniami. Część testu polega na sprawdzeniu, czy próbka została użyta poprawnie.
Podam przykład: możesz skasować bazę danych, wdrażając prostą strukturę pamięci do przechowywania rekordów. Testowany obiekt może następnie odczytywać i zapisywać rekordy w kodzie bazy danych, aby umożliwić mu wykonanie testu. Może to przetestować pewne zachowanie obiektu niezwiązanego z bazą danych, a kod pośredniczący bazy danych zostałby dołączony, aby umożliwić uruchomienie testu.
Jeśli zamiast tego chcesz sprawdzić, czy testowany obiekt zapisuje określone dane w bazie danych, będziesz musiał wyśmiewać bazę danych. Twój test obejmowałby następnie twierdzenia o tym, co zostało zapisane w makiecie bazy danych.
źródło
Inne odpowiedzi wyjaśniają, czym jest drwina. Pozwól, że przeprowadzę cię przez różne przykłady . I uwierz mi, w rzeczywistości jest to o wiele prostsze niż myślisz.
tl; dr Jest to przykład oryginalnej klasy. Wprowadzono do niego inne dane, dzięki czemu unikniesz testowania wtryskiwanych części i skupisz się wyłącznie na testowaniu szczegółów implementacyjnych twojej klasy / funkcji.
Prosty przykład:
Jak widać, nie testuję LineA, tj. Nie sprawdzam poprawności parametrów wejściowych. Nie sprawdzam, czy num1, num2 są liczbami całkowitymi. Nie mam przeciwko temu żadnych zapewnień.
Testuję tylko, aby sprawdzić, czy LineB (moja implementacja ) poda wyśmiewane wartości
1
i5
działa zgodnie z oczekiwaniami.Oczywiście w prawdziwym słowie może to stać się znacznie bardziej złożone. Parametry mogą być niestandardowym obiektem, takim jak Osoba, Adres lub szczegóły implementacji mogą być więcej niż jednym
+
. Ale logika testowania byłaby taka sama.Przykład niekodujący:
Załóżmy, że budujesz maszynę, która identyfikuje typ i markę urządzeń elektronicznych do ochrony lotniska. Maszyna robi to, przetwarzając to, co widzi za pomocą aparatu.
Teraz twój kierownik wchodzi do drzwi i prosi o przetestowanie ich w jednostce.
Następnie jako programista możesz przynieść 1000 prawdziwych obiektów, takich jak MacBook pro, Google Nexus, banan, iPad itp. I przetestować i sprawdzić, czy wszystko działa.
Ale możesz także użyć wyśmiewanych obiektów, takich jak identycznie wyglądający MacBook pro (bez prawdziwych części wewnętrznych) lub plastikowy banan przed nim. Możesz zaoszczędzić na inwestowaniu w 1000 prawdziwych laptopów i gnijących bananów.
Chodzi o to, że nie próbujesz sprawdzić, czy banan jest fałszywy, czy nie. Ani testowania, czy laptop jest fałszywy, czy nie. Wszystko robisz testuje jeśli urządzenie raz widzi banana byłoby powiedzieć,
not an electronic device
a dla MacBooka Pro byłoby powiedzieć:Laptop, Apple
. Dla maszyny wynik jego wykrycia powinien być taki sam dla fałszywej / wyśmiewanej elektroniki i prawdziwej elektronikiPowyższa logika dotyczy również testowania jednostkowego rzeczywistego kodu. Ta funkcja powinna działać tak samo z rzeczywistymi wartościami uzyskanymi z rzeczywistych danych wejściowych (i interakcji) lub wyśmiewanymiwartości wprowadzane podczas testów jednostkowych. I podobnie jak oszczędzasz się przed używaniem prawdziwego banana lub MacBooka, dzięki testom jednostkowym (i kpinom) oszczędzasz siebie przed koniecznością zrobienia czegoś, co spowoduje, że Twój serwer zwróci kod statusu 500, 403, 200 itd. (Wymuszanie twój serwer wyzwala 500 tylko wtedy, gdy serwer jest wyłączony, a 200 gdy serwer jest włączony. Trudno jest uruchomić 100 testów sieciowych, jeśli musisz stale czekać 10 sekund między przełączaniem serwera w górę i w dół). Zamiast tego wstrzykujesz / wyśmiewasz odpowiedź kodem stanu 500, 200, 403 itd. I testujesz swoją jednostkę / funkcję za pomocą wstrzykniętej / wyśmiewanej wartości.
Przykład kodowania:
Powiedzmy, że piszesz aplikację na iOS i mają zadanie calls.Your sieć jest przetestować swoją aplikację. Testowanie / ustalanie, czy połączenia sieciowe działają zgodnie z oczekiwaniami, NIE JEST TO TWOJA ODPOWIEDZIALNOŚĆ. Testowanie go jest obowiązkiem innej strony (zespołu serwerów). Musisz usunąć tę zależność (sieciową), a mimo to kontynuować testowanie całego kodu, który działa wokół niej.
Połączenie sieciowe może zwrócić różne kody stanu 404, 500, 200, 303 itp. Z odpowiedzią JSON.
Twoja aplikacja powinna działać na wszystkie z nich (w przypadku błędów aplikacja powinna zgłosić oczekiwany błąd). To, co robisz z szyderstwem, to tworzenie „wymyślonych - podobnych do rzeczywistych” odpowiedzi sieciowych (takich jak kod 200 z plikiem JSON) i testowanie kodu bez „wykonywania prawdziwego połączenia sieciowego i oczekiwania na odpowiedź sieci”. Ręczne kodowanie / zwracanie odpowiedzi sieciowej dla WSZYSTKICH odpowiedzi sieciowych i sprawdzanie, czy aplikacja działa zgodnie z oczekiwaniami. (ty nigdy zakładać / przetestować 200 z błędnych danych, ponieważ to nie jest obowiązkiem, obowiązkiem jest, aby przetestować swoją aplikację z prawidłowym 200, lub w przypadku 400, 500, przetestować, czy aplikacja generuje właściwą błąd)
To tworzenie wymyślonego - podobnego do prawdziwego - nazywa się kpiną.
Aby to zrobić, nie możesz użyć oryginalnego kodu (oryginalny kod nie ma wstępnie wstawionych odpowiedzi, prawda?). Państwo musi dodać coś do niego, wstrzyknąć / wkładkę, która danych manekina, który normalnie nie jest potrzebne (lub część swojej klasie).
Więc utworzyć instancję oryginalnej klasy i dodać cokolwiek (tutaj jest sieć httpResponse, danych lub w przypadku awarii, przechodzą prawidłową errorString, httpResponse), należy do niego, a następnie przetestować szydzili klasę.
Krótko mówiąc, kpiny mają uprościć i ograniczyć to, co testujesz, a także nakarmić to, na czym polega klasa. W tym przykładzie unikają badania sieć nazywa się , a zamiast tego testu , czy aplikacja działa zgodnie z oczekiwaniami z wprowadzoną wyjść / odpowiedzi - przez wyśmianie klas
Nie trzeba dodawać, że każdą odpowiedź sieci testujesz osobno.
Teraz pytanie, które zawsze miałem na myśli, brzmiało: kontrakty / punkty końcowe i w zasadzie odpowiedź JSON moich API jest stale aktualizowana. Jak napisać testy jednostkowe, które biorą to pod uwagę?
Aby rozwinąć więcej na ten temat: powiedzmy, że model wymaga klucza / pola o nazwie
username
. Testujesz to, a test kończy się pomyślnie. 2 tygodnie później backend zmienia nazwę klucza naid
. Twoje testy wciąż mija. dobrze? albo nie?Czy to na deweloperze backendu spoczywa obowiązek aktualizowania próbnych wersji. Czy powinno być częścią naszej umowy, że dostarczają zaktualizowane symulacje?
Odpowiedzią na powyższy problem jest to, że: testy jednostkowe + proces programowania jako programista po stronie klienta powinien / będzie wychwytywać przestarzałe fałszywe odpowiedzi. Jeśli zapytasz mnie jak? odpowiedź brzmi:
Nasza rzeczywista aplikacja nie powiedzie się (lub nie zawiedzie, ale nie będzie miała pożądanego zachowania) bez użycia zaktualizowanych interfejsów API ... stąd jeśli to się nie powiedzie ... wprowadzimy zmiany w naszym kodzie programistycznym. Co ponownie prowadzi do niepowodzenia naszych testów ... które będziemy musieli poprawić. (W rzeczywistości, jeśli mamy poprawnie wykonać proces TDD, nie powinniśmy pisać żadnego kodu o polu, chyba że napiszemy test dla niego ... i zobaczymy, że się nie powiedzie, a następnie przejdziemy i napiszemy dla niego właściwy kod programistyczny.)
To wszystko oznacza, że backend nie musi mówić: „hej, zaktualizowaliśmy kpiny” ... w końcu dzieje się to poprzez tworzenie / debugowanie kodu. ّ Ponieważ to wszystko jest częścią procesu rozwoju! Chociaż jeśli backend zapewnia wyśmiewaną odpowiedź, jest to łatwiejsze.
Chodzi mi o to, że (jeśli nie możesz zautomatyzować pobierania zaktualizowanej fałszywej odpowiedzi API) wymagana jest interakcja człowieka, tj. Ręczne aktualizacje JSON i krótkie spotkania w celu upewnienia się, że ich wartości są aktualne, staną się częścią twojego procesu
Ta sekcja została napisana dzięki luźnej dyskusji w naszej grupie spotkań CocoaHead
Tylko dla deweloperów iOS:
Bardzo dobrym przykładem drwiny jest ta praktyczna zorientowana na protokół rozmowa Natashy Muraschev . Wystarczy przejść do minuty 18:30, chociaż slajdy mogą nie być zsynchronizowane z rzeczywistym filmem 🤷♂️
Bardzo podoba mi się ta część z transkrypcji:
źródło
Istnieje wiele odpowiedzi na temat SO i dobrych postów w Internecie o kpinach. Jednym z miejsc, które warto zacząć, jest post Martina Fowlera Mocks Aren't Stubs, w którym omawia wiele pomysłów na kpiny.
W jednym akapicie - Kpina to jedna konkretna technika pozwalająca na testowanie jednostki kodu bez uzależnienia od zależności. Zasadniczo to, co odróżnia drwiny od innych metod, polega na tym, że fałszywe obiekty użyte do zastąpienia zależności kodu pozwolą na ustawienie oczekiwań - próbny obiekt będzie wiedział, jak ma być wywoływany przez twój kod i jak reagować.
Twoje pierwotne pytanie dotyczyło TypeMock, więc zostawiłem odpowiedź na to poniżej:
TypeMock to nazwa frameworku komercyjnego .
Oferuje wszystkie funkcje darmowych frameworków, takich jak RhinoMocks i Moq, a także kilka bardziej zaawansowanych opcji.
To, czy potrzebujesz TypeMock, jest wysoce dyskusyjne - możesz zrobić większość kpin, jakich kiedykolwiek chciałbyś, korzystając z bezpłatnych bibliotek kpin, a wielu twierdzi, że możliwości oferowane przez TypeMock często odciągają cię od dobrze zamkniętego projektu.
Jak wskazano w innej odpowiedzi, „TypeMocking” nie jest tak naprawdę zdefiniowaną koncepcją, ale może być rozumiany jako rodzaj kpin, jaki oferuje TypeMock, przy użyciu profilera CLR do przechwytywania wywołań .Net w czasie wykonywania, co daje znacznie większą zdolność do fałszowania obiektów (nie wymagań takich jak wymagające interfejsów lub metod wirtualnych).
źródło
Mock to metoda / obiekt symulujący zachowanie prawdziwej metody / obiektu w kontrolowany sposób. Próbne obiekty są używane w testach jednostkowych.
Często testowana metoda wywołuje inne usługi zewnętrzne lub metody w jej ramach. Są to tak zwane zależności. Po wyśmiewaniu zależności zachowują się tak, jak je zdefiniowaliśmy.
Z zależności kontrolowane przez symulacje, możemy łatwo przetestować zachowanie kodowanej przez nas metody. To jest testowanie jednostkowe.
Jaki jest cel fałszywych obiektów?
Makiety kontra odcinki
Testy jednostkowe a testy funkcjonalne
źródło
Wyśmiewanie generuje pseudo-obiekty, które symulują zachowanie rzeczywistych obiektów na potrzeby testów
źródło
Celem próbnych typów jest zerwanie zależności w celu odizolowania testu od konkretnej jednostki. Karczki są prostymi surogatami, zaś kpiny są surogatami, które mogą weryfikować użycie. Struktura próbna to narzędzie, które pomoże Ci wygenerować kody pośredniczące i próbne.
EDYCJA : Ponieważ oryginalne sformułowanie mówi o „kpinie typu”, mam wrażenie, że dotyczy to TypeMock. Z mojego doświadczenia wynika, że ogólny termin to po prostu „kpina”. Możesz zignorować poniższe informacje, szczególnie w TypeMock.
TypeMock Isolator różni się od większości innych frameworków frameworkiem tym, że działa w trybie modyfikacji mojej IL. Pozwala to na kpowanie z typów i instancji, których większość innych frameworków nie może kpić. Aby wyśmiewać te typy / wystąpienia za pomocą innych frameworków, musisz dostarczyć własne abstrakcje i wyśmiewać je.
TypeMock oferuje dużą elastyczność kosztem czystego środowiska wykonawczego. Jako efekt uboczny sposobu, w jaki TypeMock osiąga wyniki, czasami uzyskuje się bardzo dziwne wyniki podczas korzystania z TypeMock.
źródło
Wydaje mi się, że użycie frameworka izolującego TypeMock byłoby TypeMocking.
Jest to narzędzie, które generuje symulacje do użycia w testach jednostkowych, bez potrzeby pisania kodu z myślą o IoC.
źródło
Jeśli próbą jest żądanie sieciowe, inną alternatywą jest posiadanie prawdziwego serwera testowego. Możesz skorzystać z tej usługi, aby wygenerować żądanie i odpowiedź na potrzeby testowania. http://testerurl.com/
źródło