Kiedy powinienem pisać testy integracyjne?

30

Zgodnie z zasadami testów jednostkowych TDD są pisane przed kodem produkcyjnym, ale co z testami integracyjnymi, które ćwiczą interakcję między konkretnymi (nie udawanymi) obiektami przewodowymi?

Czy powinny być napisane przed testami jednostkowymi czy po kodzie produkcyjnym, aby przetestować „okablowanie”?

Pamiętaj, że nie mówię o testach akceptacyjnych ani funkcjonalnych, ale testach integracyjnych niższego poziomu.

Chedy2149
źródło

Odpowiedzi:

49

Rspec Book , wśród innych zasobów BDD, sugeruje taki cykl:

wprowadź opis zdjęcia tutaj

Zasadniczo proces jest następujący:

While behaviour required
    Write an integration test for a specific behaviour
    While integration test failing
        Write a unit test to fulfil partial behavior
        While unit test failing
            Write code to make unit test pass
        Commit
        While refactoring can be done
            Refactor
            While unit test failing
                Write code to make unit test pass
            Commit
    Push

Oświadczenie: nie mam wątpliwości, że prowadzi to do najlepszego kodu i produktu, ale może być czasochłonne. Istnieją różne rodzaje trudności związanych z danymi i determinizmem, jeśli chodzi o stwierdzenie, że testy integracyjne powinny zawsze przejść pomyślnie. Nie jest właściwe we wszystkich okolicznościach; czasami trzeba po prostu wyciągnąć coś z drzwi.

To powiedziawszy, mając na uwadze idealny proces, jest świetny. Daje ci punkt do kompromisu.

pdr
źródło
2
Dzięki @pdr, ale określiłem, że nie mówię o testach akceptacyjnych, które są pisane przed / na początku iteracji, jestem zainteresowany testami integracji niższego poziomu.
Chedy2149,
@ chedy2149: Akkh. Brakuje tego komentarza. Zanim usunę moją odpowiedź, uważam, że powinieneś sprecyzować, co rozumiesz przez „niższy poziom” w kontekście testów integracyjnych.
pdr
Poziom niższy: które zachowanie nie jest określone przez użytkowników lub klientów i które są używane do testowania interakcji klas / komponentów, czego oczekiwali deweloperzy.
Chedy2149,
4
Właściwie nie sądzę, żeby miało to znaczenie, jeśli umieścisz na tym obrazie „test akceptacyjny” lub „test integracyjny” - jest to wyidealizowany widok dla każdego rodzaju testów na różnych poziomach abstrakcji. Ale IMHO prawdziwym problemem nie jest to, że może to być „czasochłonne” - prawdziwym problemem jest to, że pisanie testów integracyjnych „wcześniej” przeciwko publicznemu interfejsowi, który wciąż jest opracowywany za pomocą TDD, jest jak strzelanie do „ruchomego celu „.
Doc Brown,
@DocBrown, więc Twoja odpowiedź jest po kodzie produkcyjnym i przed wydaniem?
Chedy2149,
10

Prawdziwy projekt pokazał mi, że nie jest możliwe napisanie testów jednostkowych, a następnie integracja, a nawet odwrotny kierunek jest niewłaściwy :-) Tak więc zwykle piszę testy jednostkowe razem z testami integracyjnymi.

Czemu? Pozwól mi napisać, jak widzę oba rodzaje testów:

  1. Testy jednostkowe - Oprócz Wikipedii i wszystkich znanych informacji, testy jednostkowe pomagają zawęzić projekt , ulepszyć model, relacje. Przebieg jest prosty: kiedy zaczniesz pisać nowy projekt / nowy komponent, przez większość czasu tworzysz jakiś rodzaj PoC . Kiedy skończysz, zawsze masz długie metody, długie klasy, niespójne metody i klasy itp.

    Testy jednostkowe pomagają usunąć te problemy, ponieważ podczas przeprowadzania rzeczywistych testów jednostkowych przy użyciu próbnych (bez zależności od innych komponentów) klas opisanych powyżej nie można przetestować. Podstawowym znakiem niestabilnego kodu jest duża część kpiąca testów, ponieważ jesteś zmuszony kpić z wielu zależności (lub sytuacji)

  2. Testy integracyjne - testy poprawne i robocze mówią ci, że twój nowy komponent (lub komponenty) współpracują razem lub z innymi komponentami - jest to zwykle definicja. Przekonałem się, że testy integracyjne w większości pomagają zdefiniować sposób korzystania z komponentu od strony konsumenta .

    Jest to naprawdę ważne, ponieważ czasami mówi ci, że Twój interfejs API nie ma sensu z zewnątrz.

Co się stanie, gdy później napisze testy jednostkowe i testy integracyjne?

Dostałem fajne klasy, przejrzysty projekt, dobry konstruktor, krótkie i spójne metody, gotowy na IoC itp. Gdy podałem moją klasę / interfejs API niektórym konsumentom, np. Programistom z zespołu ds. Integracji lub GUI, nie był w stanie używać mojego API, ponieważ wydaje się to nielogiczne , dziwne. Po prostu był zdezorientowany. Naprawiłem API zgodnie z jego punktem widzenia, ale wymagało to również przepisania wielu testów, ponieważ zmuszono mnie do zmiany metod, a czasem nawet do sposobu korzystania z API.

Co się stanie, gdy później napisałem testy integracyjne i testy jednostkowe?

Mam dokładny przepływ, dobrą użyteczność. Mam też duże klasy, niespójny kod, brak rejestrowania, długie metody. Kod spaghetti

Jaka jest moja rada

Nauczyłem się następującego przepływu:

  1. Opracuj podstawowy szkielet swojego kodu
  2. Napisz testy integracyjne, które stwierdzą, czy ma to sens z punktu widzenia konsumenta. Na razie wystarczy podstawowy przypadek użycia. Test oczywiście nie działa.
  3. Napisz kod wraz z testami jednostkowymi dla każdej klasy.
  4. Napisz resztę / brak testów integracji. Lepiej byłoby zaimplementować te testy w ramach # 3, w jaki sposób poprawiasz swój kod.

Zauważ, że zrobiłem małą prezentację na temat testowania jednostek / integracji, patrz slajd nr 21, w którym opisano szkielet.

Martin Podval
źródło
5

Testy jednostkowe służą do testowania najmniejszego możliwego do przetestowania bitu oprogramowania w aplikacji i testowania jego funkcjonalności. Każda jednostka jest testowana osobno przed połączeniem ich w części lub większe elementy aplikacji.

W tym momencie pojawiają się testy integracji :
testują te nowo utworzone części, które składają się z wcześniej przetestowanych jednostek podczas montażu tych części razem. Najlepszym rozwiązaniem byłoby napisanie testów w tym momencie podczas pisania samej aplikacji.

Ben McDougall
źródło
Więc twoja odpowiedź brzmi po kodzie produkcyjnym?
Chedy2149,
To nie odpowiada na pytanie. Pyta, czy kod produkcyjny jest napisany po napisaniu testów integracyjnych. Twoja odpowiedź może być podjęta w obie strony.
Reactgular,
1
@MathewFoscarini - zaktualizowana odpowiedź. Mam nadzieję, że teraz stanie się wyraźniejsze.
Ben McDougall,
Jeśli chodzi o testy jednostkowe, chciałbym mieć problem z „najmniejszym możliwym bitem oprogramowania”. Sprawdź, co jest w kontrakcie (np. Metody publiczne obiektu, funkcje eksportowane biblioteki), ponieważ umowa określa, co musi działać. Inne rzeczy są testowalne, ale ich działanie jest nie tylko stratą czasu, ale przynosi efekt przeciwny do zamierzonego.
itsbruce,
3

Testy integracji postrzegam jako bardzo podobne do testów jednostkowych. Pod tym względem traktuję podzbiór kodu jako czarną skrzynkę. Testy integracyjne są więc po prostu większym pudełkiem.

Wolę pisać je przed kodem produkcyjnym. Ma to tę zaletę, że pomaga mi zapamiętać, które elementy jeszcze nie podłączyłem lub że zmieniłem nieco szczegóły interakcji obiektów.

Schleis
źródło
Istnieją różne poziomy testowania: testowanie białej skrzynki, testowanie integracyjnej białej skrzynki. Testowanie czarnej skrzynki komponentów, testowanie czarnej skrzynki integracyjnej. Istnieje również testowanie systemu integracji.
Alexander.Iljushkin
2

Oprócz testów akceptacyjnych staram się pisać testy integracyjne tylko na granicach aplikacji, aby sprawdzić, czy dobrze integruje się z systemami lub komponentami innych firm.

Chodzi o to, aby utworzyć obiekty adaptera, które tłumaczą sposób, w jaki firma zewnętrzna mówi do tego, czego potrzebuje twoja aplikacja, i przetestuj tych translatorów na prawdziwym systemie zewnętrznym. Niezależnie od tego, czy wykonujesz ten test jako pierwszy, czy testowy, myślę, że jest mniej ważne niż w przypadku regularnych testów jednostkowych, ponieważ

  • Wgląd w projekt zapewniony przez TDD nie ma tutaj tak wielkiego znaczenia, ponieważ projekt jest dość dobrze znany z góry i zwykle nie ma w tym nic strasznie skomplikowanego, po prostu mapujesz rzeczy z jednego systemu do drugiego.

  • W zależności od modułu / systemu, którym chcesz się zająć, może to wymagać dużo eksploracji, majsterkowania konfiguracji, przygotowania danych próbek, co zajmuje dużo czasu i nie pasuje zbyt dobrze w krótkiej pętli sprzężenia zwrotnego TDD.

Jeśli jednak naprawdę czujesz się bardziej komfortowo, budując swój adapter stopniowo w małych, bezpiecznych krokach, zdecydowanie polecam przetestowanie go jako pierwszego, to nie zaszkodzi.

Przykłady tego podejścia można znaleźć tutaj: http://davesquared.net/2011/04/dont-mock-types-you-dont-own.html (6. akapit) http://blog.8thlight.com/eric- smith / 2011/10/27 / thats-not-yours.html

guillaume31
źródło
tutaj mówisz o testach integracyjnych, które weryfikują interakcje między „naszym systemem” a bibliotekami stron trzecich, co powiesz na testowanie interakcji z platformą podczas opracowywania na przykład wtyczki?
Chedy2149,
Chociaż mam niewielkie doświadczenie w tworzeniu wtyczek, myślę, że mogą się różnić, ponieważ z natury są ściśle powiązane z aplikacją hosta, więc możesz w pełni zaakceptować tę integrację i zdecydować, że nie potrzebujesz warstwy adaptera. W takim przypadku byłbym jednak bardzo ostrożny z wydajnością testu - w zależności od aplikacji hosta wywoływanie interfejsu API bezpośrednio w dużej liczbie testów może być bardzo wolne. Jeśli się tego obawiasz, zawsze możesz skorzystać z podejścia „dodatkowej warstwy abstrakcji” i użyć próbnych testów integracji na adapterach.
guillaume31,
1

Zamierzałem więc przyjąć pierwszą odpowiedź, ale została ona usunięta.
Podsumowując
w danej iteracji:

  1. Napisz test jednostkowy
  2. Napisz kod produkcyjny
  3. Napisz testy integracji, aby przetestować interakcje

Należy pamiętać o testach integracyjnych 1 i 2, aby zagwarantować testowalność na poziomie integracji.

Testy integracyjne niekoniecznie są pisane od końca do końca w kroku 3, mogą być częściowo zapisane między krokami 1 i 2.

Chedy2149
źródło
3
To podsumowanie całkowicie ignoruje iteracyjny charakter procesu. Gdy interfejs API Twojego kodu produkcyjnego będzie stabilny do pewnego stopnia, możesz rozpocząć pisanie testów integracyjnych. Następnie możesz ponownie pracować nad kodem produkcyjnym i prawdopodobnie zmienić lub rozszerzyć testy integracyjne. Tak więc w większości przypadków „nie piszesz testów integracyjnych po kodzie produkcyjnym”, zwykle robisz oba w pewnym stopniu równolegle. I tak naprawdę zależy to w dużej mierze od rodzaju oprogramowania, na którym pracujesz. Myślenie „czarno-białe” nie prowadzi cię dalej.
Doc Brown
Dobra uwaga: odpowiedź wydaje się ignorować iteracyjną naturę projektu poprzez refaktoryzację.
Chedy2149,
0

Testy jednostkowe testują dyskretne bloki kodu w projekcie.
Testy integracyjne sprawdzają, w jaki sposób twój kod łączy się z innym kodem: innymi słowy, testują interfejs twojego kodu.

Napisz testy jednostkowe podczas opracowywania kodu za interfejsem.
Napisz testy integracji podczas opracowywania interfejsu lub dowolnego kodu implementującego interfejs.

Oznacza to, że czasem testy integracyjne będą pisane bardzo późno w projekcie, ponieważ większość pracy znajduje się za interfejsem: na przykład kompilator, konkretna usługa internetowa, która implementuje kilka warstw logiki lub ... coś, co wymaga dużej ilości logika wewnętrzna.

Jeśli jednak wdrażasz zestaw usług REST lub refaktoryzujesz model danych i dodajesz obsługę transakcji XA, prawie natychmiast zaczniesz opracowywać testy integracyjne, ponieważ większość pracy koncentruje się wokół interfejsu, niezależnie od tego, czy jest to interfejs interfejs API REST lub sposób, w jaki program korzysta z modelu danych.

Marco
źródło
Czy zgodziłbyś się powiedzieć, że testy jednostkowe to testy białej skrzynki, a testy integracyjne to testy czarnej skrzynki?
Chedy2149,
Niestety to zależy. Technologie testowania integracji poczyniły w ostatnich latach ogromne udoskonalenia (przynajmniej w świecie Java), dzięki czemu mogę przetestować 1 klasę - ale na serwerze aplikacji. Powstaje zatem pytanie, gdzie przebiega granica między testami jednostkowymi a testami integracyjnymi? Czy test integracji podczas testowania kodu współpracuje z innymi technologiami, czy test integracji podczas testowania całej aplikacji - ale niekoniecznie w środowisku, w którym ma ona działać?
Marco,
Krótko mówiąc, w niektórych przypadkach pewne testy integracyjne to testy czarnej skrzynki - ale nie we wszystkich przypadkach.
Marco,
FYI: Wiki definiuje testy integracyjne jako „fazę testowania oprogramowania, w której poszczególne moduły oprogramowania są łączone i testowane jako grupa”
Marco,
Dokładnie, Marco. Istnieją integracje na każdym poziomie komponentów. Poziom kodu, poziom aplikacji, poziom systemu.
Alexander.Iljushkin