Wiem, jak używać tych terminów, ale zastanawiam się, czy nie są akceptowane definicje udaje , szydząc i stubbing dla testów jednostkowych? Jak je zdefiniujesz dla swoich testów? Opisz sytuacje, w których możesz ich użyć.
Oto jak ich używam:
Fake : klasa, która implementuje interfejs, ale zawiera stałe dane i brak logiki. Zwraca po prostu „dobre” lub „złe” dane w zależności od implementacji.
Mock : klasa, która implementuje interfejs i pozwala na dynamiczne ustawianie wartości zwracanych / wyjątków do odrzucenia z poszczególnych metod i zapewnia możliwość sprawdzenia, czy określone metody zostały wywołane / nie zostały wywołane.
Stub : Niby klasa pozorna, z tym wyjątkiem, że nie zapewnia możliwości sprawdzenia, czy metody zostały wywołane / nie zostały wywołane.
Makiety i kody pośredniczące mogą być generowane ręcznie lub generowane przez ramy próbne. Fałszywe klasy są generowane ręcznie. Używam próbnych przede wszystkim do weryfikacji interakcji między moją klasą a klasami zależnymi. Używam kodów pośredniczących po zweryfikowaniu interakcji i testowaniu alternatywnych ścieżek za pomocą mojego kodu. Używam fałszywych klas przede wszystkim do wyodrębnienia zależności danych lub gdy próby / kody pośredniczące są zbyt uciążliwe, aby je konfigurować za każdym razem.
źródło
Odpowiedzi:
Możesz uzyskać informacje:
Od Martina Fowlera o Mock and Stub
Fałszywe obiekty faktycznie mają działające implementacje, ale zwykle wymagają skrótu, który sprawia, że nie nadają się do produkcji
Stuby zapewniają konserwowane odpowiedzi na wywołania wykonane podczas testu, zwykle nie reagując wcale na nic poza tym, co jest zaprogramowane na test. Stuby mogą również rejestrować informacje o połączeniach, takie jak kod pośredniczący bramy e-mail, który zapamiętuje wiadomości, które „wysłał”, a może tylko liczbę wiadomości, które „wysłał”.
Mocks są tym, co mówimy o tutaj: Przedmioty z zaprogramowanymi oczekiwań stanowiących specyfikację połączeń oczekuje oni otrzymać.
Z Xunitpattern :
Fałszywe : Pozyskujemy lub budujemy bardzo lekką implementację tej samej funkcjonalności, jaką zapewnia komponent, od którego zależy SUT, i instruujemy, aby używał SUT zamiast rzeczywistej.
Stub : Ta implementacja jest skonfigurowana do reagowania na wywołania z SUT z wartościami (lub wyjątkami), które wykonają nieprzetestowany kod (patrz Błędy produkcyjne na stronie X) w SUT. Kluczowym wskazaniem do użycia testu Stub jest posiadanie nieprzetestowanego kodu spowodowanego niemożnością kontrolowania pośrednich danych wejściowych SUT
Mock Object, który implementuje ten sam interfejs co obiekt, od którego zależy SUT (System Under Test). Możemy użyć fałszywego obiektu jako punktu obserwacyjnego, gdy potrzebujemy wykonać weryfikację zachowania, aby uniknąć posiadania niesprawdzonego wymagania (patrz Błędy produkcyjne na stronie X) spowodowanego niemożnością zaobserwowania skutków ubocznych wywoływania metod w SUT.
Osobiście
Staram się uprościć, używając: Mock and Stub. Używam Mock, gdy jest to obiekt, który zwraca wartość ustawioną dla testowanej klasy. Używam Stuba, aby naśladować testowaną klasę Interface lub Abstract. W rzeczywistości nie ma znaczenia, jak to nazwiesz, wszystkie są klasami, które nie są używane w produkcji i są używane jako klasy narzędzi do testowania.
źródło
Stub - obiekt, który zapewnia predefiniowane odpowiedzi na wywołania metod.
Mock - obiekt, na którym stawiasz oczekiwania.
Fake - obiekt o ograniczonych możliwościach (do celów testowych), np. Fałszywy serwis internetowy.
Test Double to ogólny termin na kody pośredniczące, kpiny i podróbki. Ale nieformalnie często słyszysz, jak ludzie nazywają ich kpiną.
źródło
EXPECT_CALL()
s na pozorowanej metodzie, która wymusza określone wyniki na podstawie określonych danych wejściowych, przy użyciu typu.WillOnce(Invoke(my_func_or_lambda_func))
(lub z.WillRepeatedly()
) składnia dołączona doEXPECT_CALL()
. Niektóre przykłady użyciaInvoke()
można zobaczyć w innym kontekście u dołu mojej długiej odpowiedzi tutaj: stackoverflow.com/a/60905880/4561887 .Invoke()
jest tutaj: github.com/google/googletest/blob/master/googlemock/docs/… . W każdym razie, wniosek jest taki: Google mock (gmock) pozwala na łatwe tworzenie zarówno mocks i odcinki , choć większość mocks nie są odcinki.Dziwi mnie, że pytanie to istniało już od tak dawna i nikt jak dotąd nie udzielił odpowiedzi w oparciu o „The Art of Unit Testing” Roya Osherove'a .
W „3.1 Wprowadzenie kodów pośredniczących” kod pośredniczący definiuje się jako:
I definiuje różnicę między kodami pośredniczącymi a próbnymi jako:
Fałszywe to tylko nazwa używana zarówno dla kodów pośredniczących, jak i próbnych. Na przykład, gdy nie obchodzi Cię rozróżnienie między skrótami a próbami.
Sposób, w jaki Osherove odróżnia kody pośredniczące od próbnych, oznacza, że każda klasa używana jako podróbka do testów może być zarówno pośrednicząca, jak i próbna. To, co jest dla konkretnego testu, zależy całkowicie od tego, jak wypisujesz czeki w teście.
Przykład testu, w którym klasa FakeX jest używana jako kod pośredniczący:
fake
Instancji służy jako odgałęzienie, ponieważAssert
nie korzystafake
w ogóle.Przykład testu, w którym klasa testowa X jest używana jako próbka:
W tym przypadku
Assert
sprawdza wartośćfake
, co czyni z tego fałszywego makieta.Oczywiście te przykłady są wysoce wymyślone, ale widzę wielką zasługę w tym rozróżnieniu. Uświadamia ci, w jaki sposób testujesz swoje rzeczy i gdzie są zależności w teście.
Zgadzam się z tym Osherove
Przeciwstawianie się podróbkom jest czymś, czego naprawdę chcesz uniknąć, ponieważ bardzo uzależnia twoje testy od implementacji klasy, która w ogóle nie jest testowana. Co oznacza, że testy dla klasy
ActualClassUnderTest
mogą zacząć się rozpadać, ponieważ zmieniono implementacjęClassUsedAsMock
. I to wywołuje dla mnie nieprzyjemny zapach. TestyActualClassUnderTest
najlepiej przerwać tylko poActualClassUnderTest
zmianie.Zdaję sobie sprawę, że pisanie oświadczeń przeciwko podróbkom jest powszechną praktyką, szczególnie gdy jesteś mockistowskim typem subskrybenta TDD. Wydaje mi się, że jestem zdecydowanie z Martinem Fowlerem w obozie klasycystycznym (patrz „ Mocky nie są skrótami ” ) i podobnie jak Osherove unikają testowania interakcji (co można zrobić tylko poprzez walkę z podróbką).
Aby przeczytać, dlaczego należy unikać drwin, jak zdefiniowano tutaj, przejdź do Google dla „fowler mockist classicist”. Znajdziesz mnóstwo opinii.
źródło
Jak wspomniano w najczęściej głosowanej odpowiedzi, Martin Fowler omawia te rozróżnienia w Mocks Aren't Stubs , a w szczególności w podtytule The Difference Between Mocks and Stubs , więc przeczytaj ten artykuł.
Zamiast skupiać się na jak te rzeczy są różne, myślę, że to bardziej skupić się na oświecenie dlaczego są różne koncepcje. Każdy istnieje w innym celu.
Podróbki
Fałszywy jest implementacją, która zachowuje się w sposób „naturalny”, ale nie jest „prawdziwy”. Są to rozmyte pojęcia, więc różni ludzie rozumieją, co czyni je fałszywymi.
Jednym z przykładów podróbki jest baza danych w pamięci (np. Używanie sqlite ze
:memory:
sklepem). Nigdy nie użyłbyś tego do produkcji (ponieważ dane nie są utrwalane), ale jest to całkowicie wystarczające jako baza danych do użycia w środowisku testowym. Jest również znacznie lżejszy niż „prawdziwa” baza danych.Jako inny przykład, być może używasz jakiegoś magazynu obiektów (np. Amazon S3) w produkcji, ale w teście możesz po prostu zapisać obiekty do plików na dysku; wówczas implementacja „zapisz na dysku” byłaby fałszywa. (Lub możesz nawet sfałszować operację „zapisz na dysku”, używając zamiast tego systemu plików w pamięci).
Jako trzeci przykład wyobraź sobie obiekt, który udostępnia interfejs API pamięci podręcznej; obiekt, który implementuje poprawny interfejs, ale który po prostu nie wykonuje buforowania, ale zawsze zwraca brak pamięci podręcznej, byłby rodzajem fałszywki.
Celem podróbki nie jest wpływanie na zachowanie testowanego systemu , ale uproszczenie implementacji testu (poprzez usunięcie zbędnych lub ciężkich zależności).
Stuby
Stub jest implementacją, która zachowuje się „nienaturalnie”. Jest wstępnie skonfigurowany (zwykle przez konfigurację testową), aby reagować na określone dane wejściowe za pomocą określonych danych wyjściowych.
Celem kodu pośredniczącego jest doprowadzenie testowanego systemu do określonego stanu. Na przykład, jeśli piszesz test na kod, który wchodzi w interakcję z interfejsem API REST, możesz zlikwidować interfejs API REST za pomocą interfejsu API, który zawsze zwraca odpowiedź standardową lub który odpowiada na żądanie interfejsu API z określonym błędem. W ten sposób możesz napisać testy, które zawierają stwierdzenia o tym, jak system reaguje na te stany; na przykład testowanie odpowiedzi uzyskiwanej przez użytkowników, jeśli interfejs API zwraca błąd 404.
Kod pośredniczący jest zwykle implementowany, aby reagować tylko na dokładne interakcje, na które kazałeś mu odpowiedzieć. Ale kluczową cechą, która sprawia, że coś jest odgałęzieniem, jest jego cel : w odgałęzieniu chodzi o skonfigurowanie twojego przypadku testowego.
Makiety
Makiety jest podobna do zalążek, ale z weryfikacji dodanej. Celem mock jest, aby twierdzenia dotyczące konfiguracji urządzeń w ramach testu w interakcję z uzależnienia .
Na przykład, jeśli piszesz test systemu, który przesyła pliki do strony internetowej, możesz zbudować próbkę, która akceptuje plik i której możesz użyć, aby potwierdzić, że przesłany plik jest poprawny. Lub, na mniejszą skalę, często używa się makiety obiektu, aby sprawdzić, czy testowany system wywołuje określone metody kpionego obiektu.
Próbki są powiązane z testowaniem interakcji , które jest specyficzną metodologią testowania. Ludzie, którzy wolą testować stan systemu niż interakcje systemowe, będą używać próbnych , jeśli w ogóle, oszczędnie.
Test podwaja się
Podróbki, odcinki i makiety należą do kategorii podwójnych testów . Podwójny test to dowolny obiekt lub system używany w teście zamiast czegoś innego. Większość zautomatyzowanych testów oprogramowania wymaga użycia podwójnych testów. Niektóre inne rodzaje deblu testowych obejmują wartości nieużywane , szpiegów i I / O blackholes .
źródło
Aby zilustrować użycie kodów pośredniczących i próbnych, chciałbym również dołączyć przykład oparty na „ The Art of Unit Testing ” Roya Osherove'a .
Wyobraź sobie, że mamy aplikację LogAnalyzer, która ma wyłączną funkcję drukowania dzienników. Musi nie tylko rozmawiać z usługą internetową, ale jeśli usługa internetowa zgłosi błąd, LogAnalyzer musi zalogować błąd do innej zależności zewnętrznej, wysyłając go e-mailem do administratora usługi internetowej.
Oto logika, którą chcielibyśmy przetestować w LogAnalyzer:
Jak sprawdzić, czy LogAnalyzer poprawnie wywołuje usługę e-mail, gdy usługa sieciowa zgłasza wyjątek? Oto pytania, przed którymi stoimy:
Jak możemy zastąpić serwis internetowy?
Jak możemy zasymulować wyjątek od usługi internetowej, abyśmy mogli przetestować połączenie z usługą e-mail?
Skąd będziemy wiedzieć, że usługa e-mail została poprawnie lub w ogóle wywołana?
Pierwsze dwa pytania możemy rozwiązać, korzystając z kodu pośredniczącego dla usługi sieci Web . Aby rozwiązać trzeci problem, możemy użyć fałszywego obiektu dla usługi e-mail .
Fałszywy to ogólny termin, którego można użyć do opisania kodu pośredniczącego lub próbnego. W naszym teście otrzymamy dwa fałszywe. Jednym z nich będzie próbna usługa e-mail, której użyjemy do zweryfikowania, czy do usługi e-mail wysłano prawidłowe parametry. Drugim będzie kod pośredniczący, którego użyjemy do symulacji wyjątku zgłoszonego przez serwis internetowy. Jest to zalążek, ponieważ nie będziemy używać fałszywej usługi sieci Web do weryfikacji wyniku testu, a jedynie do upewnienia się, że test działa poprawnie. Usługa e-mail jest fałszywą, ponieważ twierdzimy, że została poprawnie wywołana.
źródło
tym, czego dochodzić na nim, nazywa się mock obiektu i wszystko inne, co tylko pomógł rozruch próbny, jest en .
źródło
Chodzi o to, aby testy były ekspresyjne. Ustawiam oczekiwania na próbę, jeśli chcę, aby test opisał związek między dwoma obiektami. Zwracam wartości zwracane, jeśli konfiguruję obiekt pomocniczy, aby uzyskać interesujące zachowanie w teście.
źródło
Jeśli znasz Arrange-Act-Assert, jednym ze sposobów wyjaśnienia różnicy między kodem pośredniczącym a próbnym, które mogą być dla Ciebie przydatne, jest to, że kody pośredniczące należą do sekcji arrange, ponieważ służą one do ustawiania stanu wejściowego, a symulacje należą do sekcja potwierdzenia, ponieważ służą one do potwierdzenia wyników.
Manekiny nic nie robią. Służą one wyłącznie do wypełniania list parametrów, aby nie występowały błędy niezdefiniowane lub zerowe. Istnieją również po to, by spełniać funkcję sprawdzania typów w ściśle wpisywanych językach, dzięki czemu możesz mieć możliwość kompilacji i uruchamiania.
źródło
Stub, podróbki i makiety mają różne znaczenie w różnych źródłach. Sugeruję wprowadzenie wewnętrznych warunków zespołu i uzgodnienie ich znaczenia.
Myślę, że ważne jest rozróżnienie między dwoma podejściami: - walidacja zachowania (implikuje zastąpienie zachowania) - walidacja stanu końcowego (imitacja zachowania)
W przypadku błędu rozważ wysłanie wiadomości e-mail. Kiedy robi poprawności zachowań - sprawdzić tę metodę
Send
zIEmailSender
została wykonana jednorazowo. I musisz emulować wynik tej metody, zwróć identyfikator wysłanej wiadomości. Więc mówicie: „Spodziewam się tegoSend
to zostanie wywołane. I po prostu zwrócę fałszywy (lub losowy) identyfikator dla każdego połączenia” . Oto sprawdzanie poprawności zachowania:emailSender.Expect(es=>es.Send(anyThing)).Return((subject,body) => "dummyId")
Podczas sprawdzania stanu konieczne będzie utworzenie
TestEmailSender
tego narzędziaIEmailSender
. I zaimplementujSend
metodę - zapisując dane wejściowe do jakiejś struktury danych, która będzie używana do przyszłej weryfikacji stanu, takiej jak tablica niektórych obiektów,SentEmails
a następnie przetestujesz, czy to sprawdziszSentEmails
zawiera oczekiwany e-mail. To jest sprawdzanie stanu:Assert.AreEqual(1, emailSender.SentEmails.Count)
Z moich odczytów zrozumiałem, że walidacja zachowań zwykle nazywana jest próbą . I sprawdzanie stanu zwykle zwane skrótami lub podróbkami .
źródło
stub i fake są obiektami, ponieważ mogą zmieniać swoją odpowiedź w zależności od parametrów wejściowych. główna różnica między nimi polega na tym, że Fake jest bliższy implementacji w świecie rzeczywistym niż odgałęzienie. Stuby zawierają zasadniczo zakodowane odpowiedzi na oczekiwane żądanie. Zobaczmy przykład:
Mock to krok w górę od podróbek i króćców. Makiety zapewniają taką samą funkcjonalność jak kody pośredniczące, ale są bardziej złożone. Mogą mieć zdefiniowane dla nich reguły określające, w jakiej kolejności muszą być wywoływane metody interfejsu API. Większość próbnych może śledzić, ile razy została wywołana metoda i może reagować na podstawie tych informacji. Egzaminy na ogół znają kontekst każdego połączenia i mogą reagować inaczej w różnych sytuacjach. Z tego powodu drwiny wymagają pewnej wiedzy na temat klasy, z której drwią. kodów pośredniczących zazwyczaj nie można śledzić, ile razy została wywołana metoda lub w jakiej kolejności została wywołana sekwencja metod. Makieta wygląda jak:
źródło
fake object
jest prawdziwą implementacją interfejsu (protokołu) lub rozszerzenia z wykorzystaniem dziedziczenia lub innych podejść, których można użyć do stworzenia - jest zależność. Zwykle jest on tworzony przez programistę jako najprostsze rozwiązanie zastępujące pewną zależnośćstub object
jest nagim obiektem (0, zero i metody bez logiki) ze stanem dodatkowym i predefiniowanym (przez programistę) do definiowania zwracanych wartości. Zwykle jest tworzony przez frameworkmock object
jest bardzo podobny do stanustub object
dodatkowego jest zmieniany podczas wykonywania programu, aby sprawdzić, czy coś się stało (wywołano metodę).źródło