Czy potrzebujemy logowania podczas wykonywania TDD?

40

Wykonując cykl Czerwony, Zielony i Refaktor, zawsze powinniśmy napisać minimalny kod, aby przejść test. W ten sposób nauczono mnie TDD i sposób, w jaki prawie wszystkie książki opisują ten proces.

Ale co z rejestrowaniem?

Szczerze mówiąc rzadko używałem logowania do aplikacji, chyba że działo się coś naprawdę skomplikowanego, jednak widziałem wiele postów mówiących o tym, jak ważne jest prawidłowe logowanie.
Tak więc oprócz zalogowania wyjątku nie mogłem uzasadnić prawdziwego znaczenia zalogowania w odpowiednio przetestowanej aplikacji (testy jednostkowe / integracyjne / akceptacyjne).

Więc moje pytania to:

  1. Czy musimy się zalogować, jeśli wykonujemy TDD? czy test nie powiedzie się, co złego w aplikacji?
  2. Czy powinniśmy dodać test dla procesu logowania w każdej metodzie w każdej klasie?
  3. Jeśli na przykład niektóre poziomy dzienników są wyłączone w środowisku produkcyjnym, czy nie spowoduje to zależności między testami a środowiskiem?
  4. Ludzie mówią o tym, jak logi ułatwiają debugowanie, ale jedną z głównych zalet TDD jest to, że zawsze wiem, co jest nie tak z powodu niepowodzenia testu.

Czy coś tam mi brakuje?

Songo
źródło
5
Myślę, że rejestrowanie jest szczególnym przypadkiem wielu reguł. Klasa / funkcja powinna robić jedną rzecz i jedną rzecz ... oprócz logowania. Funkcje powinny być raczej czyste, z wyjątkiem logowania. Itd. itp. Rejestrowanie łamie zasady.
Phoshi
1
Czy logowanie nie jest głównie ortogonalne w stosunku do jakiejkolwiek metodologii programowania SW? Być może powinieneś to zawęzić i zapytać: Czy potrzebujemy przypadków testowych do logowania podczas wykonywania TDD?
hyde

Odpowiedzi:

50

1) Czy musimy się zalogować, jeśli wykonujemy TDD? czy test nie powiedzie się, co złego w aplikacji?

Zakłada się, że masz wszystkie możliwe testy, których potrzebuje Twoja aplikacja, co rzadko jest prawdą. Dzienniki pomagają wyśledzić błędy, dla których jeszcze nie napisałeś testów.

2) Czy powinniśmy dodać test dla procesu rejestrowania w każdej metodzie w każdej klasie?

Jeśli sam rejestrator zostanie przetestowany, nie będzie musiał być ponownie testowany w każdej klasie, podobnie jak inne zależności.

3) Jeśli na przykład niektóre poziomy dziennika są wyłączone w środowisku produkcyjnym, czy nie spowoduje to zależności między testami a środowiskiem?

Ludzie (i agregatory dzienników) zależą od dzienników, testy nie powinny od nich zależeć. Zazwyczaj istnieje kilka poziomów dziennika, a niektóre z nich są używane w produkcji, a niektóre dodatkowe poziomy są używane w programowaniu, podobnie jak:

„Poziom dziennika Rails to informacje w trybie produkcyjnym, a debugowanie w fazie rozwoju i testowania” - http://guides.rubyonrails.org/debugging_rails_applications.html

Inne aplikacje stosują podobne podejście.

4) Ludzie mówią o tym, jak logi ułatwiają debugowanie, ale jedną z głównych zalet TDD jest to, że zawsze wiem, co jest nie tak z powodu niepowodzenia testu.

Błędy produkcyjne przejdą wszystkie testy, więc możesz potrzebować innego odniesienia do zbadania tych problemów.

FMJaguar
źródło
26
Nawet idealnie rygorystycznie wykonane TDD nie zapobiegnie problemom produkcyjnym z wydajnością, interakcją systemu, interakcją stron trzecich. Kwestie współbieżności są również bardzo trudne do pełnego pokrycia testem. 100% pokrycia testowego „tylko” oznacza, że ​​100% kodu zostało wykonane, co nie jest poprawne we wszystkich stanach lub środowiskach.
Holstebroe
34

Rejestrowanie jest przydatne do wyjaśnienia nietypowego zachowania aplikacji:

Dzienniki zdarzeń rejestrują zdarzenia zachodzące podczas wykonywania systemu w celu zapewnienia ścieżki audytu, którą można wykorzystać do zrozumienia działania systemu i diagnozowania problemów. Są one niezbędne do zrozumienia działania złożonych systemów, szczególnie w przypadku aplikacji o niewielkiej interakcji użytkownika (takich jak aplikacje serwerowe ) ...

Bez względu na to, jak aplikacja została przetestowana i niezależnie od tego, jak dobrze są rejestrowane wyjątki, użytkownicy mogą zapytać,

wyjście twojego programu wynosi 0, podczas gdy spodziewaliśmy się, że będzie to 1, dlaczego tak jest?

Musisz się zalogować, aby sprawdzić, jaka była konfiguracja aplikacji, parametry i inne szczegóły środowiska wykonawczego, aby wyjaśnić jej (nie wyjątkowe) zachowanie.

Z powyższej perspektywy rejestrowanie jest bardziej zorientowane na wsparcie niż na rozwój. Po uruchomieniu aplikacji pożądane jest, aby ktoś inny mógł obsługiwać pytania użytkowników, aby programiści mogli skupić się na dalszym rozwoju.

Rejestrowanie działania aplikacji pozwala komuś innemu zrozumieć zachowanie programu bez konieczności zagłębiania się w kod i bez rozpraszania programistów prośbami o wyjaśnienie, co się dzieje.

komar
źródło
5
+1 za „rejestrowanie jest bardziej zorientowane na wsparcie”. Naprawdę uderzył w gwóźdź.
Tibos
1
+1 za „nietypowe zachowanie”, a także za „rejestrowanie jest bardziej zorientowane na wsparcie”. Ale czy możesz edytować swoją odpowiedź, aby podać źródło cytowanego akapitu?
logc
@ logc źródło cytatu jest odsyłane przez link w pierwszym słowie tutaj, „Logging” - po kliknięciu przejdziesz do artykułu w Wikipedii: en.wikipedia.org/wiki/Logfile
gnat
16

Większość odpowiedzi tutaj koncentruje się na aspekcie poprawności. Rejestrowanie służy jednak również innemu celowi: rejestrowanie może być sposobem na zebranie odpowiednich danych dotyczących wydajności. Nawet jeśli system działa bezbłędnie, dziennik może stwierdzić, dlaczego jest wolny. Nawet przy pełnym pokryciu wszystkich aspektów zestaw testów nie powie.

Oczywiście system o kluczowym znaczeniu dla wydajności może / powinien zapewniać kluczowe wskaźniki wydajności dla niektórych operacyjnych paneli kontrolnych, ale „klasyczne” rejestrowanie może zapewnić inny poziom szczegółowości.

Johnnes
źródło
2
Nie zapomnij także o logowaniu do celów dziennika kontroli. Lub fakturowanie. Lub różnego rodzaju statystyki. Lub rejestrowanie zdarzeń w celu dopasowania do innych rodzajów statystyk innych systemów.
PlasmaHH
Czy profilowanie nie jest czymś, co zrobiłbyś bez logowania? A może masz na myśli, że możesz stale rejestrować wyniki profilowania?
Bergi
@Bergi: całkowicie zależy od tego, jak działa Twoja aplikacja. Jeśli jest to np. Aplikacja internetowa, rejestrowanie czasu obsługi każdego żądania, a następnie próba klastrowania tych zdarzeń dla „złych wykonawców” może również działać.
PlasmaHH
@Bergi profilowanie ma miejsce podczas opracowywania, ale należy pamiętać o działających systemach, że używanie dysków może być spowolnione, procesor może być bardziej obciążony, usługi mogą nie reagować na czas, równoległe wątki mogą powodować problemy z blokowaniem ...
johannes
Audyt @PlasmaHH jest częścią podstawowych wymagań i musi być objęty testami. W większości przypadków nie uruchamiam go na „normalnych” trasach logowania. Normalne rejestrowanie może się nie powieść, a inspekcja nie. „różne statystyki” zebrałem w trakcie występu;)
Johannes
8

Krótka odpowiedź na twoje główne pytanie brzmi: co do zasady, błędy w twoim kodzie NIE będą ujawniane przez TDD. Niektórzy mogą, najlepiej wielu, ale brak nieudanych testów nie oznacza braku błędów. Jest to bardzo ważna maksyma w testowaniu oprogramowania.

Ponieważ nie możesz wiedzieć, czy będziesz mieć nieprawidłowe zachowanie w systemie, być może w rzadkich przypadkach, rejestrowanie jest przydatnym narzędziem, które może pomóc zrozumieć, co jest nie tak, gdy coś nieuchronnie pójdzie nie tak.

Rejestrowanie i TDD rozwiązują różne problemy.

Andres F.
źródło
7
  1. Jeśli nie masz 100% pokrycia testowego, co zwykle nie jest prawdą, nie możesz wiedzieć, że twoje oprogramowanie nigdy się nie zawiesi (EDYCJA: i - jak powiedziano w komentarzach - nawet jeśli tak, coś niezależnego od twojego oprogramowania może spowodować awaria); to tak samo, jak myślenie, że możesz zrobić oprogramowanie, które absolutnie nie ma błędów (nawet NASA nie może tego zrobić). Przynajmniej musisz zarejestrować ewentualne awarie na wypadek awarii programu, abyś wiedział, dlaczego.

  2. Rejestrowanie powinno być wykonywane przez zewnętrzną bibliotekę lub staż wewnętrzny, w zależności od używanej technologii. Rozumiem przez to, że powinno to być coś, co już zostało przetestowane i że nie musisz sam się testować. Przesadą jest testowanie, że każda metoda rejestruje rzeczy, które powinna.

  3. Dzienniki nie są przeznaczone do testów, nie powinno być żadnej zależności. To powiedziawszy, nie musisz wyłączać rejestrowania dla testów, jeśli wydaje ci się to ograniczeniem, chociaż dzienniki powinny być przechowywane w pliku odpowiadającym środowisku (powinieneś mieć inny plik dla środowiska testowego, programistycznego i produkcyjnego) przynajmniej).

  4. Błąd może być bardzo niejasny i nie zawsze jest oczywiste, co poszło nie tak, gdy jeden test TDD nie powiódł się. Dzienniki powinny być bardziej precyzyjne. Na przykład, jeśli wykonujesz algorytm sortowania, a cały przypadek testowy zawodzi, powinieneś mieć dzienniki dla każdego testu algorytmu, które pomogą ci zlokalizować, gdzie leży problem.

Pierre Arlaud
źródło
3
Nawet jeśli masz 100% zasięgu, czy masz go na każdą możliwą rzecz, jaka może się zdarzyć? Co się stanie, jeśli połączenie sieciowe z bazą danych ulegnie awarii? Czy twoje testy ci to powiedzą?
Zachary K
Nigdy nie możesz wiedzieć, że twoje oprogramowanie nigdy nie zawiedzie NAWET, jeśli masz 100% zasięgu. 100% pokrycia, choć pożądane, daje o wiele mniej informacji o poprawności, niż mogłoby się wydawać.
Andres F.
Tak, ty też masz rację. Chodzi o to, że brak możliwości awarii nie jest wykonalny. Będę edytować.
Pierre Arlaud
1
Edycja jest nadal niepoprawna. Nawet jeśli masz 100% pokrycia testowego, kod może zawierać błąd (nie musisz obwiniać przyczyn zewnętrznych). Testy NIE sugerują działania kodu; jedyną rzeczą, którą sugerują z całą pewnością, jest to, że nie napisałeś testu, który wykrył błąd :) Pokrycie testu jest ważną miarą, ale nie jest bezpośrednio związane z brakiem błędów.
Andres F.
3
Trywialne jest udowodnienie, że „100% pokrycia testowego, które mija! = Brak błędów”. Kontrprzykład: add(x, y) = 2(zawsze zwraca 2). Poniższy test zakończy się pomyślnie i zapewnia pełne pokrycie: assert(2 == add(1,1)). 100% pokrycia testowego dla funkcji buggy :)
Andres F.
5

Tak, w ogólnym przypadku musisz się zalogować.

Rejestrowanie nie polega na debugowaniu. No cóż, OK, część logowania polega czasem na debugowaniu i możesz pominąć tę część, jeśli nie potrzebujesz jej podczas programowania.

Ale ważniejszą częścią rejestrowania jest łatwość konserwacji. Dobrze zaprojektowane logowanie może odpowiedzieć na następujące pytania:

  • Czy aplikacja nadal działa i działa? (Rejestrując bicie serca co 1000 sekund.)
  • Czy wydajność aplikacji zmieniła się w ciągu ostatnich 10 miesięcy? (Poprzez rejestrowanie statystyk wydajności przypadków użycia).
  • Czy obciążenie aplikacją zmieniło się w ciągu ostatnich 10 miesięcy? (Rejestrując liczbę żądań według typów wniosków).
  • Czy którykolwiek z naszych interfejsów zmienił charakterystykę wydajności?
  • Czy nowe wydanie powoduje inną charakterystykę użytkowania w stosunku do niektórych podsystemów?
  • Czy jesteśmy pod atakiem DoS ?
  • Jakie rodzaje błędów się zdarzają?

Wszystko to można osiągnąć, logując się. I tak, powinien być zaplanowany, zaprojektowany i przetestowany, najlepiej automatyczny.

Rejestrowanie to funkcja, która dezaktywuje leczenie, podobnie jak inne funkcje.

Jens Schauder
źródło
4

TL; DR: rejestrowanie i TDD są ortogonalne. Posiadanie jednego z nich nie ma żadnego znaczenia

Czy musimy się zalogować, jeśli wykonujemy TDD? czy test nie powiedzie się, co złego w aplikacji?

Zasadniczo większość logowania, które zaimplementowałem i które widziałem zaimplementowane, służy do rozwiązywania problemów operacyjnych, a nie do debugowania programistycznego (chociaż może to pomóc). Głównymi odbiorcami tego rejestrowania są administratorzy i operatorzy, którzy zarządzają Twoimi serwerami, wspierają ludzi, którzy wysłali do nich logi do analizy, oraz klientów, którzy chcą przejrzeć logi i spróbować dowiedzieć się, co się dzieje.

Te dzienniki służą do rozwiązywania problemów związanych głównie z punktami integracji. Mogą to być usługi sieciowe (baza danych, mydło itp.), Zasoby lokalne (dysk, pamięć itp.), Złe dane (dane wejściowe klienta, złe / uszkodzone źródła danych itp.) Itp. Przechwytywanie wyjątków, rejestrowanie błędów, a nawet rejestrowanie informacji (ustawienia, konfiguracje itp.) mogą pomóc w rozwiązywaniu problemów.

Czy powinniśmy dodać test dla procesu logowania w każdej metodzie w każdej klasie?

Dodaj testowanie tam, gdzie jest to konieczne, aby przetestować rejestrowanie. Jeśli masz połączenia ad hoc w celu wylogowania informacji, należy je przetestować. Chociaż wdrażanie rejestrowania i testowania dzienników przy użyciu programowania zorientowanego na aspekty lub metaprogramowania może zmniejszyć obciążenie związane z testowaniem.

Jeśli na przykład niektóre poziomy dzienników są wyłączone w środowisku produkcyjnym, czy nie spowoduje to zależności między testami a środowiskiem?

Jeśli piszesz swój kod za pomocą IoC i korzystasz z prób, powinieneś być w stanie skutecznie przetestować całe logowanie bez polegania na konkretnej konfiguracji środowiska.

dietbuddha
źródło
3

TDD ogólnie pomaga zmniejszyć błędy w kodowaniu. Pomaga o wiele mniej w przypadku błędów w specyfikacji lub po prostu nieporozumień na temat tego, jak rzeczy działają.

„Och? Możesz dostać wiadomość z danymi, zanim otrzymasz potwierdzenie, że logowanie się powiodło? Nigdy tego nie wiedziałem, no cóż, to sobie z tym nie poradzi!” ... Takie rzeczy. Rejestrowanie jest bardzo przydatne do informowania Cię o tym, co próbowało zrobić oprogramowanie, dzięki czemu możesz wykryć błąd.

JohnB
źródło
2

Z mojego doświadczenia wynika, że ​​do aplikacji dodano wysoki poziom rejestrowania, gdy nie wykonujemy TDD. Następnie poziom niepewności staje się wysoki, dlatego dodajemy rejestrowanie, aby zobaczyć, co się dzieje.

Podczas gdy robiąc TDD (a może test-za każdym razem) dodam znacznie mniej instrukcji dziennika. To z kolei oznacza mniej LOC i może (nie zawsze) wpływać na wydajność.

Ale dodajemy logi wchodzące i wychodzące dla funkcji w sposób półautomatyczny w mojej firmie w większości przypadków, niezależnie od metody programowania. Jak wiem, uznano to za obowiązkowe w analizie problemów produkcyjnych.

Przykładem mogą być metody komponentu bean usługi EJB, które są obecne w interfejsie publicznym. Innym może być przypadek, gdy funkcja wykonuje złożone obliczenia. Bardzo pomocne może być wprowadzenie liczb do metody (na przykład możesz napisać test jednostkowy, aby wrócić do ogólnego tematu pod ręką).

dbalakirev
źródło
czy mógłbyś rozwinąć powody, dla których dodajesz dzienniki wchodzące i wychodzące dla funkcji? dlaczego jest to wymagane w twojej firmie?
komara
tak, absolutnie. mam nadzieję, że teraz jest lepiej.
dbalakirev