Wpis z mikrobloga

23/100 dni z książką

Trzy prawa TDD

“Możemy zdefiniować trzy następujące prawa:
Nie można zacząć pisać kodu produkcyjnego do momentu napisania niespełnionego testu jednostkowego.
Nie można napisać więcej testów jednostkowych, które są wystarczające do niespełnienia testu, a brak kompilacji jest jednocześnie nieudanym testem.
Nie można pisać większej ilości kodu produkcyjnego, niż wystarczy do spełnienia obecnie niespełnionego testu.”

[Więcej infomacji]


#feaoftruss #czystykod #programowanie #programista15k #webdev #gamedev

Podobało się? To zaplusuj i zapisz się do wołania (link w stopce)

************

[Chcesz być wołany?]
  • 29
@FEAofTruss: przedwczoraj jakoś się zabrałem w końcu i przeczytałem tą książkę całą, ale na moje ona przegina w drugą stronę. Np. postuluje żeby było tylko jedno użycie assert XD Czyli na sprawdzenie obiektu mającego 5 pól, napisz 5 testów. Niektóre rzeczy też już nie przystają, np żeby nie robić konstruktora domyślnego, problem w tym że spring i hibernate bez tego w ogóle nie potraktują tego jako encji itp
@FEAofTruss: powodzenia z podejściem TDD, jak masz naprawić problem związany z przetwarzaniem równoległym (np race condition). Test jednostkowy raczej Ci tego nie złapie, więc trzymając się ściśle TDD nie możesz rozwiązywać takich problemów
@dog_meat: do takich testów to tym bardziej potrzebujesz testów jednostkowych i dodatkowego kodu który pozwoli jakoś orkiestrować wątki żeby wykonywały się dokładnie w tej kolejności która powoduje bug. Ogólnie testowanie współbieżnego kodu to wyższa szkoła jazdy i warto spędzić trochę czasu żeby napisać kod umożliwiający efektywne testowanie go.

Zresztą jak inaczej naprawiać te bugi? Dodawać randomowe sleepy w kodzie aż bug się zamanifestuje, naprawić bug, usunąć sleep i czekać na regresję
@sakfa: w jaki sposób chciałbyś w teście jednostkowym zreprodukować tego typu problemy, skoro są niedeterministyczne? Tzn, jeśli zauważysz że jest taki problem, to wg TDD powinieneś napisać najpierw test, który zawsze będzie czerwony do czasu napisania poprawki. Natomiast przy takich problemach test będzie czasem czerwony, czesne zielony.
@dog_meat: musiałbyś mi podać konkretny przykład to ci powiem jakbym do tego podszedł. W praktyce kod podatny na race condition to spory smród, zamiast go testować najprawdopodobniej starałbym się go najpierw usunąć a potem napisać test do już deterministycznego kodu, pełna zgoda że TDD jest tu raczej bez sensu. Zresztą wcześniej się źle wyraziłem, testowanie współbieżności to raczej poziom wyżej niż testy jednostkowe, to już trochę bliżej testów integracyjnych.

Ale gdybym
@sakfa: właśnie o tym piszę, że TDD się tu nie sprawdzi, skoro sam piszesz, że wywaliłbyś kod, napisał od nowa a później test.

Natomiast odnośnie tego to zdecydowanie się tak nie zrobił. Kod nie powinien mieć żadnych wytrychów na potrzeby testu
Kod nie powinien mieć żadnych wytrychów na potrzeby testu


@dog_meat: nie zgadzam się z tym, brzmi mi jak jakiś dziwny dogmat typu 'nigdy nie należy testować na produkcji'. Jeżeli wytrych ułatwi i uprości test to czemu go nie dodać?

Z dependency injection też nie korzystasz? Przecież cały ten wzorzec to jeden wielki wytrych w kodzie żeby ułatwić testowanie.
@sakfa: DI złoży do oderwania abstrakcji od implementacji. Dzięki temu można w razie czego łatwo zmienić implementację. A że ułatwia to testowanie to tylko przyjemny efekt uboczny
DI złoży do oderwania abstrakcji od implementacji


@dog_meat: no nie, do tego służą po prostu interfejsy. Nie musisz mieć DI żeby oderwać abstrakcje od implementacji:

interface Dao { }
class MysqlDao extends Dao { }

class App {
Dao dao = new MysqlDao();
...
}

Jest oderwana abstrakcja od implementacji? Jest. Mamy DI? Nie.

Ta najbardziej punktowana odpowiedz na SO: https://stackoverflow.com/a/130862 wspomina że największą zaletą DI jest właśnie izolacja klas na
@dog_meat: racja. Nie mówię że DI jest wytrychem na potrzeby testów tylko i wyłącznie. Jest też oczywiście używane do innych rzeczy.

Ale przynajmniej w mojej praktyce widziałem wiele klas majacych tylko 1 implementację i tworzonych tylko w jednym miejscu i i tak były przekazywane jako argument konstruktora tylko i wyłącznie po to żeby przekazać ich inną implementację w teście. Jak to inaczej nazwać jak nie wytrych na potrzeby testów? :)