Muszę wcielić się w diabła, który jest zwolennikiem tego pytania, ponieważ nie mogę go dobrze bronić z powodu braku doświadczenia. Oto oferta, dostaję koncepcyjnie różnice między testowaniem jednostkowym a testowaniem integracyjnym. Skupiając się w szczególności na metodach trwałości i repozytorium, test jednostkowy użyłby makiety prawdopodobnie za pośrednictwem struktury takiej jak Moq, aby stwierdzić, że wyszukiwane zamówienie zostało zwrócone zgodnie z oczekiwaniami.
Załóżmy, że zbudowałem następujący test jednostkowy:
[TestMethod]
public void GetOrderByIDTest()
{
//Uses Moq for dependency for getting order to make sure
//ID I set up in 'Arrange' is same one returned to test in 'Assertion'
}
Więc jeśli skonfiguruję OrderIdExpected = 5
i mój próbny obiekt zwróci 5
jako identyfikator, mój test przejdzie. Rozumiem. I jednostka przetestowany kod, aby upewnić się co moi preform kod zwraca oczekiwanego obiektu i identyfikator, a nie coś innego.
Otrzymam następujący argument:
„Dlaczego po prostu nie pominąć testów jednostkowych i nie wykonać testów integracyjnych? To ważne jest testowanie procedury składowanej bazy danych i kodu. Wydaje się, że to zbyt dużo pracy, aby mieć testy jednostkowe i testy integracyjne, kiedy ostatecznie chcę wiedzieć, czy baza danych wywołuje i kod działa. Wiem, że testy trwają dłużej, ale muszą być uruchamiane i testowane niezależnie, więc wydaje mi się, że nie ma sensu mieć obu. Po prostu przetestuj, co jest ważne. ”
Mógłbym go obronić za pomocą definicji z podręcznika: „Cóż, to test integracyjny i musimy osobno przetestować kod jako test jednostkowy i, yada, yada, yada ...” Jest to przypadek, w którym purystyczne wyjaśnienie praktyk a rzeczywistość przegrywa. Czasami się na to natrafiam i jeśli nie jestem w stanie obronić rozumowania stojącego za kodem testów jednostkowych, który ostatecznie opiera się na zewnętrznych zależnościach, to nie mogę tego uzasadnić.
Dziękujemy za pomoc w tym pytaniu, dziękuję!
źródło
Odpowiedzi:
Testy jednostkowe i testy integracyjne mają różne cele.
Testy jednostkowe weryfikują funkcjonalność kodu ... czy otrzymujesz to, czego oczekujesz od metody po jej wywołaniu. Testy integracyjne sprawdzają, jak zachowuje się kod, gdy są połączone razem jako system. Nie należy oczekiwać, że testy jednostkowe oceniają zachowanie systemu, ani nie oczekuje się, że testy integracyjne zweryfikują określone wyniki konkretnej metody.
Testy jednostkowe, jeśli wykonane poprawnie, są łatwiejsze do skonfigurowania niż testy integracyjne. Jeśli polegasz wyłącznie na testach integracyjnych, Twoje testy będą:
Konkluzja: Użyj testu integracji, aby sprawdzić, czy połączenia między obiektami działają poprawnie, ale najpierw przetestuj jednostkę, aby zweryfikować wymagania funkcjonalne.
To powiedziawszy, możesz nie potrzebować testów jednostkowych dla niektórych metod repozytorium. Testy jednostkowe nie powinny być wykonywane na trywialnych metodach; jeśli wszystko, co robisz, to przekazanie żądania do kodu wygenerowanego przez ORM i zwrócenie wyniku, w większości przypadków nie musisz tego testować jednostkowo; test integracji jest odpowiedni.
źródło
Jestem po stronie pragmatyków. Nie testuj swojego kodu dwa razy.
Testy integracyjne piszemy tylko dla naszych repozytoriów. Testy te zależą tylko od prostej konfiguracji testu, która działa na bazie danych w pamięci. Myślę, że zapewniają wszystko, co robi test jednostkowy i wiele więcej.
źródło
Testy jednostkowe zapewniają poziom modułowości, którego nie są w stanie przeprowadzić testy integracyjne (zgodnie z projektem). Kiedy system zostanie ponownie skomponowany lub ponownie skomponowany, (i tak się stanie) testy jednostkowe mogą być często ponownie użyte, podczas gdy testy integracyjne muszą być często przepisywane. Testy integracyjne, które próbują wykonać coś, co powinno znaleźć się w teście jednostkowym, często robią za dużo, co utrudnia ich utrzymanie.
Dodatkowo, w tym testowanie jednostkowe ma następujące zalety:
Możliwe jest podzielenie pracy (i wymuszenie OSUSZANIA) podczas korzystania zarówno z testów jednostkowych, jak i integracyjnych. Po prostu polegaj na testach jednostkowych dla małych jednostek funkcjonalności i nie powtarzaj żadnej logiki, która jest już w teście jednostkowym w teście integracji. To często prowadzi do mniejszej pracy (a tym samym mniejszej ilości ponownej pracy).
źródło
Testy są przydatne, gdy się psują: proaktywnie lub ponownie aktywnie.
Testy jednostkowe są proaktywne i mogą stanowić ciągłą weryfikację funkcjonalną, podczas gdy testy integracyjne są reaktywne na danych etapowych / fałszywych.
Jeśli rozważany system jest bliski / zależny od danych bardziej niż logiki obliczeniowej, testy integracji powinny zyskać na znaczeniu.
Na przykład, jeśli budujemy system ETL, najbardziej odpowiednie testy będą dotyczyły danych (etapowych, sfałszowanych lub na żywo). Ten sam system będzie miał kilka testów jednostkowych, ale tylko wokół sprawdzania poprawności, filtrowania itp.
Wzorzec repozytorium nie powinien mieć logiki obliczeniowej ani biznesowej. Jest bardzo blisko bazy danych. Ale repozytorium jest również zbliżone do logiki biznesowej, która z niego korzysta. Jest to więc kwestia zachowania równowagi.
Testy jednostkowe mogą testować JAK DZIAŁA repozytorium. Testy integracyjne mogą przetestować CO NAPRAWDĘ STAŁO się, gdy wywołano repozytorium.
Teraz „CO NAPRAWDĘ SIĘ STAŁO” może wydawać się bardzo kuszące. Ale może to być bardzo kosztowne w przypadku ciągłego i powtarzalnego działania. Obowiązuje tutaj klasyczna definicja testów kruchości.
Przez większość czasu po prostu uważam, że wystarczy napisać Test jednostkowy na obiekcie korzystającym z repozytorium. W ten sposób sprawdzamy, czy została wywołana odpowiednia metoda repozytorium i czy zwrócone są prawidłowe wyniki Mocked.
źródło
Istnieją 3 osobne rzeczy, które wymagają przetestowania: procedura przechowywana, kod wywołujący procedurę przechowywaną (tj. Klasa repozytorium) i konsument. Zadaniem repozytorium jest wygenerowanie zapytania i konwersja zwróconego zestawu danych na obiekt domeny. Jest wystarczający kod do obsługi testów jednostkowych, który różni się od faktycznego wykonania zapytania i utworzenia zestawu danych.
Więc (jest to bardzo bardzo uproszczony przykład):
Następnie podczas testowania
OrderRepository
przekaż wyśmiewanyISqlExecutor
i sprawdź, czy testowany obiekt przekazuje poprawny kod SQL (to jest jego zadanie) i zwraca odpowiedniOrder
obiekt, biorąc pod uwagę zbiór danych wynikowych (również wyśmiewany). Prawdopodobnie jedynym sposobem przetestowania konkretnejSqlExecutor
klasy są testy integracyjne, co jest dość uczciwe, ale jest to klasa cienkiego opakowania i rzadko się to zmienia, więc wielka sprawa.Nadal musisz przetestować również procedury składowane.
źródło
Mogę sprowadzić to do bardzo prostej linii myślenia: faworyzuj testy jednostkowe, ponieważ pomaga to zlokalizować błędy. I rób to konsekwentnie, ponieważ niespójności powodują zamieszanie.
Dalsze powody wynikają z tych samych zasad, które kierują rozwojem OO, ponieważ dotyczą one również testów. Na przykład zasada pojedynczej odpowiedzialności.
Jeśli wydaje się, że niektóre testy jednostkowe nie są warte wykonania, być może jest to znak, że temat nie jest w rzeczywistości wart. A może jego funkcjonalność jest bardziej abstrakcyjna niż jej odpowiednik, a testy dla niego (a także jego kodu) można wyodrębnić na wyższy poziom.
Jak w przypadku wszystkiego, są wyjątki. A programowanie wciąż jest w pewnym sensie sztuką, dlatego wiele problemów jest wystarczająco różnych, aby uzasadnić ich ocenę pod kątem najlepszego podejścia.
źródło