Zautomatyzowane testy jednostkowe, testy integracyjne lub testy akceptacyjne [zamknięte]

29

Wydaje się, że TDD i testy jednostkowe są obecnie wielką atrakcją. Ale czy to naprawdę przydatne w porównaniu z innymi formami automatycznego testowania?

Intuicyjnie zgaduję, że automatyczne testowanie integracji jest znacznie bardziej przydatne niż testowanie jednostkowe. Z mojego doświadczenia wynika, że ​​najwięcej błędów dotyczy interakcji między modułami, a nie rzeczywistej (zwykle ograniczonej) logiki każdej jednostki. Często dochodziło również do regresji z powodu zmiany interfejsów między modułami (oraz zmiany warunków wstępnych i końcowych).

Czy coś nie rozumiem lub dlaczego testy jednostkowe są tak bardzo skoncentrowane w porównaniu z testami integracyjnymi? Jest tak po prostu dlatego, że zakłada się, że testowanie integracji to coś, co masz, a testowanie jednostkowe to kolejna rzecz, której musimy nauczyć się stosować jako programiści?

A może testy jednostkowe dają po prostu najwyższy zysk w porównaniu ze złożonością automatyzacji?

Jakie są Twoje doświadczenia związane ze zautomatyzowanymi testami jednostkowymi, automatycznymi testami integracji i automatycznymi testami akceptacyjnymi, a jakie doświadczenie przyniosło najwyższy zwrot z inwestycji? i dlaczego?

Gdybyś musiał wybrać tylko jedną formę testowania, która ma zostać zautomatyzowana przy następnym projekcie, co by to było?

Z góry dziękuję.

Bjarke Freund-Hansen
źródło
Chciałbym tylko dodać spóźniony link do testów integracyjnych JB Rainsbergera to oszustwo . Podkreśla wiele powodów, dla których testy integracyjne są fałszywą ekonomią.
Tim
6
To kolejny przykład zamknięcia pytania, które było idealnie w tej witrynie, kiedy zostało zadane trzy lata temu! Wspieranie społeczności, w której zasady się zmieniają, jest po prostu irytujące, a wyrzucasz wszystkie stare rzeczy!
Bjarke Freund-Hansen

Odpowiedzi:

34

Jednym z ważnych czynników, który sprawia, że ​​testy jednostkowe są niezwykle przydatne, jest szybkie sprzężenie zwrotne .

Zastanów się, co stanie się, gdy aplikacja będzie w pełni objęta testami integracji / systemu / testów funkcjonalnych (co jest już idealną sytuacją, daleką od rzeczywistości w większości sklepów programistycznych). Są one często prowadzone przez dedykowany zespół testujący.

  • Zatwierdzasz zmianę w repozytorium SCM,
  • kiedyś (ewentualnie dni) później testujący dostaną nową wewnętrzną wersję i zaczną ją testować,
  • znajdują błąd i składają raport o błędzie,
  • (w idealnym przypadku) ktoś przypisuje ci raport o błędzie.

To wszystko może potrwać dni, a nawet tygodnie. Do tego czasu pracujesz już nad innymi zadaniami, więc nie masz w pamięci najmniejszych szczegółów kodu. Co więcej, zazwyczaj nie masz nawet bezpośredniego dowodu na to, gdzie rzeczywiście jest błąd, więc znalezienie i naprawienie błędu zajmuje dużo czasu.

Podczas gdy w testach jednostkowych (TDD)

  • piszesz test
  • piszesz kod, aby spełnić test,
  • test wciąż się nie udaje,
  • patrzysz na kod i zazwyczaj masz „ups” w ciągu kilku sekund (np. „ups, zapomniałem sprawdzić ten warunek!”), a następnie
  • napraw błąd natychmiast.

Wszystko to dzieje się w ciągu kilku minut .

Nie oznacza to, że testy integracyjne / systemowe nie są przydatne; służą po prostu innym celom. Dzięki dobrze napisanym testom jednostkowym można wykryć dużą część błędów w kodzie, zanim przejdą one do fazy integracji, gdzie ich znalezienie i naprawienie jest już znacznie droższe. Masz rację, że testy integracyjne są potrzebne do wykrycia tego rodzaju błędów, które są trudne lub niemożliwe do wykrycia przy pomocy testów jednostkowych. Jednak z mojego doświadczenia są one rzadsze; większość błędów, które widziałem, jest spowodowana przez proste lub nawet trywialne pominięcie gdzieś wewnątrz metody.

Nie wspominając o tym, że testy jednostkowe testują również interfejsy pod kątem użyteczności / bezpieczeństwa itp., Zapewniając w ten sposób niezwykle ważne informacje zwrotne w celu ulepszenia projektu i interfejsów API. Które IMHO może znacznie zmniejszyć szanse na błędy integracji modułu / susbsystemu: im łatwiejszy i czystszy interfejs API, tym mniejsza szansa na nieporozumienie lub pominięcie.

Jakie są Twoje doświadczenia związane ze zautomatyzowanymi testami jednostkowymi, automatycznymi testami integracji i automatycznymi testami akceptacyjnymi, a jakie doświadczenie przyniosło najwyższy zwrot z inwestycji? i dlaczego?

Zwrot z inwestycji zależy od wielu czynników, prawdopodobnie najważniejszym z nich jest to, czy Twój projekt jest typu greenfield, czy jest dziedzictwem. Wraz z rozwojem od podstaw moja rada (i dotychczasowe doświadczenie) to od samego początku testowanie jednostek w stylu TDD. Jestem przekonany, że w tym przypadku jest to najbardziej opłacalna metoda.

Jednak w starszym projekcie zbudowanie wystarczającego zasięgu testów jednostkowych jest ogromnym przedsięwzięciem, które będzie bardzo wolno przynosić korzyści. Bardziej efektywne jest próbowanie objęcia najważniejszych funkcji testami systemowymi / funkcjonalnymi za pośrednictwem interfejsu użytkownika, jeśli to możliwe. (aplikacje GUI na komputery stacjonarne mogą być trudne do automatycznego testowania za pomocą GUI, chociaż narzędzia do automatycznego testowania są stopniowo ulepszane ...) Daje to szybko zgrubną, ale skuteczną siatkę bezpieczeństwa. Następnie możesz zacząć stopniowo budować testy jednostkowe wokół najbardziej krytycznych części aplikacji.

Gdybyś musiał wybrać tylko jedną formę testów do zautomatyzowanego w następnym projekcie, co by to było?

To pytanie teoretyczne i uważam je za bezcelowe. Wszystkie rodzaje testów mają zastosowanie w zestawie narzędzi dobrego inżyniera SW, a wszystkie mają scenariusze, w których są niezastąpione.

Péter Török
źródło
2
+1 za „szybką informację zwrotną” dla testów jednostkowych. Jest także bardzo przydatny do uruchamiania jako post-commit na serwerze Continuous Integration.
Frank Shearar
1
„Wszystkie rodzaje testów mają zastosowanie w zestawie narzędzi dobrego inżyniera SW, a wszystkie mają scenariusze, w których są niezastąpione”. - Chciałbym móc głosować kilka razy tylko na to! Ludzie, którzy myślą, że mogą po prostu znaleźć jedno idealne narzędzie / metodę testową i zastosować ją wszędzie, nudzą mnie.
ptyx
8

Wszystkie typy testów są bardzo ważne i zapewniają, że różne aspekty systemu są określone. Więc pracując wstecz, „gdybym musiał wybrać jeden rodzaj testowania ...” nie zrobiłbym tego. Testy jednostkowe dostarczają mi innych informacji zwrotnych niż testy integracyjne lub testy interaktywne przeprowadzane przez osobę.

Oto rodzaj / korzyści testowania, które wykonujemy:

  • Testowanie jednostkowe - zapewnia, że ​​urządzenia wykonują pracę zgodnie z oczekiwaniami. Testujemy umowy zarówno z dostawcą, jak i konsumentem dla każdego interfejsu - i jest to dość łatwe do zautomatyzowania. Sprawdzamy również nasze warunki brzegowe itp.
  • Testy integracyjne - zapewniają, że urządzenia współpracują ze sobą w zgodzie. Ma to głównie na celu przetestowanie naszego projektu. Jeśli coś się tutaj psuje, musimy dostosować nasze testy jednostkowe, aby upewnić się, że to się więcej nie powtórzy.
  • Testowanie systemu - zapewnia, że ​​system spełnia wymagania / specyfikacje. Zwykle ludzie przeprowadzają tego typu testy.
  • Testy akceptacyjne - klient robi to, aby sprawdzić, czy produkt końcowy robi to, co jest reklamowane.

Opcjonalne, ale zalecane testowanie:

  • Testowanie doświadczenia użytkownika: Chociaż otrzymujemy przyzwoitą informację zwrotną z testów systemowych, o tym, że ludzie z klienta przeglądają niektóre wersje wstępne, może naprawdę pomóc ustalić, czy musimy zmienić rzeczy, zanim będzie za późno.

Aby zrozumieć, dlaczego testowanie jednostkowe ma przewagę nad testami integracyjnymi, musisz zrozumieć dodatkowe testy rzędów wielkości, które byłyby konieczne. Dla każdego możliwego wyniku dla jednostki A musi istnieć test. To samo dotyczy jednostki B. Teraz, jeśli obie z nich współpracują w celu uzyskania bardziej kompletnego rozwiązania, liczba testów jest kombinatoryczna. Krótko mówiąc, aby przetestować każdą kombinację interakcji między jednostką A i jednostką B, potrzebujesz testów A * B. Dodaj jednostkę C, a liczba testów dla trio wyniesie A * B * C.

W tym miejscu koncepcja interfejsów i granic obiektów staje się bardzo ważna. Interfejsy stanowią określoną umowę. Implementor z interfejsem zgadza się, że będzie zachowywać się w określony sposób. Podobnie konsument interfejsu zgadza się, że użyje implementacji w określony sposób. Pisząc test, który zbiera każdą klasę implementującą interfejs, możesz łatwo przetestować, czy każda implementacja przestrzega umów interfejsu. To połowa równania. Druga połowa to przetestowanie strony konsumenta - w której pojawiają się fałszywe obiekty. Makieta jest skonfigurowana tak, aby zapewnić, że interakcje są zawsze zgodne ze specyfikacją. W tym momencie wszystko, czego potrzeba, to kilka testów integracyjnych, aby upewnić się, że mamy poprawne umowy między implementatorem a konsumentem.

Berin Loritsch
źródło
„Testowanie systemu - upewnia się, że system spełnia wymagania / specyfikacje Zwykle ludzie przeprowadzają tego typu testy”. Testy integracji systemu / aka funkcjonalne / akty „end-to-end” / aka wysokiego poziomu są również dobre dla automatyzacji.
MiFreidgeim SO-przestań być zły
3

Są to różne narzędzia o różnych celach:

  • Testowanie jednostkowe jest narzędziem projektowym (TDD) i prawie warunkiem wstępnym refaktoryzacji.

  • Testy integracyjne świetnie nadają się do wizualizacji postępu projektu, a także świetnie zapobiegają błędom regresji.

Należy pamiętać, że tak naprawdę nie można projektować za pomocą testów integracyjnych i nie można znaleźć regresji przy testach jednostkowych.

Javier
źródło
@Nie możesz naprawdę projektować za pomocą testów integracyjnych i nie znajdziesz regresji przy testach jednostkowych. Dokładnie!
Chankey Pathak
Testy jednostkowe mogą wykryć regresje spowodowane refaktoryzacją, np. Zmienioną metodę współużytkowanego pomocnika. Testy integracyjne są jednak znacznie lepsze.
StuperUser
Drugi punkt dotyczący testów integracyjnych obejmuje testy „systemowe / funkcjonalne” (
znane również
W pełni uzgodnione; podobny punkt przedstawił kilka lat temu Steve Sanderson. Zobacz tabelę „Cel - najsilniejsza technika” w jego wpisie na blogu w 2009 r. Na blog.stevensanderson.com/2009/08/24/..., aby uzyskać nieco komplementarne przemyślenia na swój temat tutaj.
Mark A. Fitzgerald
1

Użyłem Selen szeroko do testów poprawności.

W dużej firmie wydawniczej, kiedy powstało nowe wydanie, zwykle potrzeba około 3 testerów około godziny lub dwóch, aby odwiedzić wszystkie rodziny witryn i upewnić się, że wszystko jest w porządku, zgodnie ze skryptem testowym. Dzięki Selenium byliśmy w stanie zautomatyzować testy i dystrybuować je na wielu komputerach i przeglądarkach. Obecnie, kiedy uruchamiane są skrypty testowe, automatyczne wykonanie tej samej czynności ORAZ wyrzucenie ładnego raportu zajmuje 3 komputerom około 10 minut.

Wielką zaletą selenu jest to, że można go powiązać z platformami do testów jednostkowych, takimi jak XUnit, TestNG lub MSTest.

Z mojego doświadczenia wynika, że ​​było to niezwykle cenne, jednak konfiguracja czegoś takiego naprawdę zależy od twojego projektu i zespołu, więc ROI na pewno będzie się różnić.

Ryan Hayes
źródło
1

Najlepszy zwrot z inwestycji to zwykle najwcześniejsze testy, w których można znaleźć tego rodzaju błąd.

Testy jednostkowe powinny znaleźć większość błędów, które dotyczą tylko jednej metody lub jednego komponentu. Wykrywa błędy, które zwykle można naprawić w ciągu kilku minut, przy całkowitym czasie zawracania krótszym niż jedna godzina. BARDZO tanie testy, BARDZO tanie błędy do znalezienia i naprawy! Jeśli te błędy przeszły do ​​testowania integracji, zwrot może być bardziej podobny do dnia (testy często odbywają się co noc), zakładając, że błąd nie zostanie zasłonięty przez inny błąd; plus prawdopodobnie pojawi się więcej błędów, ponieważ inny kod został napisany przeciwko początkowemu kodowi błędów; plus wszelkie przeprojektowania wpłyną na więcej fragmentów kodu. Ponadto dopuszczenie większej liczby błędów oznacza konieczność wykonania o wiele większej liczby testów przed zakończeniem testów integracyjnych. Słabe testy jednostkowe często leżą u podstaw długich, uciążliwych i kosztownychtestowe cykle integracji. Pomijanie testów jednostkowych może skrócić czas opracowywania o połowę, ale testowanie potrwa co najmniej 3 do 4 razy dłużej, cały projekt podwoi swoją długość, a ty nadal będziesz mieć gorszą jakość niż w przypadku testowania jednostkowego IME.

Testy integracyjne są zwykle najwcześniejszymi rzeczywistymi testami, które mogą znaleźć błędy integracyjne (chociaż procesy przeglądu mogą znaleźć pewne błędy przed napisaniem oprogramowania lub zanim kod przejdzie do testowania). Chcesz znaleźć te błędy, zanim zaczniesz pokazywać oprogramowanie użytkownikowi lub wydać, ponieważ usuwanie błędów w ostatnim momencie (lub naprawianie na gorąco!) Jest bardzo drogie. Nie można znaleźć tych błędów wcześniej, gdy byłoby to tańsze do naprawienia, ponieważ potrzebujesz wielu działających komponentów do zintegrowania (z definicji). Testy integracyjne ulegają spowolnieniu, gdy błędy, które nie mają nic wspólnego z oddziałującymi elementami (jak drobne literówki), muszą zostać rozwiązane w pierwszej kolejności, zanim zaczną się bardziej interesujące testy.

Testy akceptacji użytkownika upewniają się, że oprogramowanie robi to, czego chce klient (chociaż, mam nadzieję, że klient był zaangażowany przez cały czas, aby zmniejszyć ryzyko znalezienia ogromnej luki między oczekiwaniami a faktycznym oprogramowaniem na końcu projektu - BARDZO drogie !). Zanim przejdziesz do tego etapu testowania, naprawdę powinieneś uwierzyć, że większość błędów w twoim produkcie, w porównaniu do specyfikacji, została już znaleziona. Testy akceptacji użytkownika polegają bardziej na upewnieniu się, że produkt odpowiada potrzebom klienta, niż na upewnieniu się, że nie ma błędów w porównaniu ze specyfikacjami.

Gdybym miał zautomatyzować tylko jeden rodzaj testów, byłoby to testowanie jednostkowe. Testy integracyjne mogą być wykonywane ręcznie i były wykonywane w ten sposób przez wiele dużych firm przez lata. Ręczne wykonywanie pracy, którą komputer może wykonywać w kółko, jest bardziej czasochłonne, a w przypadku większości projektów znacznie droższe, nie wspominając o nudach i podatności na błędy, ale można to zrobić. Testy akceptacyjne użytkownika są często ręczne, ponieważ użytkownicy często nie wiedzą, jak zautomatyzować swoje testy, wciąż testując to, na czym im zależy. Testy jednostkowe MUSZĄ być zautomatyzowane. Musisz być w stanie uruchomić wszystkie testy jednostkowe w ciągu kilku sekund na żądanie tak często, jak co kilka minut. Ludzie nie mogą nawet zbliżyć się do testów manualnych. Nie wspominając o tym, że testy jednostkowe są w kodzie i nie można ich wykonać bez wywołania ich za pomocą kodu, tj. Zautomatyzowania ich.

Należy pamiętać, że jest to forum przede wszystkim dla programistów, a nie testerów. Testy integracyjne są głównie wdrażane przez testerów. Testy jednostkowe są wdrażane przez programistów. Oczywiście programiści mówią więcej o testowaniu jednostkowym niż o innych typach testów. Nie oznacza to, że nie sądzą, aby inne testy były ważne. Oznacza to po prostu, że tak naprawdę tego nie robią (lub robią to rzadziej).

Ethel Evans
źródło
Dzięki szczególnie za ten ostatni akapit, nie myślałem o tym.
Bjarke Freund-Hansen
Do Twojej wiadomości zaktualizowałem odpowiedź, odkąd ją przeczytałeś - zdałem sobie sprawę, że nie przeczytałem wystarczająco oryginalnego pytania
Ethel Evans
@EthelEvans, twoje powody dotyczące priorytetów testów jednostkowych są prawidłowe dla nowych projektów. W przypadku starszych projektów, które zostały napisane bez uwzględnienia automatyzacji zakresu testów, najważniejsze są testy integracji systemowej / funkcjonalnej / aka wysokiego poziomu. Zobacz ostatnią część odpowiedzi na programmers.stackexchange.com/a/39370/31574 .
MiFreidgeim SO-przestań być zły
@MichaelFreidgeim, ostatecznie zależy od tego, jak stabilne są interfejsy. Automatyzacja testów wysokiego poziomu może szybko ponieść wygórowane koszty konserwacji, jeśli szybko przestaną być aktualne. W takim przypadku należy zautomatyzować obniżanie, aby pomóc w budowaniu stabilności i zastosować testy eksploracyjne (ewentualnie oparte na sesji lub liście kontrolnej) dla testów E2E i testów integracyjnych, aby uniknąć ponoszenia nieprzyjemnych kosztów utrzymania automatyzacji. Jednak nie wszystkie starsze projekty mają stabilne interfejsy - szczególnie jeśli są poddawane reaktywacji lub agresywnej reorganizacji.
Ethel Evans,
1

W tym scenariuszu czuję, że testy akceptacyjne są królem.

Jeśli zatwierdzenie przerwie testy akceptacyjne, należy je rozwiązać.

Testy akceptacyjne wskazują, gdzie znajduje się twoje oprogramowanie, testy jednostkowe nie.

Dlatego testy jednostkowe mogą zapewnić bardzo fałszywe poczucie bezpieczeństwa.

godelfiend
źródło
0

Pytanie jest nie tyle ważne, co to, co można zautomatyzować i uruchomić szybko.

Testy jednostkowe pokazują, czy mały element nadaje się do określonego celu, a zazwyczaj jest mały i szybki do uruchomienia. Ponieważ są małe, zwykle można je łatwo zautomatyzować.

Testy integracyjne pokazują, czy komponenty współpracują ze sobą. Są zwykle znacznie większe i mogą nie być łatwe do zautomatyzowania. Uruchomienie może potrwać dłużej. Zaletą jest to, że można je uruchamiać automatycznie, ale jest to większe zadanie i i tak nie będą uruchamiane tak często.

Testy akceptacyjne pokazują, czy projekt jest akceptowalny czy nie. Jest to zwykle niemożliwe do pełnej automatyzacji (chociaż automatyczne testy mogą odgrywać pewną rolę), ponieważ zwykle niemożliwe jest ustalenie dokładnych i pełnych wymagań w kwestii formalnej, która jest mniej skomplikowana niż sam kod źródłowy. Testy akceptacyjne zwykle obejmują potencjalnych użytkowników zajmujących się systemem i obserwujących, że wyniki są zadowalające pod każdym względem, co zwykle jest częściowo subiektywne. Ponieważ testy akceptacyjne są zwykle uruchamiane raz (różni klienci zwykle będą chcieli przeprowadzać własne oddzielne testy akceptacyjne), naprawdę nie warto automatyzować.

David Thornley
źródło