Czytałem różne artykuły o kpinach i karczowaniu w testach, w tym kpiny Martina Fowlera , ale nie rozumiem różnicy.
962
Czytałem różne artykuły o kpinach i karczowaniu w testach, w tym kpiny Martina Fowlera , ale nie rozumiem różnicy.
Odpowiedzi:
Kikut
Uważam, że największym rozróżnieniem jest to, że napisałeś już odcinek ze z góry określonym zachowaniem. Tak więc miałbyś klasę, która implementuje zależność (najprawdopodobniej klasę abstrakcyjną lub interfejs), którą sfałszujesz do celów testowych, a metody zostałyby po prostu zgaszone z ustalonymi odpowiedziami. Nie zrobiliby nic wymyślnego, a ty już napisałeś dla niego kod pośredni poza testem.
Drwić
Kpina jest czymś, co w ramach testu musisz skonfigurować zgodnie ze swoimi oczekiwaniami. Makieta nie jest konfigurowana w określony sposób, więc masz kod, który robi to w teście. Próbki są w pewien sposób określane w czasie wykonywania, ponieważ kod określający oczekiwania musi zostać uruchomiony, zanim cokolwiek zrobi.
Różnica między Mockami a Stubami
Testy pisane próbnymi
initialize -> set expectations -> exercise -> verify
próbami zwykle przebiegają według wzoru. Podczas gdy wstępnie napisany kod będzie następował poinitialize -> exercise -> verify
.Podobieństwo między próbkami i skrótami
Celem obu jest wyeliminowanie testowania wszystkich zależności klasy lub funkcji, aby twoje testy były bardziej skoncentrowane i prostsze w tym, co próbują udowodnić.
źródło
Przedmowa
Istnieje kilka definicji obiektów, które nie są rzeczywiste. Ogólny termin to test podwójny . Termin ten obejmuje: manekin , fałszywy , skrótowy , próbny .
Odniesienie
Zgodnie z artykułem Martina Fowlera :
Styl
Egzaminy próbne a stadniny = testy behawioralne a testy stanowe
Zasada
Zgodnie z zasadą testu tylko jedna rzecz na test , w jednym teście może znajdować się kilka kodów pośredniczących, ale generalnie jest tylko jedna próbka.
Koło życia
Testuj cykl życia za pomocą kodów pośredniczących:
Cykl życia testu z próbami:
Podsumowanie
Testy próbne i pośredniczące dają odpowiedź na pytanie: Jaki jest wynik?
Testy z próbami są również zainteresowane: Jak uzyskano wynik?
źródło
Kikut to prosty fałszywy obiekt. Po prostu upewnia się, że test działa płynnie.
Makieta to mądrzejszy skrót. Sprawdzasz, czy test przechodzi przez to.
źródło
Oto opis każdego z nich wraz z próbką ze świata rzeczywistego.
Atrapa - po prostu fałszywe wartości, aby spełnić
API
.Fake - utwórz testową implementację klasy, która może zależeć od jakiejś zewnętrznej infrastruktury. (Dobrą praktyką jest to, że test jednostkowy NIE wchodzi w interakcje z zewnętrzną infrastrukturą).
Stub - zastępuj metody zwracające wartości zakodowane, zwane także
state-based
.Mock - bardzo podobny,
Stub
aleinteraction-based
raczej niż oparty na stanie. Oznacza to, że nie oczekujesz,Mock
że zwróci jakąś wartość, ale założysz, że tworzona jest określona kolejność wywołań metod.Stubs
iMocks
są w rzeczywistości podtypamiMock
, oba zamieniają rzeczywistą implementację na implementację testową, ale z różnych, konkretnych powodów.źródło
W kursieodeschool.com , Rails Testing for Zombies , podają następującą definicję terminów:
Kikut
Drwić
Tak więc, jak Sean Copenhaver opisał w swojej odpowiedzi, różnica polega na tym, że drwiny ustalają oczekiwania (tj. Robią twierdzenia na temat tego, czy i jak zostaną wywołane).
źródło
Stuby nie zawodzą twoich testów, próbuj.
źródło
Myślę, że najprostszą i jaśniejszą odpowiedź na to pytanie udziela Roy Osherove w swojej książce The Art of Unit Testing (strona 85)
Oznacza to, że jeśli robisz twierdzenia przeciwko fałszywemu, oznacza to, że używasz fałszywego jako makiety, jeśli używasz fałszywego tylko w celu uruchomienia testu bez potwierdzenia, używasz fałszywego jako kodu pośredniczącego.
źródło
Czytając wszystkie powyższe wyjaśnienia, postaram się zagęścić:
źródło
Mock to po prostu testowanie zachowania, upewniające się, że wywoływane są określone metody. Stub to wersja testowa (per se) konkretnego obiektu.
Co masz na myśli po Apple?
źródło
Jeśli porównasz to do debugowania:
źródło
Użycie modelu mentalnego naprawdę pomogło mi to zrozumieć, zamiast wszystkich wyjaśnień i artykułów, które nie do końca się „zagłębiły”.
Wyobraź sobie, że twoje dziecko ma szklany talerz na stole i zaczyna się nim bawić. Teraz boisz się, że się zepsuje. Dajesz mu zamiast tego plastikową płytkę. To byłby Mock (to samo zachowanie, ten sam interfejs, „bardziej miękka” implementacja).
Teraz powiedz, że nie masz plastikowego zamiennika, więc wyjaśnisz „Jeśli będziesz dalej z nim bawił, pęknie!”. To jest Stub , wcześniej podałeś wcześniej zdefiniowany stan.
Dummy byłoby widelec nawet nie używać ... I Spy może być coś podobnego zapewniając taką samą wyjaśnienie już używany, który pracował.
źródło
Myślę, że najważniejszą różnicą między nimi są ich intencje.
Pozwól, że spróbuję wyjaśnić to w DLACZEGO pośredniku kontra DLACZEGO udawanie
Załóżmy, że piszę kod testowy dla publicznego kontrolera osi czasu mojego klienta Mac twitter
Oto przykładowy kod testowy
Pisząc próbną, odkrywasz relację współpracy między obiektami, sprawdzając, czy spełnione są oczekiwania, a kod pośredni symuluje tylko zachowanie obiektu.
Proponuję przeczytać ten artykuł, jeśli chcesz dowiedzieć się więcej o próbach: http://jmock.org/oopsla2004.pdf
źródło
Aby być bardzo jasnym i praktycznym:
Stub: klasa lub obiekt, który implementuje metody sfałszowanej klasy / obiektu i zwraca zawsze to, co chcesz.
Przykład w JavaScript:
Mock: To samo z kodem pośredniczącym, ale dodaje pewną logikę, która „weryfikuje”, gdy wywoływana jest metoda, dzięki czemu masz pewność, że niektóre implementacje wywołują tę metodę.
Jak mówi @mLevan, wyobraź sobie jako przykład, że testujesz klasę rejestracji użytkownika. Po wywołaniu Save powinien wywołać SendConfirmationEmail.
Bardzo głupi kod Przykład:
źródło
Ten slajd bardzo dobrze wyjaśnia główne różnice.
* Z CSE 403 Wykład 16, University of Washington (slajd stworzony przez „Marty Stepp”)
źródło
Podoba mi się wyjaśnienie Roy Osherove [link do filmu] .
źródło
źródło
zobaczmy Test Doubles:
Stub : Stub to obiekt, który przechowuje predefiniowane dane i używa go do odbierania połączeń podczas testów. Na przykład : obiekt, który musi pobrać niektóre dane z bazy danych, aby odpowiedzieć na wywołanie metody.
Mocks : Mocks to obiekty, które rejestrują odbierane połączenia. W zapewnieniu testowym możemy zweryfikować na próbkach, że wszystkie oczekiwane działania zostały wykonane. Takie jak : funkcja wywołująca usługę wysyłania wiadomości e-mail. po więcej sprawdź to .
źródło
Fałszywy to ogólny termin, który może być używany do opisania albo niedopałek lub atrapa obiektu (odręcznie lub w inny sposób), ponieważ zarówno wygląd jak prawdziwy przedmiot.
To, czy podróbka jest kikutem, czy próbą, zależy od tego, jak zostanie wykorzystany w bieżącym teście. Jeśli jest używany do sprawdzania interakcji (potwierdzony przeciwko), jest to próbny obiekt. W przeciwnym razie jest to zalążek.
Podróbki zapewniają sprawne działanie testu. Oznacza to, że czytelnik twojego przyszłego testu zrozumie, jakie będzie zachowanie fałszywego obiektu, bez konieczności czytania jego kodu źródłowego (bez konieczności polegania na zasobach zewnętrznych).
Co oznacza płynny przebieg testu?
Na przykład w poniższym kodzie:
Chcesz przetestować metodę mailService.SendEMail () , aby to zrobić, musisz zasymulować wyjątek w swojej metodzie testowej, więc wystarczy utworzyć klasę Fake Stub errorService, aby zasymulować ten wynik, a następnie kod testowy będzie mógł przetestować Metoda mailService.SendEMail (). Jak widzisz, musisz zasymulować wynik pochodzący z innej klasy ErrorService klasy zależności zewnętrznych.
źródło
Bezpośrednio z gazety Mock Role, a nie Objects , twórcy jMock:
Główne różnice to:
Podsumowując, jednocześnie starając się rozproszyć zamieszanie związane z tytułem artykułu Fowlera : kpiny to odcinki, ale nie tylko odcinki .
źródło
Czytałem The Art of Unit Testing i natknąłem się na następującą definicję:
źródło
Natrafiłem na ten interesujący artykuł autorstwa UncleBob The Little Mocker . Wyjaśnia całą terminologię w bardzo łatwy do zrozumienia sposób, więc jest przydatny dla początkujących. Artykuł Martina Fowlersa jest trudny do przeczytania, szczególnie dla początkujących, takich jak ja.
źródło
Stub pomaga nam przeprowadzić test. W jaki sposób? Podaje wartości, które pomagają uruchomić test. Te wartości same w sobie nie są rzeczywiste i stworzyliśmy je tylko w celu uruchomienia testu. Na przykład tworzymy HashMap, aby dać nam wartości, które są podobne do wartości w tabeli bazy danych. Zamiast bezpośrednio wchodzić w interakcję z bazą danych, wchodzimy w interakcję z Hashmap.
Mock to fałszywy obiekt, który uruchamia test. gdzie kładziemy nacisk.
źródło
Zobacz poniżej przykład makiety vs odcinki przy użyciu frameworka C # i Moq. Moq nie ma specjalnego słowa kluczowego dla kodu Stub, ale możesz także użyć obiektu Mock do utworzenia kodów pośredniczących.
źródło
Punkt testowy testu pośredniego i próbnego:
Stub to fałszywa implementacja wykonywana przez użytkownika w sposób statyczny, tzn. W Stubie piszącym kod implementacyjny. Więc nie może obsłużyć definicji usługi i warunku dynamicznego. Zwykle odbywa się to w frameworku JUnit bez użycia frameworku.
Mock jest również implementacją fikcyjną, ale jego implementacja została wykonana dynamicznie przy użyciu frameworków takich jak Mockito. Możemy więc traktować definicję warunków i usług w sposób dynamiczny, tzn. Symulacje można tworzyć dynamicznie z kodu w czasie wykonywania. Tak więc używając makiety możemy dynamicznie implementować Stuby.
źródło
Plus przydatne odpowiedzi, jeden z najpotężniejszych punktów korzystania z Mocków niż subskrybcji
Jeśli współpracownik [od którego zależy główny kod] nie jest pod naszą kontrolą (np. Z biblioteki innej firmy),
W tym przypadku stub jest trudniejszy do napisania niż próbowania .
źródło
Użyłem przykładów python w mojej odpowiedzi, aby zilustrować różnice.
Stub - Stubbing to technika opracowywania oprogramowania służąca do wdrażania metod zajęć na wczesnym etapie cyklu rozwojowego. Są one powszechnie stosowane jako symbole zastępcze dla implementacji znanego interfejsu, gdzie interfejs jest sfinalizowany lub znany, ale implementacja nie jest jeszcze znana ani sfinalizowana. Zaczynasz od kodów pośredniczących, co oznacza po prostu, że zapisujesz tylko definicję funkcji i pozostawiasz kod na później. Zaletą jest to, że nie zapomnisz metod i możesz nadal myśleć o swoim projekcie, widząc go w kodzie. Możesz również ustawić swój kod zwrotny na odpowiedź statyczną, dzięki czemu odpowiedź może zostać natychmiast wykorzystana przez inne części kodu. Obiekty wejściowe zapewniają prawidłową odpowiedź, ale są statyczne bez względu na przekazane dane wejściowe, zawsze otrzymasz tę samą odpowiedź:
Drwić obiekty są wykorzystywane w próbnych testach oni potwierdzić, że niektóre metody są nazywane na tych obiektach. Sztuczne obiekty to symulowane obiekty, które naśladują zachowanie rzeczywistych obiektów w kontrolowany sposób. Zazwyczaj tworzy się próbny obiekt w celu przetestowania zachowania jakiegoś innego obiektu. Próbki pozwalają nam symulować zasoby, które są niedostępne lub zbyt nieporęczne do testów jednostkowych.
mymodule.py:
test.py:
Jest to bardzo prosty przykład, który po prostu uruchamia rm i potwierdza parametr, za pomocą którego został wywołany. Możesz użyć makiety z obiektami, nie tylko funkcjami, jak pokazano tutaj, a także możesz zwrócić wartość, dzięki czemu można użyć makiety do zastąpienia kodu pośredniczącego do testowania.
Więcej na unittest.mock , uwaga w 2.x mock nie jest zawarta w unittest, ale jest modułem do pobrania, który można pobrać przez pip (mock install pip).
Przeczytałem także „The Art of Unit Testing” Roy'a Osherove i myślę, że byłoby wspaniale, gdyby podobna książka została napisana przy użyciu Pythona i przykładów Pythona. Jeśli ktoś wie o takiej książce, udostępnij ją. Twoje zdrowie :)
źródło
Stub to fałszywy obiekt zbudowany do celów testowych. Próbny to kod pośredniczący, który rejestruje, czy oczekiwane połączenia zostały skutecznie wykonane.
źródło
Kod pośredniczący to pusta funkcja, która służy do unikania nieobsługiwanych wyjątków podczas testów:
Mock to sztuczna funkcja używana w celu uniknięcia zależności systemu operacyjnego, środowiska lub sprzętu podczas testów:
Pod względem twierdzeń i stanu:
Bibliografia
źródło
tam jest wiele prawidłowych odpowiedzi, ale myślę, że warto wspomnieć o tym formularzu wuj Bob: https://8thlight.com/blog/uncle-bob/2014/05/14/TheLittleMocker.html
najlepsze wyjaśnienie z przykładami!
źródło
Makieta jest zarówno przedmiotem technicznym, jak i funkcjonalnym .
Kpina jest techniczna . Jest on rzeczywiście tworzony przez fałszywą bibliotekę (z tego znane są EasyMock, JMockit i ostatnio Mockito) dzięki generowaniu kodu bajtowego .
Implementacja próbna jest generowana w taki sposób, że możemy ją instrumentować , aby zwracała określoną wartość po wywołaniu metody, ale także kilka innych rzeczy, takich jak sprawdzenie, czy wywołano próbną metodę z określonymi parametrami (ścisłe sprawdzenie) lub dowolnymi parametrami ( brak ścisłej kontroli).
Tworzenie makiety:
Nagrywanie zachowania:
Weryfikacja wywołania:
To oczywiście nie jest naturalny sposób na tworzenie / nadpisywanie klasy / zachowania Foo. Dlatego odnoszę się do aspektu technicznego.
Ale makieta jest również funkcjonalna, ponieważ jest instancją klasy, którą musimy odizolować od SUT. A z zarejestrowanymi zachowaniami, moglibyśmy użyć go w SUT w taki sam sposób, jak zrobilibyśmy go z kodem pośredniczącym.
Kod pośredniczący to tylko obiekt funkcjonalny : jest to instancja klasy, którą musimy odizolować od SUT i to wszystko. Oznacza to, że zarówno klasa pośrednicząca, jak i wszystkie urządzenia zachowań potrzebne podczas naszych testów jednostkowych muszą być wyraźnie zdefiniowane.
Na przykład kod pośredniczący
hello()
musiałby podklasowaćFoo
klasę (lub implementować interfejs, który on ma) i przesłonićhello()
:Jeśli inny scenariusz testowy wymaga zwrotu innej wartości, prawdopodobnie będziemy musieli zdefiniować ogólny sposób ustawiania zwrotu:
Inny scenariusz: gdybym miał metodę skutków ubocznych (bez powrotu) i sprawdziłbym, czy ta metoda została wywołana, prawdopodobnie powinienem dodać wartość logiczną lub licznik w klasie stub, aby policzyć, ile razy metoda została wywołana.
Wniosek
Kod pośredniczący wymaga często dużego obciążenia / kodu do napisania do testu jednostkowego. Jakiej kpiny zapobiega dzięki zapewnieniu funkcji nagrywania / weryfikacji od razu po wyjęciu z pudełka.
Dlatego obecnie podejście stub jest rzadko stosowane w praktyce wraz z pojawieniem się doskonałych fałszywych bibliotek.
O artykule Martina Fowlera: Nie uważam się za programistę „mockist”, kiedy używam makiet i unikam kodów pośredniczących.
Ale używam makiety, gdy jest to naprawdę wymagane (irytujące zależności) i preferuję testy krojenia i testy mini-integracji, gdy testuję klasę z zależnościami, których kpowanie byłoby narzutem.
źródło