Zadaję to pytanie dotyczące problemów, których doświadczyłem podczas projektów TDD. Podczas tworzenia testów jednostkowych zauważyłem następujące wyzwania.
- Generowanie i utrzymywanie fałszywych danych
Utrzymywanie dużych fałszywych danych jest trudne i nierealne. Jeszcze trudniej jest, gdy struktura bazy danych ulega zmianom.
- Testowanie GUI
Nawet przy MVVM i możliwości testowania GUI, do odtworzenia scenariusza GUI potrzeba dużo kodu.
- Testowanie biznesu
Mam doświadczenie, że TDD działa dobrze, jeśli ograniczysz go do prostej logiki biznesowej. Jednak skomplikowana logika biznesowa jest trudna do przetestowania, ponieważ liczba kombinacji testów (przestrzeń testowa) jest bardzo duża.
- Sprzeczność wymagań
W rzeczywistości trudno jest uchwycić wszystkie analizowane wymagania i projekt. Wielokrotnie wymagania jednej nuty prowadzą do sprzeczności, ponieważ projekt jest złożony. Sprzeczność znajduje się późno w fazie wdrażania. TDD wymaga, aby wymagania były w 100% poprawne. W takich przypadkach można oczekiwać, że podczas tworzenia testów zostaną wychwycone sprzeczne wymagania. Problem polega jednak na tym, że nie dotyczy to złożonych scenariuszy.
Przeczytałem to pytanie: Dlaczego działa TDD?
Czy TDD naprawdę działa w przypadku złożonych projektów korporacyjnych, czy praktycznie ogranicza się do typu projektu?
Odpowiedzi:
Fałszywe.
Testy jednostkowe nie wymagają „dużych” próbnych danych. Wymaga wystarczającej ilości próbnych danych do przetestowania scenariuszy i nic więcej.
Ponadto prawdziwie leniwi programiści proszą ekspertów tematycznych o tworzenie prostych arkuszy kalkulacyjnych różnych przypadków testowych. Tylko prosty arkusz kalkulacyjny.
Następnie leniwy programista pisze prosty skrypt do przekształcania wierszy arkusza kalkulacyjnego w jednostkowe przypadki testowe. To naprawdę bardzo proste.
Gdy produkt ewoluuje, arkusze kalkulacyjne przypadków testowych są aktualizowane i generowane są nowe testy jednostkowe. Rób to cały czas. To naprawdę działa.
Co? "Rozmnażać się"?
Celem TDD jest projektowanie rzeczy pod kątem testowalności (Test Drive Development). Jeśli GUI jest tak złożony, należy go przeprojektować, aby był prostszy i bardziej testowalny. Prostsze oznacza również szybsze, łatwiejsze w utrzymaniu i bardziej elastyczne. Ale w większości prostsze będą oznaczały więcej do przetestowania.
To może być prawda.
Jednak bardzo pomocne jest poproszenie ekspertów tematu o dostarczenie podstawowych przypadków testowych w prostej formie (np. Arkusza kalkulacyjnego).
Arkusze kalkulacyjne mogą stać się dość duże. Ale to w porządku, ponieważ użyłem prostego skryptu Python, aby zamienić arkusze kalkulacyjne w przypadki testowe.
I. Musiałem ręcznie napisać kilka przypadków testowych, ponieważ arkusze kalkulacyjne były niekompletne.
Jednak. Gdy użytkownicy zgłosili „błędy”, po prostu zapytałem, który przypadek testowy w arkuszu kalkulacyjnym jest nieprawidłowy.
W tym momencie eksperci merytoryczni albo poprawią arkusz kalkulacyjny, albo dodadzą przykłady wyjaśniające, co miało się wydarzyć. Zgłoszenia błędów mogą - w wielu przypadkach - być jasno zdefiniowane jako problem przypadku testowego. Z mojego doświadczenia wynika, że zdefiniowanie błędu jako zepsutego przypadku testowego znacznie ułatwia dyskusję.
Zamiast słuchać ekspertów próbujących wyjaśnić bardzo złożony proces biznesowy, eksperci muszą przedstawić konkretne przykłady tego procesu.
Nieużywanie TDD absolutnie wymaga, aby wymagania były w 100% poprawne. Niektórzy twierdzą, że TDD może tolerować niekompletne i zmieniające się wymagania, przy czym podejście inne niż TDD nie może działać z niekompletnymi wymaganiami.
Jeśli nie użyjesz TDD, sprzeczność zostanie wykryta późno w fazie wdrażania.
Jeśli używasz TDD, sprzeczność jest wykrywana wcześniej, gdy kod przechodzi niektóre testy, a inne nie. Rzeczywiście, TDD daje dowód na sprzeczność na wcześniejszym etapie procesu, na długo przed implementacją (oraz argumenty podczas testowania akceptacji użytkownika).
Masz kod, który przechodzi niektóre testy, a inne nie. Patrzysz tylko na te testy i znajdujesz sprzeczność. Działa to naprawdę bardzo dobrze w praktyce, ponieważ teraz użytkownicy muszą kłócić się o sprzeczność i przedstawiać spójne, konkretne przykłady pożądanego zachowania.
źródło
tak
Moja pierwsza ekspozycja na TDD dotyczyła komponentów oprogramowania pośredniego dla telefonu komórkowego z systemem Linux. Ostatecznie powstały miliony linii kodu źródłowego, co z kolei wywołało około 9 gigabajtów kodu źródłowego dla różnych komponentów open source.
Wszyscy autorzy komponentów mieli zaproponować zarówno interfejs API, jak i zestaw testów jednostkowych oraz poddać je weryfikacji projektu przez komisję. Nikt nie oczekiwał perfekcji w testowaniu, ale wszystkie publicznie dostępne funkcje musiały mieć co najmniej jeden test, a po poddaniu komponentu kontroli źródła wszystkie testy jednostkowe musiały zawsze przejść pomyślnie (nawet jeśli zrobiły to, ponieważ komponent fałszywie raportował działało dobrze).
Bez wątpienia, przynajmniej po części z powodu TDD i nacisku, że wszystkie testy jednostkowe zawsze kończą się sukcesem, wydanie 1.0 pojawiło się wcześnie, poniżej budżetu i ze zdumiewającą stabilnością.
Po wydaniu wersji 1.0, ponieważ firma chciała móc szybko zmienić zakres ze względu na wymagania klientów, powiedzieli nam, abyśmy przestali robić TDD i usunęli wymóg, aby testy jednostkowe przebiegły pomyślnie. Zadziwiające było to, jak szybko jakość spadła w toalecie, a potem nastąpił harmonogram.
źródło
removed the requirement that unit tests pass. It was astonishing how quickly quality went down the toilet, and then the schedule followed it.
- to tak, jakby powiedzieć kierowcy F1, że nie wolno mu robić postojów, ponieważ zajmuje to zbyt dużo czasu ... Idiotyzm.Twierdziłbym, że im bardziej złożony projekt, tym więcej korzyści czerpiesz z TDD. Główne korzyści to skutki uboczne tego, w jaki sposób TDD zmusi cię do napisania kodu w znacznie mniejszych, znacznie bardziej niezależnych częściach. Kluczowe korzyści to:
a) Otrzymujesz dużo, znacznie wcześniejszą weryfikację projektu, ponieważ twoja pętla sprzężenia zwrotnego jest znacznie ściślejsza z powodu testów od samego początku.
b) Możesz zmieniać bity i kawałki i zobaczyć, jak reaguje system, ponieważ cały czas budujesz kołdrę pokrycia testowego.
c) W rezultacie gotowy kod będzie znacznie lepszy.
źródło
Czy TDD naprawdę działa w przypadku złożonych projektów?
Tak. Nie każdy projekt, więc powiedziano mi, że działa dobrze z TDD, ale większość aplikacji biznesowych jest w porządku, i założę się, że te, które nie działają dobrze, gdy są napisane w czysty sposób TDD, mogą być napisane w sposób ATDD bez większych problemów.
Generowanie i utrzymywanie fałszywych danych
Zachowaj mały rozmiar i miej tylko to, czego potrzebujesz, i nie jest to przerażający problem. Nie zrozum mnie źle, to ból. Ale warto.
Testowanie GUI
Przetestuj MVVM i upewnij się, że można go przetestować bez widoku. Nie było to dla mnie trudniejsze niż przetestowanie jakiejkolwiek innej logiki biznesowej. Testowanie widoku w kodzie, którego nie robię, wszystko, co testujesz, to jednak logika wiązania, która, jak można się spodziewać, zostanie szybko złapana, gdy wykonasz szybki test ręczny.
Testowanie firmy
Nie stwierdzono problemu. Wiele małych testów. Jak wspomniałem powyżej, niektóre przypadki (sudoku wydają się być popularne) są najwyraźniej trudne do zrobienia TDD.
TDD wymaga, aby wymagania były w 100% poprawne
Nie, nie robi tego. Skąd wziął się ten pomysł? Wszystkie zwinne praktyki akceptują zmianę wymagań. Musisz wiedzieć, co robisz, zanim to zrobisz, ale to nie to samo, co wymaganie 100% wymagań. TDD jest powszechną praktyką w Scrumie, gdzie wymagania (historie użytkowników) z samej definicji nie są w 100% kompletne.
źródło
Po pierwsze, uważam, że twój problem dotyczy bardziej testów jednostkowych niż TDD, ponieważ nie widzę nic tak naprawdę specyficznego dla TDD (cykl testowy + cykl refaktoryzacji czerwony-zielony) w tym, co mówisz.
Co rozumiesz przez fałszywe dane? Makieta ma dokładnie zawierać prawie żadne dane, tj. Nie ma pól innych niż jedno lub dwa potrzebne w teście i żadnych zależności innych niż testowany system. Konfigurowanie fałszywej wartości oczekiwanej lub zwracanej można wykonać w jednym wierszu, więc nic strasznego.
Jeśli masz na myśli, że baza danych podlega zmianom bez dokonania odpowiednich modyfikacji w modelu obiektowym, dobrze są tutaj testy jednostkowe, aby cię o tym ostrzec. W przeciwnym razie zmiany w modelu muszą oczywiście znaleźć odzwierciedlenie w testach jednostkowych, ale przy wskazaniach kompilacji jest to łatwe.
Masz rację, testowanie interfejsu GUI (Widok) nie jest łatwe, a wiele osób radzi sobie bez niego dobrze (poza tym testowanie GUI nie jest częścią TDD). Natomiast wysoce zalecane jest testowanie jednostkowe kontrolera / prezentera / ViewModel / dowolnej warstwy pośredniej, w rzeczywistości jest to jeden z głównych powodów, dla których wzorce takie jak MVC lub MVVM są.
Jeśli logika biznesowa jest złożona, trudno jest zaprojektować testy jednostkowe. Twoim zadaniem jest uczynić je tak atomowymi, jak to możliwe, każdy testując tylko jedną odpowiedzialność za testowany obiekt. Testy jednostkowe są tym bardziej potrzebne w złożonym środowisku, ponieważ zapewniają siatkę bezpieczeństwa gwarantującą, że nie złamiesz reguł biznesowych ani wymagań podczas wprowadzania zmian w kodzie.
Absolutnie nie. Udane oprogramowanie wymaga, aby wymagania były w 100% poprawne;) Testy jednostkowe odzwierciedlają tylko Twoją wizję wymagań; jeśli wizja jest wadliwa, twój kod i oprogramowanie też będą, testy jednostkowe czy nie ... I to właśnie tam świecą testy jednostkowe: z wystarczająco wyraźnymi tytułami testów, decyzje projektowe i interpretacja wymagań stają się przejrzyste, co ułatwia wskazanie palcem na to, co należy zmienić następnym razem, gdy klient mówi „ta zasada biznesowa nie jest taka, jak bym chciał”.
źródło
Muszę się śmiać, gdy słyszę, jak ktoś narzeka, że nie może używać TDD do testowania swojej aplikacji, ponieważ jej aplikacja jest tak skomplikowana. Jaka jest alternatywa? Czy małpy testowe walą w akry klawiatur? Czy użytkownicy mogą być testerami? Co jeszcze? Oczywiście jest to trudne i złożone. Czy uważasz, że Intel nie testuje swoich układów, dopóki nie zostaną wysłane? Jak to jest „head-in-the-sand”?
źródło
Odkryłem, że TDD (i ogólnie testy jednostkowe) są praktycznie niemożliwe z pokrewnego powodu: złożonych, nowatorskich i / lub rozmytych algorytmów. Problem, który napotkałem najbardziej w prototypach badawczych, które piszę, polega na tym, że nie mam pojęcia, jaka jest prawidłowa odpowiedź poza uruchomieniem mojego kodu. Jest to zbyt skomplikowane, aby racjonalnie rozgryźć ręcznie, z wyjątkiem absurdalnie trywialnych przypadków. Jest to szczególnie prawdziwe, jeśli algorytm obejmuje heurystykę, aproksymacje lub niedeterminizm. Nadal próbuję przetestować funkcjonalność niższego poziomu, od której ten kod zależy, i używam bardzo mocno do sprawdzania poprawności. Moją ostatnią metodą testowania jest napisanie dwóch różnych implementacji, najlepiej w dwóch różnych językach przy użyciu dwóch różnych zestawów bibliotek i porównanie wyników.
źródło
Z mojego doświadczenia: Tak dla Unittests (test modułów / funkcji w izolacji), ponieważ w większości nie mają problemów, o których wspominasz: (Gui, Mvvm, Business-Modell). Nigdy nie miałem więcej niż 3 makiety / kody pośredniczące, aby wypełnić jeden najbardziej nieprzystosowany (ale może twoja domena wymaga więcej).
Nie jestem jednak pewien, czy TDD może rozwiązać problemy, o których wspomniałeś podczas testów integracji lub testów end-to-end z testami typu BDD.
Ale przynajmniej niektóre problemy można zmniejszyć .
Dzieje się tak, jeśli chcesz wykonać pełne pokrycie na poziomie testu integracyjnego lub testu kompleksowego. Pełniejsze pokrycie może być łatwiejsze na najtrudniejszym poziomie.
Przykład: sprawdzanie złożonych uprawnień użytkownika
Testowanie funkcji
IsAllowedToEditCusterData()
na poziomie testu integracji wymagałoby zapytania różnych obiektów o informacje o użytkowniku, domenie, kliencie, środowisku ....Wyśmiewanie tych części jest dość trudne. Jest to szczególnie prawdziwe, jeśli
IsAllowedToEditCusterData()
trzeba znać te różne przedmioty.Na poziomie Unittest miałbyś funkcję,
IsAllowedToEditCusterData()
która bierze na przykład 20 parametrów, które zawierają wszystko, co funkcja musi wiedzieć. PonieważIsAllowedToEditCusterData()
nie trzeba wiedzieć, jakie pola auser
, adomain
, acustomer
... ma to łatwo przetestować.Kiedy musiałem wdrożyć,
IsAllowedToEditCusterData()
miałem dwa przeciążenia:Jedno przeciążenie, które nie robi nic więcej niż uzyskanie tych 20 parametrów, a następnie wywołanie przeciążenia z 20 parametrami, które podejmują decyzję.
(mój
IsAllowedToEditCusterData()
miał tylko 5 parametrów i potrzebowałem 32 różnych kombinacji, aby go całkowicie przetestować)Przykład
źródło
Smutna odpowiedź jest taka, że nic tak naprawdę nie działa w przypadku dużych, złożonych projektów!
TDD jest tak dobry jak wszystko inne i lepszy niż większość, ale sam TDD nie gwarantuje sukcesu w dużym projekcie. To jednak zwiększy twoje szanse na sukces. Zwłaszcza w połączeniu z innymi dyscyplinami zarządzania projektami (weryfikacja wymagań, przypadki użycia, macierz podatności na wymagania, instrukcje dotyczące kodu itp.).
źródło
Pamiętaj, że testy jednostkowe są wymuszonymi specyfikacjami . Jest to szczególnie cenne w złożonych projektach. Jeśli twoja stara baza kodu nie ma żadnych testów do jej wykonania, nikt nie odważy się niczego zmienić, ponieważ będą się bali zepsuć.
„Wtf. Dlaczego ta gałąź kodu nawet tam jest? Nie wiem, może ktoś jej potrzebuje, lepiej zostaw ją tam, aby kogoś nie denerwować ...” Z czasem złożone projekty stają się śmieciami.
Dzięki testom każdy może śmiało powiedzieć: „Dokonałem drastycznych zmian, ale wszystkie testy wciąż przechodzą”. Z definicji niczego nie złamał. Prowadzi to do bardziej zwinnych projektów, które mogą ewoluować. Być może jednym z powodów, dla których nadal potrzebujemy ludzi do utrzymania COBOL, jest to, że testy nie były popularne od tego czasu: P.
źródło
Widziałem, jak duży złożony projekt kompletnie się nie udaje, gdy używa się wyłącznie TDD, tj. Bez co najmniej konfiguracji w debuggerze / IDE. Próbne dane i / lub testy okazały się niewystarczające. Rzeczywiste dane klientów Beta były wrażliwe i nie można ich było kopiować ani rejestrować. Zespół programistów nigdy nie był w stanie naprawić fatalnych błędów, które pojawiały się, gdy wskazywano na rzeczywiste dane, a cały projekt został złomowany, wszyscy zwolnieni przez cały czas.
Rozwiązaniem tego problemu byłoby uruchomienie go w debugerze na stronie klienta, sprawdzenie rzeczywistych danych, przejście przez kod, z punktami przerwania, zmiennymi oglądania, pamięcią pamięci itp. Jednak ten zespół którzy uważali, że ich kod nadaje się do ozdabiania najlepszych wież z kości słoniowej, przez prawie rok nigdy nie uruchomili swojej aplikacji. To zadziwiło mnie.
Tak jak wszystko, równowaga jest kluczem. TDD może być dobry, ale nie polegaj wyłącznie na nim.
źródło
Myślę, że tak, zobacz Test Driven Development naprawdę działa
źródło
Jeśli połączenie budżetu, wymagań i umiejętności zespołu znajduje się w ćwiartce przestrzeni projektu, to jest „porzućcie nadzieję, że wszyscy, którzy tu wejdziecie”, to z definicji jest bardzo prawdopodobne, że projekt się nie powiedzie.
Być może wymagania są złożone i niestabilne, infrastruktura niestabilna, zespół młodszy i o wysokich obrotach, a architekt jest idiotą.
W projekcie TDD objawem zbliżającej się awarii jest to, że testy nie mogą być napisane zgodnie z harmonogramem; spróbować, tylko odkryć „że zajmie to długo, a my mamy tylko to ”.
Inne podejścia wykażą różne objawy, gdy zawiodą; najczęściej dostawa systemu, który nie działa. Polityka i umowy określą, czy jest to lepsze.
źródło
TDD
może to zabrzmieć z góry jak ból, ale na dłuższą metę będzie to twój najlepszy przyjaciel, zaufaj mi,TDD
że naprawdę sprawi, że aplikacja będzie łatwa w utrzymaniu i bezpieczna na dłuższą metę.źródło