Najwyraźniej w niektórych organizacjach częścią procesu wydawania oprogramowania jest testowanie jednostkowe, ale w dowolnym momencie wszystkie testy jednostkowe muszą przejść pomyślnie. Np. Może być jakiś ekran, który pokazuje wszystkie testy jednostkowe przechodzące na zielono - co powinno być dobre.
Osobiście uważam, że tak nie powinno być z następujących powodów:
Promuje ideę, że kod powinien być idealny i nie powinny istnieć żadne błędy - co w prawdziwym świecie jest z pewnością niemożliwe dla programu dowolnej wielkości.
Odradza się wymyślanie testów jednostkowych, które się nie powiodą. Lub z pewnością wymyślą testy jednostkowe, które byłyby trudne do naprawienia.
Jeśli w dowolnym momencie wszystkie testy jednostkowe zakończą się pomyślnie, nie ma dużego obrazu stanu oprogramowania w żadnym momencie. Nie ma mapy drogowej / celu.
Odstrasza pisanie testów jednostkowych z góry - przed wdrożeniem.
Sugerowałbym nawet, że nawet wydanie oprogramowania z nieudanymi testami jednostkowymi nie jest konieczne. Przynajmniej wtedy wiesz, że niektóre aspekty oprogramowania mają ograniczenia.
Czy coś mi umyka? Dlaczego organizacje oczekują pozytywnego wyniku wszystkich testów jednostkowych? Czy to nie życie w świecie snów? I czy tak naprawdę nie przeszkadza to w prawdziwym zrozumieniu kodu?
źródło
Odpowiedzi:
To pytanie zawiera kilka nieporozumień, ale najważniejsze, na którym chciałbym się skupić, to to, że nie rozróżnia gałęzi rozwoju lokalnego, gałęzi trunk, inscenizacji lub wydania.
W lokalnym oddziale deweloperskim może się zdarzyć, że w dowolnym momencie przeprowadzą niektóre testy jednostkowe. W bagażniku jest do pewnego stopnia akceptowalny, ale już silny wskaźnik, aby naprawić rzeczy JAK NAJSZYBCIEJ. Pamiętaj, że nieudane testy jednostkowe w bagażniku mogą przeszkadzać reszcie zespołu, ponieważ wymagają od wszystkich sprawdzenia, czy nie jego ostatnia zmiana spowodowała awarię.
W gałęzi pomostowej lub zwalniającej testy zakończone niepowodzeniem są „czerwonym alarmem”, wskazując, że zniknęło coś zupełnie nie tak z jakimś zestawem zmian, gdy został on scalony z pnia do gałęzi zwalniającej.
Wydanie oprogramowania z pewnymi znanymi błędami poniżej określonego poziomu nie musi być złe. Te znane usterki nie powinny jednak powodować niepowodzenia testu jednostkowego. W przeciwnym razie, po każdym uruchomieniu testu jednostkowego, trzeba będzie sprawdzić 20 nieudanych testów jednostkowych i sprawdzić jeden po drugim, czy awaria była dopuszczalna, czy nie. To staje się kłopotliwe, podatne na błędy i odrzuca ogromną część aspektu automatyzacji testów jednostkowych.
Jeśli naprawdę masz testy na akceptowalne, znane błędy, skorzystaj z funkcji wyłączania / ignorowania narzędzia do testowania jednostek (aby nie były uruchamiane domyślnie, tylko na żądanie). Dodatkowo dodaj bilet o niskim priorytecie do narzędzia do śledzenia problemów, aby problem nie został zapomniany.
źródło
To jest dobre. Nie ma w tym „być”.
Nie. Dowodzi to, że przetestowałeś kod tak dobrze, jak możesz. Jest całkiem możliwe, że twoje testy nie obejmują wszystkich przypadków. Jeśli tak, ewentualne błędy pojawią się w raportach o błędach, a ty napiszesz [nieudane] testy w celu odtworzenia problemów, a następnie naprawisz aplikację tak, aby testy zakończyły się pomyślnie.
Niepowodzenie lub negatywne testy nakładają twarde ograniczenia na to, co Twoja aplikacja zaakceptuje i nie zaakceptuje. Większość programów, które znam, sprzeciwi się „dacie” 30 lutego. Ponadto programiści, którymi jesteśmy kreatywni, nie chcą łamać „swoich dzieci”. Koncentracja na przypadkach „szczęśliwej ścieżki” prowadzi do kruchych aplikacji, które często się psują.
Aby porównać sposób myślenia programisty i testera:
Są to radykalnie różne perspektywy, które trudno jest pogodzić wielu programistom.
Nie piszesz testów, aby pracować dla siebie. Piszesz testy, aby upewnić się, że Twój kod robi to, co powinien, a co ważniejsze, że nadal robi to, co powinien, po zmianie wewnętrznej implementacji.
Jedynym testem „obrazkowym” jest migawka, w której kod „działa” w momencie, w którym został przetestowany. Jak ewoluuje potem, to inna historia.
Właśnie to powinieneś robić. Napisz test, który się nie powiedzie (ponieważ metoda, którą testuje, nie został jeszcze zaimplementowany), a następnie napisz kod metody, aby metoda zadziałała, a tym samym pozytywny wynik testu. To właściwie sedno rozwoju opartego na testach.
Zwolnienie kodu z uszkodzonymi testami oznacza, że część jego funkcjonalności nie działa już tak jak wcześniej. Może to być celowe działanie, ponieważ naprawiłeś błąd lub ulepszyłeś funkcję (ale najpierw powinieneś zmienić test, aby się nie powiódł, a następnie zakodować poprawkę / ulepszenie, aby test działał w tym procesie). Co ważniejsze: wszyscy jesteśmy ludźmi i popełniamy błędy. Jeśli złamiesz kod, powinieneś przerwać testy, a te zepsute testy powinny ustawić dzwonienie dzwonków alarmowych.
Jeśli już, to żyje w świecie rzeczywistym , uznając, że deweloperzy nie są ani wszechwiedzący, ani infallable, że możemy zrobić, popełniają błędy i że potrzebujemy siatki bezpieczeństwa złapać nas, czy i kiedy zrobić bałagan!
Wprowadź testy.
Być może. Niekoniecznie musisz rozumieć implementację czegoś, aby napisać testy na to (to jest ich sedno). Testy określają zachowanie i ograniczenia aplikacji i zapewniają, że pozostają one takie same, chyba że celowo je zmienisz.
źródło
Nie są - rozwój oparty na testach opiera się na pojęciu testów zakończonych niepowodzeniem. Niepowodzenie testów jednostkowych prowadzących do rozwoju, niepowodzenie testów akceptacyjnych do prowadzenia historii ....
Brakuje kontekstu ; gdzie testy jednostkowe mogą się nie powieść?
Zazwyczaj odpowiedź jest taka, że testy jednostkowe mogą się nie powieść tylko w prywatnych obszarach izolowanych.
Podstawowa koncepcja jest następująca: w środowisku, w którym dzielone są testy zakończone niepowodzeniem, dodatkowy wysiłek wymaga zrozumienia, czy zmiana kodu produkcyjnego spowodowała nowy błąd. Różnica między zero a nie zero jest znacznie łatwiejsza do wykrycia i zarządzania niż różnica między N a N.
Ponadto utrzymywanie kodu współdzielonego w czystości oznacza, że programiści mogą pozostać przy zadaniu. Kiedy scalam twój kod, nie muszę zmieniać kontekstów od problemu, za który płacę mi rozwiązanie, do skalowania mojego zrozumienia, ile testów powinno się nie udać. Jeśli wspólny kod przechodzi wszystkie testy, wszelkie awarie pojawiające się podczas scalania moich zmian muszą być częścią interakcji między moim kodem a istniejącą czystą linią bazową.
Podobnie podczas wprowadzania na pokład nowy programista może szybciej zwiększyć produktywność, ponieważ nie musi tracić czasu na odkrywanie, które testy negatywne są „dopuszczalne”.
Mówiąc ściślej: dyscyplina polega na tym, że testy przeprowadzane podczas kompilacji muszą przejść pomyślnie.
Jak mogę powiedzieć, nie ma nic złego w wyłączaniu nieudanych testów .
Na przykład w środowisku „ciągłej integracji” będziesz dzielić się kodem z dużą częstotliwością. Często integracja niekoniecznie oznacza, że zmiany muszą być gotowe do wydania. Istnieje szereg ciemnych technik wdrażania, które zapobiegają uwalnianiu ruchu do sekcji kodu, dopóki nie będą gotowe.
Te same techniki można również wykorzystać do wyłączenia testów zakończonych niepowodzeniem.
Jednym z ćwiczeń, które przeszedłem po wydaniu punktu, było opracowanie produktu z wieloma nieudanymi testami. Odpowiedzią, którą wymyśliliśmy, było po prostu przejrzenie pakietu, wyłączenie nieudanych testów i udokumentowanie każdego z nich. To pozwoliło nam szybko dotrzeć do punktu, w którym wszystkie włączone testy przeszły, a zarząd / darczyńca / właściciel złota mogli zobaczyć wszystkie transakcje, które podjęliśmy, aby dojść do tego punktu, i mogli podejmować świadome decyzje o oczyszczeniu a nowej pracy.
W skrócie: istnieją inne techniki śledzenia pracy, które nie zostały wykonane, niż pozostawienie szeregu nieudanych testów w uruchomionym pakiecie.
źródło
Istnieje wiele świetnych odpowiedzi, ale chciałbym dodać jeszcze jeden punkt, który moim zdaniem nie jest jeszcze dobrze opisany: jaki jest sens przeprowadzania testów.
Testy jednostkowe nie służą sprawdzeniu, czy Twój kod nie zawiera błędów.
Myślę, że to jest główne nieporozumienie. Gdyby to była ich rola, rzeczywiście można by się spodziewać, że w każdym miejscu będą mieć niepomyślne testy. Lecz,
Testy jednostkowe sprawdzają, czy Twój kod działa tak, jak myślisz.
W skrajnych przypadkach może to obejmować sprawdzenie, czy znane błędy nie zostały naprawione. Chodzi o to, aby mieć kontrolę nad bazą kodu i unikać przypadkowych zmian. Po dokonaniu zmiany wszystko jest w porządku i spodziewane jest przerwanie niektórych testów - zmieniasz zachowanie kodu. Świeżo zepsuty test to teraz dobry ślad tego, co zmieniłeś. Sprawdź, czy wszystkie pęknięcia są zgodne z tym, czego oczekujesz od zmiany. Jeśli tak, po prostu zaktualizuj testy i kontynuuj. Jeśli nie - no cóż, twój nowy kod jest zdecydowanie wadliwy, wróć i napraw go przed przesłaniem!
Teraz wszystkie powyższe działania działają tylko wtedy, gdy wszystkie testy są zielone, co daje mocne pozytywne wyniki: dokładnie tak działa kod. Czerwone testy nie mają tej właściwości. „Tego nie robi ten kod” rzadko jest użyteczną informacją.
Testy akceptacyjne mogą być tym, czego szukasz.
Istnieje coś takiego jak test akceptacyjny. Możesz napisać zestaw testów, które należy spełnić, aby wywołać kolejny kamień milowy. Mogą być czerwone, ponieważ do tego właśnie zostały zaprojektowane. Ale są one bardzo różne od testów jednostkowych i nie mogą ani nie powinny ich zastąpić.
źródło
Widzę to jako programowy odpowiednik zespołu rozbitego okna .
Testy robocze mówią mi, że kod ma określoną jakość i że właściciele kodu dbają o to.
Jeśli chodzi o to, kiedy powinieneś dbać o jakość, zależy to raczej od gałęzi / repozytorium kodu źródłowego, nad którym pracujesz. Kod deweloperski mógł mieć bardzo zepsute testy wskazujące na trwające prace (miejmy nadzieję!).
Zepsute testy w oddziale / repozytorium dla systemu na żywo powinny natychmiast ustawić dzwonienie dzwonków alarmowych. Jeśli zepsute testy mogą nadal kończyć się niepowodzeniem lub jeśli są trwale oznaczone jako „zignoruj” - spodziewaj się, że ich liczba z czasem się powiększy. Jeśli nie będą one regularnie sprawdzane, zostanie ustawiony precedens, że pozostawienie uszkodzonych testów jest w porządku.
Zepsute testy są tak pejoratywnie oglądane w wielu sklepach, że mają ograniczenia co do tego, czy uszkodzony kod może być nawet popełniony .
źródło
Oto podstawowy logiczny błąd:
Dzięki testom jednostkowym dobrze jest, gdy wszystkie testy przejdą pomyślnie. Jest również DOBRY, gdy test się nie powiedzie. Obaj nie muszą być w opozycji.
Niepowodzenie testu to problem, który został złapany przez twoje narzędzie zanim dotarł do użytkownika. To okazja, aby naprawić błąd przed opublikowaniem. I to dobrze.
źródło
Odpowiedź Phill W. jest świetna. Nie mogę tego zastąpić.
Chcę jednak skupić się na innej części, która mogła być częścią zamieszania.
„w dowolnym momencie” przesadza z twoją sprawą. Co ważne, testy jednostkowe przechodzą po wprowadzeniu pewnej zmiany, zanim zaczniesz wdrażać kolejną zmianę.
W ten sposób możesz śledzić, która zmiana spowodowała błąd. Jeśli testy jednostkowe rozpoczęły się niepowodzeniem po wdrożeniu zmiany 25, ale przed wdrożeniem zmiany 26, oznacza to, że zmiana 25 spowodowała błąd.
Oczywiście podczas wdrażania zmiany testy jednostkowe mogą się nie powieść; tat bardzo zależy od tego, jak duża jest zmiana. Jeśli przebudowuję podstawową funkcję, która jest czymś więcej niż drobną poprawką, prawdopodobnie przerwie testy na jakiś czas, dopóki nie skończę implementować mojej nowej wersji logiki.
Może to powodować konflikty dotyczące zasad zespołu. Tak naprawdę spotkałem to kilka tygodni temu:
Każda reguła byłaby w porządku. Ale obie zasady nie mogą ze sobą współpracować. Jeśli przydzielono mi poważną zmianę, której ukończenie zajmuje kilka dni, nie byłbym w stanie przestrzegać obu zasad jednocześnie. Chyba że będę komentował moje zmiany każdego dnia i dopuściłbym się ich bez komentarza po tym, jak wszystko zostało zrobione; która jest po prostu nonsensowną pracą.
W tym scenariuszu problemem nie jest to, że testy jednostkowe nie mają żadnego celu; to, że firma ma nierealne oczekiwania . Ich arbitralny zestaw reguł nie obejmuje wszystkich przypadków, a nieprzestrzeganie reguł jest ślepo uważane za awarię programisty, a nie za regułę (co w moim przypadku jest).
źródło
Jeśli nie naprawisz wszystkich testów jednostkowych, możesz szybko przejść do stanu, w którym nikt nie naprawia zepsutych testów.
Jest niepoprawny, ponieważ testy jednostkowe nie wykazały, że kod jest idealny
Odradzanie tworzenia kodu, który również byłby trudny do przetestowania, jest zniechęcające, co jest dobre z punktu widzenia projektu
Pokrycie kodu może w tym pomóc (choć nie jest to panaceum). Również testy jednostkowe są tylko jednym aspektem testowania - chcesz również testy integracji / akceptacji.
źródło
Aby dodać kilka punktów do i tak dobrych odpowiedzi ...
To pokazuje brak zrozumienia procesu wydania. Niepowodzenie testu może wskazywać na planowaną funkcję w TDD, która nie została jeszcze zaimplementowana; lub może wskazywać na znany problem, dla którego planowana jest poprawka dla przyszłej wersji; lub może to być po prostu coś, co zdaniem kierownictwa nie jest wystarczająco ważne, aby to naprawić, ponieważ klienci raczej tego nie zauważą. Kluczową rzeczą, jaką dzielą te wszystkie osoby, jest to, że kierownictwo dokonało osądu dotyczącego niepowodzenia.
Inne odpowiedzi obejmowały granice testowania.
Nie rozumiem jednak, dlaczego uważasz, że eliminowanie błędów jest wadą. Jeśli nie chcesz dostarczyć kodu, który sprawdziłeś (najlepiej jak potrafisz), robi to, co powinien, dlaczego nawet pracujesz w oprogramowaniu?
Dlaczego musi istnieć plan działania?
Testy jednostkowe początkowo sprawdzają, czy funkcjonalność działa, ale następnie (jako testy regresyjne) sprawdzają, czy nie zostały przypadkowo uszkodzone. Dla wszystkich funkcji z istniejącymi testami jednostkowymi nie ma mapy drogowej . Każda funkcja działa (w granicach testowania). Jeśli ten kod jest gotowy, nie ma mapy drogowej, ponieważ nie trzeba więcej nad nim pracować.
Jako profesjonalni inżynierowie musimy unikać pułapki pozłacania. Hobbyści mogą sobie pozwolić na marnowanie czasu na majsterkowanie przy krawędziach z czymś, co działa. Jako profesjonaliści musimy dostarczyć produkt. Oznacza to, że dostajemy coś działającego, sprawdzamy, czy to działa, i przechodzimy do następnej pracy.
źródło
Nie prawda. dlaczego myślisz, że to niemożliwe? tutaj przykład dla programu, który działa:
W takim przypadku może to nie być test jednostkowy, ale test integracyjny, jeśli jest skomplikowany
prawda, z jakiegoś powodu nazywa się to testem jednostkowym , sprawdza małą jednostkę kodu.
Deweloperzy
będziezniechęcać pisać żadnych testów, jeśli nie rozumieją jego zaletyz natury (chyba że pochodzą z kontroli jakości)źródło
Zdecydowanie nie. Promuje ideę, że twoje testy nie powinny zawieść, nic więcej i nic innego. Zakładanie, że przeprowadzanie testów (nawet wielu z nich) mówi coś o „doskonałym” lub „bez błędów”, jest błędem. Decydowanie o tym, jak płytkie lub głębokie powinny być twoje testy, stanowi znaczącą część pisania dobrych testów i powód, dla którego mamy wyraźnie oddzielne kategorie testów (testy „jednostkowe”, testy integracyjne, „scenariusze” w sensie ogórka itp.).
W programowaniu opartym na testach obowiązkowe jest, aby wszystkie testy jednostkowe zakończyły się niepowodzeniem przed rozpoczęciem kodowania. Z tego właśnie powodu nazywa się to „cyklem czerwono-zielonym” (lub „cyklem refaktora czerwono-zielonego”).
Testy są raczej rodzajem mikro-celu. W programowaniu opartym na testach programista najpierw napisze test (liczba pojedyncza), a następnie będzie miał wyraźny cel zaimplementowania kodu; następnie następny test i tak dalej.
Funkcja testów nie może być kompletna przed napisaniem kodu.
Wykonane poprawnie, w języku i przy użyciu biblioteki testowej, która jest dobrze dostosowana do tego podejścia, może faktycznie znacznie przyspieszyć programowanie, ponieważ komunikaty o błędach (wyjątki / ślady stosu) mogą bezpośrednio wskazywać deweloperowi, gdzie powinien wykonać pracę Kolejny.
Nie rozumiem, jak to stwierdzenie byłoby prawdziwe. Testy pisemne powinny być idealnie częścią wdrożenia.
Ponieważ organizacje oczekują, że testy będą miały znaczenie dla kodu. Pomyślne napisanie testów oznacza, że udokumentowałeś część aplikacji i udowodniłeś, że aplikacja wykonuje to, co mówi (test). Nic więcej i nic mniej.
Ponadto bardzo dużą częścią testów jest „regresja”. Chcesz mieć możliwość opracowywania lub refaktoryzacji nowego kodu z pewnością. Dzięki dużej ilości zielonych testów możesz to zrobić.
Od poziomu organizacyjnego do psychologicznego. Deweloper, który wie, że jego błędy najprawdopodobniej zostaną złapane przez testy, będzie mógł swobodniej wymyślić inteligentne, odważne rozwiązania problemów, które musi rozwiązać. Z drugiej strony programista, który nie ma testów, po pewnym czasie będzie się zatrzymywał (z powodu strachu), ponieważ nigdy nie wie, czy zmiana, którą robi, psuje resztę aplikacji.
Nie. Praca z aplikacją testowaną to czysta radość - chyba że nie podoba ci się ta koncepcja z jakiegokolwiek powodu („większy wysiłek” itp.), Który możemy omówić w innym pytaniu.
Absolutnie nie, dlaczego miałoby to być?
Znajdziesz wiele dużych projektów open source (dla których zarządzanie „zrozumieniem” i know-how na temat kodu jest bardzo palącym tematem), które faktycznie wykorzystują testy jako główną dokumentację oprogramowania, poza tym, że są testami, dostarczają również prawdziwe, działające, poprawne składniowo przykłady dla użytkowników lub programistów aplikacji / biblioteki. To często działa wspaniale.
Oczywiście pisanie złych testów jest złe. Ale to nie ma nic wspólnego z funkcją testów jako takich.
źródło
(Z moich oryginalnych komentarzy)
Istnieje różnica między wymaganą funkcjonalnością a przyszłymi celami. Testy dotyczą wymaganej funkcjonalności: są precyzyjne, formalne, wykonywalne, a jeśli zawiodą, oprogramowanie nie działa. Przyszłe cele mogą nie być precyzyjne ani formalne, nie mówiąc już o wykonywalności, więc lepiej pozostawić je w języku naturalnym, np. W modułach do śledzenia problemów / błędów, dokumentacji, komentarzy itp.
W ramach ćwiczenia spróbuj zastąpić wyrażenie „test jednostkowy” w swoim pytaniu „błędem kompilatora” (lub „błędem składni”, jeśli nie ma kompilatora). Oczywiste jest, że wydanie nie powinno zawierać błędów kompilatora, ponieważ byłoby bezużyteczne; jednak błędy kompilatora i błędy składniowe są normalnym stanem rzeczy na komputerze programisty podczas pisania kodu. Błędy znikają dopiero po ich zakończeniu; i właśnie wtedy kod powinien zostać wypchnięty. Teraz zamień „błąd kompilatora” w tym akapicie na „test jednostkowy” :)
źródło
Celem automatycznych testów jest jak najwcześniejsze poinformowanie cię, kiedy coś zepsułeś . Przepływ pracy wygląda trochę tak:
Jeśli Twoje testy już się nie powiodły, krok 3 nie działa tak skutecznie - testy zakończą się niepowodzeniem, ale nie wiesz, czy to oznacza, że coś zepsułeś, czy nie, bez badania. Może możesz policzyć liczbę nieudanych testów, ale zmiana może naprawić jeden błąd i zepsuć inny, lub test może zakończyć się niepowodzeniem z innego powodu. Oznacza to, że musisz poczekać pewien czas, zanim dowiesz się, czy coś zostało zepsute, albo do momentu rozwiązania wszystkich problemów, albo do zbadania każdego niepowodzenia testu.
Zdolność testów jednostkowych do znalezienia nowo wprowadzonych błędów tak wcześnie, jak to możliwe, jest najcenniejszą rzeczą w automatycznych testach - im dłużej usterka pozostaje nieodkryta, tym droższa jest naprawa.
Testy na rzeczy, które nie działają, nic ci nie mówią - napisz testy jednostkowe na rzeczy, które działają lub które masz zamiar naprawić. Nie oznacza to, że twoje oprogramowanie jest wolne od wad, oznacza to, że żadna z defektów, dla których wcześniej pisałeś testy jednostkowe, nie powróciła.
Jeśli to działa, to napisz testy z góry, po prostu nie sprawdzaj ich w swoim systemie głównym, dopóki nie przejdą pomyślnie.
Testy jednostkowe nie służą do ustalania mapy drogowej / celu, może zamiast tego użyć zaległości? Jeśli wszystkie testy zakończą się pomyślnie, „dużym obrazem” jest to, że oprogramowanie nie jest zepsute (jeśli zasięg testu jest dobry). Dobra robota!
źródło
Istniejące odpowiedzi są z pewnością dobre, ale nie widziałem, aby ktokolwiek zajął się tym fundamentalnym błędnym przekonaniem w pytaniu:
Nie. Z całą pewnością nie będzie to prawdą. Podczas tworzenia oprogramowania NCrunch jest najczęściej brązowy (błąd kompilacji) lub czerwony (test nieudany).
NCrunch musi być zielony (wszystkie testy przechodzą), kiedy jestem gotów wcisnąć zatwierdzenie do serwera kontroli źródła, ponieważ w tym momencie inni mogą polegać na moim kodzie.
To również stanowi wkład do tematu tworzenia nowych testów: testy powinny potwierdzać logikę i zachowanie kodu. Warunki brzegowe, warunki uszkodzenia itp. Pisząc nowe testy, próbuję zidentyfikować te „gorące punkty” w kodzie.
Testy jednostkowe dokumentują, jak mam się nazywać mój kod - warunki wstępne, oczekiwane wyniki itp.
Jeśli test ulegnie awarii po zmianie, muszę zdecydować, czy kod lub test jest w błędzie.
Na marginesie, testowanie jednostkowe czasami idzie w parze z testowaniem opartym na testach. Jedną z zasad TDD jest to, że zepsute testy są drogowskazami. Gdy test się nie powiedzie, musisz naprawić kod, aby test się powiódł. Oto konkretny przykład z początku tego tygodnia:
Tło : Napisałem i teraz obsługuję bibliotekę używaną przez naszych programistów, która służy do sprawdzania poprawności zapytań Oracle. Przeprowadziliśmy testy, które potwierdziły, że zapytanie odpowiada pewnej oczekiwanej wartości, co sprawiło, że wielkość liter była ważna (nie ma go w Oracle) i wesoło zaakceptowano nieprawidłowe zapytania, o ile całkowicie pasowały do oczekiwanej wartości.
Zamiast tego moja biblioteka analizuje zapytanie, używając Antlr i składni Oracle 12c, a następnie opakowuje różne twierdzenia na samym drzewie składni. Rzeczy są poprawne (nie zgłoszono błędów analizy), wszystkie parametry są spełnione przez kolekcję parametrów, wszystkie oczekiwane kolumny odczytane przez czytnik danych są obecne w zapytaniu itp. Wszystkie są elementami, które prześlizgnęły się do produkcja w różnych momentach.
Jeden z moich kolegów inżynierów wysłał mi zapytanie w poniedziałek, które nie powiodło się (a raczej udało się, gdy powinno się nie powieść) w weekend. Moja biblioteka powiedziała, że składnia jest dobra, ale wybuchła, gdy serwer próbował ją uruchomić. A kiedy spojrzał na zapytanie, było oczywiste, dlaczego:
Załadowałem projekt i dodałem test jednostkowy, który stwierdził, że to zapytanie nie powinno być prawidłowe. Oczywiście test się nie powiódł.
Następnie ja debugowany test niepowodzeniem, przeszedł przez kod, gdzie oczekiwano go rzucić wyjątek i zorientowali się, że antlr było podniesienie błąd na otwartych paren, ale nie w taki sposób, poprzedni kod spodziewałem. Zmodyfikowałem kod, zweryfikowałem, że test był teraz zielony (pozytywny) i że nikt inny nie złamał się w tym procesie, nie zatwierdził i nie wypchnął.
Zajęło to może 20 minut, a proces znacznie poprawiłem bibliotekę, ponieważ teraz obsługiwał cały zakres błędów, które wcześniej ignorował. Gdybym nie miał testów jednostkowych dla biblioteki, badanie i rozwiązanie problemu zajęłoby wiele godzin.
źródło
Jedna kwestia, która nie wydaje mi się wynikać z poprzednich odpowiedzi, polega na tym, że istnieje różnica między testami wewnętrznymi a testami zewnętrznymi (i myślę, że wiele projektów nie jest wystarczająco ostrożnych, aby je rozróżnić). Test wewnętrzny sprawdza, czy jakiś wewnętrzny element działa tak, jak powinien; zewnętrzny test pokazuje, że system jako całość działa tak, jak powinien. Oczywiście jest całkiem możliwe, że wystąpią awarie komponentów, które nie spowodują awarii systemu (być może istnieje funkcja komponentu, z której system nie korzysta, lub może system odzyskuje system po awarii składnik). Awaria komponentu, która nie skutkuje awarią systemu, nie powinna powstrzymywać Cię przed zwolnieniem.
Widziałem projekty sparaliżowane przez zbyt wiele testów komponentów wewnętrznych. Za każdym razem, gdy próbujesz wdrożyć ulepszenie wydajności, przerywasz dziesiątki testów, ponieważ zmieniasz zachowanie komponentów bez faktycznej zmiany widocznego z zewnątrz zachowania systemu. Prowadzi to do braku zwinności w całym projekcie. Uważam, że inwestycja w zewnętrzne testy systemu generalnie przynosi znacznie lepszą wypłatę niż inwestycja w wewnętrzne testy komponentów, szczególnie gdy mówimy o komponentach bardzo niskiego poziomu.
Kiedy sugerujesz, że nieudane testy jednostkowe tak naprawdę nie mają znaczenia, zastanawiam się, czy o to ci chodzi? Być może powinieneś oceniać wartość testów jednostkowych i porzucać te, które powodują więcej problemów niż są warte, jednocześnie koncentrując się bardziej na testach, które weryfikują widoczne z zewnątrz zachowanie aplikacji.
źródło
„ale w dowolnym momencie wszystkie testy jednostkowe muszą przejść pomyślnie”
Jeśli taka jest postawa w Twojej firmie, to jest problem. W PEWNYM czasie, kiedy deklarujemy, że kod jest gotowy do przejścia do następnego środowiska, wszystkie testy jednostkowe powinny przejść pomyślnie. Ale podczas opracowywania powinniśmy rutynowo oczekiwać, że wiele testów jednostkowych zakończy się niepowodzeniem.
Żadna rozsądna osoba nie oczekuje od programisty doskonałej pracy za pierwszym razem. Racjonalnie oczekujemy, że będzie nad tym pracował, dopóki nie będą znane żadne problemy.
„Odradzanie wymyślania testów jednostkowych, które zakończą się niepowodzeniem, jest zniechęcające. A na pewno wymyślenie testów jednostkowych, które trudno byłoby naprawić”. Jeśli ktoś w Twojej organizacji myśli, że nie powinien wspominać o możliwym teście, ponieważ może się on nie powieść i spowodować, że będzie musiał więcej pracy, aby go naprawić, osoba ta jest całkowicie niewykwalifikowana do swojej pracy. To katastrofalne podejście. Czy chciałbyś, żeby lekarz powiedział: „Kiedy robię operację, celowo nie sprawdzam, czy szwy są prawidłowe, ponieważ jeśli zobaczę, że nie są, będę musiał wrócić i wykonać je ponownie, i to zwolni zakończenie operacji ”?
Jeśli zespół jest wrogo nastawiony do programistów, którzy identyfikują błędy, zanim kod trafi do produkcji, masz poważny problem z postawą tego zespołu. Jeśli kierownictwo karze programistów, którzy identyfikują błędy spowalniające dostawę, istnieje prawdopodobieństwo, że Twoja firma zmierza w kierunku bankructwa.
Tak, to z pewnością prawda, że czasami racjonalni ludzie mówią: „Zbliżamy się do terminu, to jest trywialny problem i nie warto poświęcać zasobów w tej chwili, aby to naprawić”. Ale nie możesz podjąć racjonalnej decyzji, jeśli nie wiesz. Chłodne sprawdzanie listy błędów i przypisywanie priorytetów i harmonogramów do ich naprawy jest racjonalne. Uświadomienie sobie, że nie jesteś świadomy problemów, abyś nie musiał podejmować tej decyzji, jest głupie. Czy uważasz, że klient nie dowie się tylko dlatego, że nie chcesz wiedzieć?
źródło
Jest to konkretny przykład uprzedzenia potwierdzającego , w którym ludzie szukają informacji, które potwierdzają ich istniejące przekonania.
Jednym ze znanych przykładów tego zjawiska jest gra 2,4,6.
Większość ludzi wybiera regułę, mówiąc: „różnica między 1. a 2. numerem jest taka sama jak różnica między 2. a 3.”.
Przetestują niektóre liczby:
Mówią: „Tak, każda obserwacja potwierdza moją hipotezę, to musi być prawda”. I ogłosić swoją zasadę osobie, która rozwiązuje zagadkę.
Ale nigdy nie otrzymali ani jednego „niepowodzenia” żadnego zestawu trzech liczb. Zasadą może być po prostu „trzy liczby muszą być liczbami” dla wszystkich faktycznie posiadanych informacji.
Zasadą jest po prostu, że liczby są w porządku rosnącym. Ludzie zwykle rozwiązują tę zagadkę tylko wtedy, gdy testują na niepowodzenie. Większość ludzi myli się, wybierając bardziej szczegółową regułę i testując tylko liczby spełniające tę konkretną regułę.
Co do tego, dlaczego ludzie zakochują się w uprzedzeniach potwierdzających i mogą widzieć, że testy jednostkowe zawodzą jako dowód na problem, jest wielu psychologów, którzy mogą wyjaśnić uprzedzenia potwierdzające lepiej niż ja, w zasadzie sprowadza się to do osób, które nie lubią się mylić i próbują autentycznie próbować udowodnić, że się mylą.
źródło