Jak przeprowadzić test jednostkowy? [Zamknięte]


89

Oglądałem webcasty Roba Connerysa w aplikacji MVCStoreFront i zauważyłem, że testował jednostkowo nawet najbardziej przyziemne rzeczy, takie jak:

public Decimal DiscountPrice
{
   get
   {
       return this.Price - this.Discount;
   }
}

Miałby taki test:

[TestMethod]
public void Test_DiscountPrice
{
    Product p = new Product();
    p.Price = 100;
    p.Discount = 20;
    Assert.IsEqual(p.DiscountPrice,80);
}

Chociaż jestem za testowaniem jednostkowym, czasami zastanawiam się, czy ta forma testowania pierwszego programowania jest naprawdę korzystna, na przykład w prawdziwym procesie masz 3-4 warstwy nad kodem (żądanie biznesowe, dokument wymagań, dokument architektury) , gdzie rzeczywista zdefiniowana reguła biznesowa (cena rabatu to cena - rabat) mogła zostać błędnie zdefiniowana.

Jeśli tak jest, twój test jednostkowy nic dla ciebie nie znaczy.

Ponadto test jednostkowy jest kolejnym punktem niepowodzenia:

[TestMethod]
public void Test_DiscountPrice
{
    Product p = new Product();
    p.Price = 100;
    p.Discount = 20;
    Assert.IsEqual(p.DiscountPrice,90);
}

Teraz test jest błędny. Oczywiście w prostym teście to nic wielkiego, ale powiedzmy, że testowaliśmy skomplikowaną regułę biznesową. Co tu zyskujemy?

Przenieś się dwa lata do przodu w życie aplikacji, gdy zajmują się nią programiści. Teraz firma zmienia swoją zasadę, a test znowu się psuje, jakiś początkujący programista naprawia test niepoprawnie ... teraz mamy kolejny punkt niepowodzenia.

Widzę tylko więcej możliwych punktów awarii, bez realnie korzystnego zwrotu, jeśli cena rabatu jest nieprawidłowa, zespół testowy nadal znajdzie problem, w jaki sposób testy jednostkowe uratowały jakąkolwiek pracę?

Czego tu brakuje? Naucz mnie kochać TDD, ponieważ do tej pory ciężko mi zaakceptować to jako przydatne. Ja też chcę, ponieważ chcę być postępowy, ale to po prostu nie ma dla mnie sensu.

EDYCJA: Kilka osób wspomina, że ​​testowanie pomaga egzekwować zgodność ze specyfikacją. Z mojego doświadczenia wynika, że ​​specyfikacja też się myliła, częściej niż nie, ale może jestem skazany na pracę w organizacji, w której specyfikacje są pisane przez ludzi, którzy nie powinni pisać specyfikacji.


5
w wielu przypadkach test jednostkowy jest specyfikacją, a także dokumentacją!
Steven A. Lowe

32
... a następnie test jednostkowy test jednostkowy testu jednostkowego ... ale co z testem jednostki ^ 4 i testem jednostkowym ^ 5 ... aaaaaaaaahhhhhhhhh!
dacracot

14
Żadna ilość testów nie uchroni Cię przed błędną specyfikacją.
Bill the Lizard,

4
Czy ktoś jeszcze słyszał coś, co brzmiało jak klaskanie jedną ręką?
gnovice

9
Myślę, że odpowiedni cytat brzmi: „To tylko żółwie na samym dole”.
Quinn Taylor

Odpowiedzi:


63

Po pierwsze, testowanie jest jak bezpieczeństwo - nigdy nie możesz być w 100% pewien, że je masz, ale każda warstwa dodaje więcej pewności i ramy ułatwiające naprawianie problemów, które pozostają.

Po drugie, można podzielić testy na podprogramy, które następnie można przetestować. Kiedy masz 20 podobnych testów, wykonanie (przetestowanego) podprogramu oznacza, że ​​twój główny test składa się z 20 prostych wywołań podprogramu, co jest o wiele bardziej poprawne.

Po trzecie, niektórzy twierdzą, że TDD rozwiązuje ten problem. Oznacza to, że jeśli po prostu napiszesz 20 testów, a one przejdą, nie masz całkowitej pewności, że faktycznie testują cokolwiek. Ale jeśli każdy test, który napisałeś początkowo, nie powiódł się , a potem go naprawiłeś, wtedy masz znacznie większą pewność, że naprawdę testuje twój kod. IMHO to tam iz powrotem zajmuje więcej czasu niż jest warte, ale jest to proces, który próbuje rozwiązać twój problem.


2
Aby zagrać w diabła adwokata, widzę dodatkowe warstwy jako więcej możliwych punktów porażki, co nie dodaje mi pewności siebie. W mojej prawdziwej pracy pracuję z wieloma zespołami w wysoce rozproszonym przedsiębiorstwie SOA. Każdy z tych zespołów może zagrozić projektowi, jeśli jego warstwa zawiedzie.
FlySwat

2
Dlatego używasz obiektów pozorowanych do testowania każdej warstwy osobno.
Toon Krijthe

10
Świetnie, więc mój test przejdzie przy użyciu IMockedComplexObject, ale kiedy faktycznie używam ComplexObject w prawdziwym świecie, kończy się niepowodzeniem ... Znowu nic nie zyskałem.
FlySwat

16
@Jonathan - nie, zyskałeś pewność, że twój kod działa - zakładając, że rozwinąłeś interfejs ComplexObject i odpowiednio przetestowałeś ten interfejs. W najgorszym przypadku zdałeś sobie sprawę, że twoje zrozumienie ComplexObject nie było tym, czego się spodziewałeś.
tvanfosson

9
@FlySwat: W odpowiedzi na Twój komentarz dotyczący IMockedComplexObject, cytuję komentarz Cwasha dotyczący innej odpowiedzi: „Nie kpisz z tego, co próbujesz przetestować, kpisz z tego, czego nie próbujesz testować”.
Brian

39

Błędny test prawdopodobnie nie złamie twojego kodu produkcyjnego. Przynajmniej nie gorzej niż brak testu. Nie jest to więc „punkt awarii”: testy nie muszą być poprawne, aby produkt faktycznie działał. Być może będą musiały być poprawne, zanim zostaną zatwierdzone jako działające, ale proces naprawiania wszelkich uszkodzonych testów nie zagraża kodowi implementacji.

Możesz myśleć o testach, nawet takich trywialnych testach, jako o drugiej opinii, co ma robić kod. Jedna opinia to test, druga to implementacja. Jeśli się nie zgadzają, wiesz, że masz problem i przyjrzyj się bliżej.

Jest to również przydatne, jeśli ktoś w przyszłości będzie chciał zaimplementować ten sam interfejs od podstaw. Nie powinni musieli czytać pierwszej implementacji, aby wiedzieć, co oznacza Rabat, a testy stanowią jednoznaczną kopię zapasową każdego pisemnego opisu interfejsu, który możesz mieć.

To powiedziawszy, tracisz czas. Jeśli istnieją inne testy, które możesz napisać, wykorzystując zaoszczędzony czas, pomijając te trywialne testy, być może byłyby bardziej wartościowe. To zależy tak naprawdę od konfiguracji testu i natury aplikacji. Jeśli rabat jest ważny dla aplikacji, i tak wyłapiesz wszelkie błędy w tej metodzie podczas testów funkcjonalnych. Testy jednostkowe pozwalają tylko złapać je w momencie testowania tej jednostki, kiedy lokalizacja błędu będzie natychmiast oczywista, zamiast czekać, aż aplikacja zostanie zintegrowana, a lokalizacja błędu może być mniej oczywista.

Nawiasem mówiąc, osobiście nie użyłbym 100 jako ceny w przypadku testowym (a raczej gdybym to zrobił, dodałbym kolejny test z inną ceną). Powodem jest to, że ktoś w przyszłości może pomyśleć, że Rabat ma być procentem. Jednym z celów takich trywialnych testów jest upewnienie się, że błędy w czytaniu specyfikacji zostaną poprawione.

[Odnośnie edycji: myślę, że jest nieuniknione, że nieprawidłowa specyfikacja jest punktem awarii. Jeśli nie wiesz, co ma robić aplikacja, prawdopodobnie tego nie zrobi. Ale pisanie testów odzwierciedlających specyfikację nie powiększa tego problemu, po prostu go nie rozwiązuje. Więc nie dodajesz nowych punktów awarii, po prostu reprezentujesz istniejące błędy w kodzie zamiast w dokumentacji waflowej .]


4
Zły test wypuści uszkodzony kod na wolność. Tam właśnie pojawia się awaria. Daje fałszywe poczucie pewności.
FlySwat

9
To prawda, ale brak testu pozwala również na uszkodzenie kodu. Błędem jest myślenie, że jeśli kod przejdzie testy jednostkowe, to musi być poprawny - wyleczyłem się z tego dość wcześnie w mojej karierze. Tak więc uszkodzony test jednostkowy nie wypuszcza zepsutego kodu na wolność, a jedynie do testów integracyjnych.
Steve Jessop

7
Ponadto nawet zły test może wykryć uszkodzony kod, o ile zawiera on różne błędy implementacji. Chodzi mi o to, że testy absolutnie nie muszą być poprawne, są po to, aby zwrócić twoją uwagę na obszary zainteresowania.
Steve Jessop

2
bardzo interesująca odpowiedź.
Peter

22

Widzę tylko więcej możliwych punktów awarii, bez realnie korzystnego zwrotu, jeśli cena rabatu jest nieprawidłowa, zespół testowy nadal znajdzie problem, w jaki sposób testy jednostkowe uratowały jakąkolwiek pracę?

Testy jednostkowe nie mają tak naprawdę oszczędzać pracy, mają pomóc w znajdowaniu błędów i zapobieganiu im. To więcej pracy, ale to właściwy rodzaj pracy. Myśli o Twoim kodzie na najniższych poziomach szczegółowości i pisze przypadki testowe, które udowodnią, że działa on w oczekiwanych warunkach, dla danego zestawu danych wejściowych. Izoluje zmienne, dzięki czemu możesz zaoszczędzić czas , szukając we właściwym miejscu, gdy pojawi się błąd. To oszczędność to zestaw testów, dzięki czemu można wykorzystać je ponownie i ponownie, gdy trzeba dokonać zmian w dół drogi.

Osobiście uważam, że większość metodologii to niewiele kroków oderwanych od inżynierii oprogramowania kultowego cargo , w tym TDD, ale nie musisz przestrzegać ścisłego TDD, aby czerpać korzyści z testów jednostkowych. Zachowaj dobre części i wyrzuć te, które przynoszą niewielkie korzyści.

Wreszcie odpowiedź na tytułowe pytanie „ Jak przeprowadzić test jednostkowy w teście jednostkowym? ” Brzmi: nie powinieneś tego robić. Każdy test jednostkowy powinien być prosty w obsłudze. Wywołaj metodę z określonymi danymi wejściowymi i porównaj ją z oczekiwanymi wynikami. Jeśli specyfikacja metody ulegnie zmianie, można się spodziewać, że niektóre testy jednostkowe tej metody również będą wymagały zmiany. To jeden z powodów, dla których przeprowadzasz testy jednostkowe na tak niskim poziomie szczegółowości, więc tylko niektóre testy jednostkowe muszą się zmienić. Jeśli okaże się, że testy dla wielu różnych metod zmieniają się z powodu jednej zmiany wymagania, być może testowanie nie odbywa się na wystarczająco wysokim poziomie szczegółowości.


„Wywołaj metodę z określonym wejściem i porównaj ją z oczekiwanymi wynikami”. ale co, jeśli wynik jest złożonym typem ... jak dokument XML. Nie możesz po prostu "==", będziesz musiał napisać konkretne porównanie kodu, a wtedy może twoja metoda porównywania może być wadliwa?
andy

@andy: Musisz osobno przetestować swoją metodę porównania. Po dokładnym przetestowaniu możesz polegać na tym, że działa w innych testach.
Bill the Lizard,

super, dzięki Bill. Zacząłem pracować w nowym miejscu i to mój pierwszy raz z testami jednostkowymi. Myślę, że w zasadzie to działa i używamy tempomatu tam, gdzie jest naprawdę przydatny, ale duże zestawy testów wydają się mieć ten sam los co starszy kod ... Po prostu nie jestem tego pewien ...
andy

11

Testy jednostkowe istnieją po to, aby Twoje jednostki (metody) robiły to, czego oczekujesz. Napisanie testu zmusza Cię do przemyślenia tego, czego oczekujesz, zanim napiszesz kod. Pomyślenie przed zrobieniem jest zawsze dobrym pomysłem.

Testy jednostkowe powinny odzwierciedlać reguły biznesowe. To prawda, że ​​w kodzie mogą być błędy, ale napisanie testu najpierw pozwala napisać go z perspektywy reguły biznesowej, zanim zostanie napisany jakikolwiek kod. Myślę, że późniejsze napisanie testu jest bardziej prawdopodobne, że doprowadzi do błędu, który opisujesz, ponieważ wiesz, w jaki sposób kod go implementuje i masz pokusę, aby upewnić się, że implementacja jest poprawna, a nie, że intencja jest poprawna.

Ponadto testy jednostkowe to tylko jedna forma - i to najmniejsza - testów, które powinieneś pisać. Należy również napisać testy integracyjne i testy akceptacyjne, które w miarę możliwości powinien wykonać klient, aby upewnić się, że system działa zgodnie z oczekiwaniami. Jeśli znajdziesz błędy podczas tego testowania, wróć i napisz testy jednostkowe (które się nie powiodą), aby przetestować zmianę w funkcjonalności, aby działała poprawnie, a następnie zmień kod, aby test przeszedł pomyślnie. Teraz masz testy regresji, które wychwytują poprawki błędów.

[EDYTOWAĆ]

Kolejna rzecz, którą odkryłem podczas robienia TDD. Prawie domyślnie wymusza dobry projekt. Wynika to z faktu, że wysoce powiązane projekty są prawie niemożliwe do przeprowadzenia testów jednostkowych w izolacji. Użycie TDD nie zajmuje dużo czasu, aby dowiedzieć się, że używanie interfejsów, odwrócenie kontroli i wstrzykiwanie zależności - wszystkie wzorce, które poprawią twój projekt i zmniejszą sprzężenie - są naprawdę ważne dla testowalnego kodu.


Być może na tym polega mój problem. Mogę wizualizować algorytm reguły biznesowej niżej, niż mogę wizualizować wynik, więc nie mam problemu z implementacją samego kodu, ale kpienie z reguły uważam za zbędne. Może po prostu tak myślę.
FlySwat

Dokładnie to robisz w teście jednostkowym. Podziel ten algorytm na części i sprawdź każdy element. Zazwyczaj stwierdzam, że mój kod pisze się sam, ponieważ napisałem już oczekiwania w moim teście jednostkowym.
tvanfosson

Mock to przeładowany termin w przestrzeni testowej. Nie kpisz z tego, co próbujesz przetestować, kpisz z tego, czego nie próbujesz przetestować ... Kiedy piszesz test dla swojej reguły biznesowej, tworzysz kod, który go wywołuje - w ogóle go nie kpi .
cwash

@cwash - nie jestem pewien, jak Twój komentarz odnosi się do mojej odpowiedzi. Nie wspomniałem o kpinie ... i zgadzam się z twoją obserwacją.
tvanfosson

@tvanfosson - mój ostatni komentarz był odpowiedzią na @FlySwat „... kpiąc z reguły jako zbędną”. Przepraszam, zapomniałem określić.
cwash

10

Jak przetestować test ? Testowanie mutacji to cenna technika, której osobiście używałem, aby uzyskać zaskakująco dobry efekt. Przeczytaj artykuł, do którego prowadzą linki, aby uzyskać więcej informacji i linki do jeszcze większej liczby referencji akademickich, ale generalnie „testuje on testy”, modyfikując kod źródłowy (np. Zmieniając „x + = 1” na „x - = 1”), a następnie ponowne uruchomienie testów, upewniając się, że co najmniej jeden test się nie powiedzie. Wszelkie mutacje, które nie powodują niepowodzeń testów, są oznaczane do późniejszego zbadania.

Zdziwiłbyś się, jak możesz mieć 100% pokrycie linii i gałęzi za pomocą zestawu testów, które wyglądają kompleksowo, a mimo to możesz zasadniczo zmienić lub nawet skomentować wiersz w swoim źródle bez narzekania żadnego z testów. Często sprowadza się to do tego, że nie testuje się z odpowiednimi wejściami, aby pokryć wszystkie przypadki graniczne, czasami jest to bardziej subtelne, ale we wszystkich przypadkach byłem pod wrażeniem, jak wiele z tego wyszło.


1
+1 interesująca koncepcja, o której jeszcze nie słyszałem
Wim Coenen

9

Stosując programowanie sterowane testami (TDD), zaczyna się od negatywnego testu. Ten krok, który może wydawać się zbędny, ma na celu sprawdzenie, czy test jednostkowy coś testuje. Rzeczywiście, jeśli test nigdy się nie powiedzie, nie przynosi żadnej wartości, a co gorsza, prowadzi do błędnej pewności, ponieważ polegasz na pozytywnym wyniku, który niczego nie dowodzi.

Ściśle przestrzegając tego procesu, wszystkie „jednostki” są chronione przez siatkę bezpieczeństwa, którą wykonują testy jednostkowe, nawet najbardziej przyziemne.

Assert.IsEqual(p.DiscountPrice,90);

Nie ma powodu, dla którego test rozwija się w tym kierunku - albo czegoś mi brakuje w twoim rozumowaniu. Gdy cena wynosi 100, a rabat 20, cena rabatu wynosi 80. To jest jak niezmiennik.

Teraz wyobraź sobie, że Twoje oprogramowanie musi obsługiwać inny rodzaj rabatu opartego na procentach, być może w zależności od zakupionego wolumenu, Twoja metoda Product :: DiscountPrice () może stać się bardziej skomplikowana. Możliwe, że wprowadzenie tych zmian łamie prostą regułę rabatową, którą mieliśmy na początku. Wtedy zobaczysz wartość tego testu, który natychmiast wykryje regresję.


Red - Green - Refactor - ma to na celu zapamiętanie istoty procesu TDD.

Czerwony odnosi się do czerwonego paska JUnit, gdy test zakończy się niepowodzeniem.

Zielony to kolor paska postępu JUnit po przejściu wszystkich testów.

Refaktoryzacja w stanie zielonym: usuń wszelkie powielenia, popraw czytelność.


Teraz, aby odnieść się do twojego punktu dotyczącego „3-4 warstw nad kodem”, jest to prawdą w tradycyjnym procesie (podobnym do kaskady), a nie w przypadku zwinnego procesu tworzenia. A agile to świat, z którego pochodzi TDD; TDD jest kamieniem węgielnym eXtreme Programming .

Agile polega na bezpośredniej komunikacji, a nie na rzucaniu dokumentów z wymaganiami.


8

Chociaż jestem za testowaniem jednostkowym, czasami zastanawiam się, czy ta forma testowania pierwszego rozwoju jest naprawdę korzystna ...

Małe, trywialne testy, takie jak ten, mogą być „kanarkiem w kopalni” dla Twojej bazy kodów, ostrzegając o niebezpieczeństwie, zanim będzie za późno. Trywialne testy są przydatne, ponieważ pomagają w prawidłowym przeprowadzaniu interakcji.

Na przykład pomyśl o trywialnym teście wprowadzonym w celu zbadania, jak korzystać z interfejsu API, którego nie znasz. Jeśli ten test ma jakikolwiek związek z tym, co robisz w kodzie, który używa interfejsu API „w rzeczywistości”, warto go zachować. Kiedy API wyda nową wersję i musisz zaktualizować. Masz teraz swoje założenia dotyczące oczekiwanego zachowania interfejsu API zapisane w formacie wykonywalnym, którego można użyć do przechwytywania regresji.

... [ja] w rzeczywistym procesie masz 3-4 warstwy nad swoim kodem (wniosek biznesowy, dokument wymagań, dokument architektury), w których rzeczywista zdefiniowana reguła biznesowa (cena rabatowa to cena - rabat) może być błędnie zdefiniowana. Jeśli tak jest, twój test jednostkowy nic dla ciebie nie znaczy.

Jeśli od lat programujesz bez pisania testów, może nie być od razu oczywiste, że ma to jakąkolwiek wartość. Ale jeśli myślisz, że najlepszym sposobem pracy jest „wydawanie wczesne, wydawanie często” lub „zwinność”, ponieważ chcesz mieć możliwość szybkiego / ciągłego wdrażania, to Twój test zdecydowanie coś znaczy. Jedynym sposobem na to jest legitymizowanie każdej zmiany wprowadzanej w kodzie za pomocą testu. Bez względu na to, jak mały jest test, po uzyskaniu zielonego zestawu testów teoretycznie można je wdrożyć. Zobacz także „ciągła produkcja” i „wieczysta wersja beta”.

Nie musisz też najpierw „testować”, aby mieć taki sposób myślenia, ale jest to generalnie najskuteczniejszy sposób, aby się tam dostać. Kiedy wykonujesz TDD, zamykasz się w małym, trwającym od dwóch do trzech minut cyklu Red Green Refactor. W żadnym momencie nie jesteś w stanie zatrzymać się i wyjść i mieć kompletnego bałaganu na rękach, którego debugowanie i ponowne złożenie zajmie godzinę.

Dodatkowo twój test jednostkowy jest kolejnym punktem niepowodzenia ...

Pomyślny test to taki, który wykazuje awarię w systemie. Niepowodzenie testu ostrzeże Cię o błędzie w logice testu lub w logice Twojego systemu. Celem testów jest złamanie kodu lub udowodnienie, że jeden scenariusz działa.

Jeśli piszesz testy po kodzie, ryzykujesz napisaniem testu, który jest „zły”, ponieważ aby zobaczyć, że Twój test naprawdę działa, musisz zobaczyć, że jest on zarówno uszkodzony, jak i działa. Kiedy piszesz testy po kodzie, oznacza to, że musisz „wyzwolić pułapkę” i wprowadzić błąd do kodu, aby zobaczyć, że test się nie powiedzie. Większość programistów nie tylko jest z tego powodu zaniepokojona, ale twierdzi, że jest to strata czasu.

Co tu zyskujemy?

Robienie rzeczy w ten sposób zdecydowanie przynosi korzyści. Michael Feathers definiuje „stary kod” jako „nieprzetestowany kod”. Stosując to podejście, legitymizujesz każdą zmianę wprowadzoną w bazie kodu. Jest to bardziej rygorystyczne niż niestosowanie testów, ale jeśli chodzi o utrzymanie dużej bazy kodu, opłaca się.

Mówiąc o piórach, są dwa świetne zasoby, które powinieneś sprawdzić w związku z tym:

Obydwa wyjaśniają, jak zastosować tego typu praktyki i dyscypliny w projektach, które nie są „greenfield”. Zapewniają techniki pisania testów wokół ściśle powiązanych komponentów, twardych zależności i rzeczy, nad którymi niekoniecznie masz kontrolę. Chodzi o znalezienie „szwów” i przetestowanie ich.

[I] Jeśli cena rabatu jest nieprawidłowa, zespół testowy nadal znajdzie problem, w jaki sposób testy jednostkowe uratowały jakąkolwiek pracę?

Takie nawyki są jak inwestycja. Zwroty nie są natychmiastowe; z czasem narastają. Alternatywą dla braku testowania jest zasadniczo zaciągnięcie długu w postaci braku możliwości wychwycenia regresji, wprowadzenia kodu bez obawy o błędy integracji lub podejmowania decyzji projektowych. Piękno polega na tym, że legitymizujesz każdą zmianę wprowadzoną w swoim kodzie.

Czego tu brakuje? Naucz mnie kochać TDD, ponieważ do tej pory ciężko mi zaakceptować to jako przydatne. Ja też chcę, ponieważ chcę być postępowy, ale to po prostu nie ma dla mnie sensu.

Traktuję to jako odpowiedzialność zawodową. To ideał, do którego warto dążyć. Ale jest to bardzo trudne i nużące. Jeśli zależy ci na tym i uważasz, że nie powinieneś tworzyć kodu, który nie jest testowany, będziesz w stanie znaleźć siłę woli, aby nauczyć się dobrych nawyków testowania. Jedną z rzeczy, które robię teraz (podobnie jak inni), jest czas na samodzielne pisanie kodu bez żadnych testów, a następnie posiadanie dyscypliny, aby go wyrzucić. Może się to wydawać marnotrawstwem, ale tak nie jest. To nie jest tak, że to ćwiczenie kosztuje firmowe materiały fizyczne. Pomogło mi to zrozumieć problem i jak pisać kod w taki sposób, aby był zarówno wyższej jakości, jak i testowalny.

Moja rada byłaby taka, że ​​jeśli naprawdę nie masz ochoty być w tym dobrym, to w ogóle tego nie rób. Słabe testy, które nie są utrzymywane, nie działają dobrze itp. Mogą być gorsze niż brak jakichkolwiek testów. Trudno jest się uczyć samemu i prawdopodobnie nie spodoba ci się to, ale nauka będzie prawie niemożliwa, jeśli nie masz ochoty tego robić lub nie widzisz w tym wystarczającej wartości gwarantuje inwestycję czasu.

Kilka osób wspomina, że ​​testowanie pomaga egzekwować zgodność ze specyfikacją. Z mojego doświadczenia wynika, że ​​specyfikacja również się myliła, najczęściej ...

Klawiatura programisty to miejsce, w którym guma styka się z drogą. Jeśli specyfikacja jest nieprawidłowa i nie podnosisz na niej flagi, jest wysoce prawdopodobne, że zostaniesz za to obwiniony. A przynajmniej twój kod będzie. Dyscyplina i rygor związany z testowaniem jest trudny do przestrzegania. To wcale nie jest łatwe. Wymaga praktyki, dużo nauki i wielu błędów. Ale ostatecznie to się opłaca. W szybko zmieniającym się projekcie to jedyny sposób, w jaki możesz spać w nocy, bez względu na to, czy spowalnia.

Inną rzeczą do przemyślenia jest to, że techniki, które są zasadniczo takie same jak testowanie, okazały się działać w przeszłości: „pomieszczenie czyste” i „projektowanie na podstawie umowy” mają tendencję do tworzenia tych samych typów konstrukcji kodu „meta”, które testy robią i wymuszają je w różnych punktach. Żadna z tych technik nie jest srebrną kulą, a rygor ostatecznie będzie Cię kosztował w zakresie funkcji, które możesz dostarczyć pod względem czasu wprowadzenia na rynek. Ale nie o to chodzi. Chodzi o to, aby móc utrzymać to, co dostarczasz. Jest to bardzo ważne w przypadku większości projektów.


7

Testowanie jednostkowe działa bardzo podobnie do prowadzenia ksiąg podwójnego zapisu. Podajesz tę samą rzecz (regułę biznesową) na dwa zupełnie różne sposoby (jako reguły zaprogramowane w kodzie produkcyjnym i jako proste, reprezentatywne przykłady w testach). Jest bardzo mało prawdopodobne, że popełnisz ten sam błąd w obu, więc jeśli obaj zgadzają się ze sobą, jest raczej mało prawdopodobne, abyś się pomylił.

W jaki sposób testowanie będzie warte wysiłku? Z mojego doświadczenia wynika, że ​​przynajmniej na cztery sposoby, przynajmniej podczas tworzenia oprogramowania sterowanego testami:

  • pomaga w opracowaniu dobrze odsprzężonego projektu. Możesz tylko test jednostkowy kod, który jest dobrze oddzielony;
  • pomaga określić, kiedy skończysz. Konieczność określenia potrzebnego zachowania w testach pomaga nie budować funkcjonalności, której w rzeczywistości nie potrzebujesz, i określić, kiedy funkcjonalność jest kompletna;
  • daje ci siatkę bezpieczeństwa dla refaktoryzacji, dzięki czemu kod jest dużo bardziej podatny na zmiany; i
  • oszczędza dużo czasu na debugowanie, co jest strasznie kosztowne (słyszałem, że tradycyjnie programiści spędzają do 80% czasu na debugowaniu).

5

Większość testów jednostkowych, założenia testowe. W takim przypadku cena rabatu powinna być ceną pomniejszoną o rabat. Jeśli twoje założenia są błędne, założę się, że twój kod również jest zły. A jeśli popełnisz głupi błąd, test zakończy się niepowodzeniem i poprawisz go.

Jeśli zasady się zmienią, test zakończy się niepowodzeniem i to dobrze. Więc w tym przypadku również musisz zmienić test.

Zasadniczo, jeśli test od razu się nie powiedzie (i nie używasz najpierw projektu testowego), albo test, albo kod są nieprawidłowe (lub oba, jeśli masz zły dzień). Używasz zdrowego rozsądku (i być może według specyfikacji), aby poprawić nieprawidłowy kod i ponownie przeprowadzić test.

Jak powiedział Jason, testowanie to bezpieczeństwo. I tak, czasami wprowadzają dodatkową pracę z powodu błędnych testów. Ale w większości przypadków pozwalają zaoszczędzić dużo czasu. (I masz doskonałą okazję, aby ukarać gościa, który złamie test (mówimy o gumowym kurczaku)).


4

Przetestuj wszystko, co możesz. Nawet trywialne błędy, takie jak zapomnienie o przeliczeniu metrów na stopy, mogą mieć bardzo kosztowne skutki uboczne. Napisz test, napisz kod do sprawdzenia, spraw, aby zdał, przejdź dalej. Kto wie, w przyszłości ktoś może zmienić kod rabatowy. Test może wykryć problem.


To nie dotyczy moich myśli. Rozumiem podstawową mantrę TDD ... Nie widzę korzyści.
FlySwat

4

Uważam, że testy jednostkowe i kod produkcyjny mają związek symbiotyczny. Krótko mówiąc: jedno testuje drugie. I oba testują dewelopera.


3

Pamiętaj, że koszt naprawy defektów rośnie (wykładniczo) w miarę jak defekty przeżywają cykl rozwojowy. Tak, zespół testujący może wykryć usterkę, ale (zwykle) zajmie więcej pracy, aby wyodrębnić i naprawić usterkę od tego momentu, niż gdyby test jednostkowy się nie powiódł, i łatwiej będzie wprowadzić inne usterki podczas naprawiania, jeśli nie ma testów jednostkowych do uruchomienia.

Zwykle łatwiej to zobaczyć na czymś więcej niż trywialnym przykładzie ... a przy trywialnych przykładach, cóż, jeśli w jakiś sposób zepsujesz test jednostkowy, osoba przeglądająca go złapie błąd w teście lub błąd w kodzie, lub obie. (Są sprawdzane, prawda?) Jak wskazuje tvanfosson , testy jednostkowe to tylko jedna część planu SQA.

W pewnym sensie testy jednostkowe są ubezpieczeniem. Nie gwarantują, że złapiesz każdą usterkę i czasami może się wydawać, że wydajesz na nie dużo zasobów, ale kiedy złapią defekty, które możesz naprawić, wydasz znacznie mniej niż gdybyś nie miał żadnych testów i musiałbyś naprawić wszystkie usterki w dalszej części.


3

Rozumiem twój punkt widzenia, ale jest to wyraźnie przesadzone.

Twój argument jest zasadniczo taki: testy wprowadzają porażkę. Dlatego testy są złe / strata czasu.

Chociaż może to być prawdą w niektórych przypadkach, nie jest to większość.

TDD zakłada: Więcej testów = mniej awarii.

Testy częściej wychwytują punkty awarii niż je wprowadzają.


1

Może tu pomóc jeszcze większa automatyzacja! Tak, pisanie testów jednostkowych może wymagać dużo pracy, więc skorzystaj z kilku narzędzi, które Ci w tym pomogą. Spójrz na coś takiego jak Pex firmy Microsoft, jeśli używasz .Net. Automatycznie utworzy dla Ciebie zestawy testów jednostkowych, sprawdzając Twój kod. Pojawi się testy, które zapewniają dobre pokrycie, próbując objąć wszystkie ścieżki w kodzie.

Oczywiście, patrząc na swój kod, nie można wiedzieć, co tak naprawdę próbujesz zrobić, więc nie wie, czy jest poprawny, czy nie. Ale wygeneruje dla ciebie interesujące przypadki testowe, a następnie możesz je zbadać i zobaczyć, czy zachowuje się zgodnie z oczekiwaniami.

Jeśli następnie pójdziesz dalej i napiszesz sparametryzowane testy jednostkowe (tak naprawdę możesz o nich myśleć jak o kontraktach), wygeneruje z nich określone przypadki testowe i tym razem będzie wiedział, czy coś jest nie tak, ponieważ twoje asercje w testach zawiodą.


1

Zastanawiałem się trochę nad dobrym sposobem odpowiedzi na to pytanie i chciałbym narysować paralelę do metody naukowej. IMO, możesz przeformułować to pytanie: „Jak eksperymentować z eksperymentem?”

Eksperymenty weryfikują empiryczne założenia (hipotezy) dotyczące fizycznego wszechświata. Testy jednostkowe będą testować założenia dotyczące stanu lub zachowania wywoływanego kodu. Możemy mówić o słuszności eksperymentu, ale to dlatego, że dzięki wielu innym eksperymentom wiemy, że coś nie pasuje. Nie ma zarówno zbieżnej ważności, jak i dowodów empirycznych . Nie projektujemy nowego eksperymentu, aby przetestować lub zweryfikować ważność eksperymentu , ale możemy zaprojektować zupełnie nowy eksperyment .

Podobnie jak w przypadku eksperymentów , nie opisujemy ważności testu jednostkowego na podstawie tego, czy sam przejdzie test jednostkowy. Wraz z innymi testami jednostkowymi opisuje założenia, jakie przyjmujemy na temat testowanego systemu. Podobnie jak w przypadku eksperymentów, staramy się usunąć jak najwięcej złożoności z tego, co testujemy. „Tak proste, jak to tylko możliwe, ale nie prostsze”.

W przeciwieństwie do eksperymentów , mamy w zanadrzu sztuczkę, która pozwala nam zweryfikować, że nasze testy są trafne, a nie tylko zbieżne. Możemy sprytnie wprowadzić błąd, o którym wiemy, że powinien zostać wyłapany przez test, i sprawdzić, czy test rzeczywiście się nie powiedzie. (Gdybyśmy tylko mogli to zrobić w prawdziwym świecie, bylibyśmy znacznie mniej zależni od tej zbieżnej ważności!) Bardziej wydajnym sposobem na to jest obejrzenie niepowodzenia testu przed jego wdrożeniem (czerwony krok w kolorze czerwonym, zielonym, refaktoryzacji ).


1

Pisząc testy, musisz używać odpowiedniego paradygmatu.

  1. Zacznij od napisania testów.
  2. Upewnij się, że nie zaczną.
  3. Pozwól im przejść.
  4. Przegląd kodu przed sprawdzeniem kodu (upewnij się, że testy zostały przejrzane).

Nie zawsze możesz być pewien, ale poprawiają one ogólne testy.


0

Nawet jeśli nie przetestujesz swojego kodu, z pewnością zostanie on przetestowany w produkcji przez Twoich użytkowników. Użytkownicy są bardzo kreatywni, próbując zawiesić oprogramowanie i znaleźć nawet niekrytyczne błędy.

Naprawianie błędów w produkcji jest znacznie droższe niż rozwiązywanie problemów w fazie rozwoju. Efektem ubocznym jest utrata dochodów z powodu exodusu klientów. Możesz liczyć na 11 utraconych lub nie pozyskanych klientów na 1 złego klienta.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.