Blog

03 kwietnia 2015 Wojciech Zawistowski

Powinien, czy robi? (“it should” czy “it does”)?

Tagi:

Powinien, czy robi? (“it should” czy “it does”)?

Istnieją dwa popularne style formatowania opisów testów: it('should do something') i it('does something'). Którego stylu powinniśmy używać? Czy któryś z nich jest obiektywnie lepszy, czy jest to wyłącznie kwestia gustu?

By łatwiej nam było podjąć decyzję, przyjrzyjmy się obu stylom, should i does, z trzech różnych punktów widzenia:

Formatowanie wyników testu

Porównajmy jak testy tej samej funkcjonalności, zapisane w stylu should oraz does, mogłyby wyglądać wyświetlone w konsoli:

Styl should:

Guest User
should have temporary account
should not have permanent account
should be able to read posts
should not be able to create posts

Styl does:

Guest User
has temporary account
does not have permanent account
can read posts
cannot create posts

Najbardziej widoczną różnicą jest to, że słowo should funkcjonuje jak znacznik listy wypunktowanej, stały separator formujący wymagania w schludny ciąg. Jest to wyłącznie kwestia upodobań. Niektórzy twierdzą, że poprawia to czytelność, sprawiając, że łatwiej “przeskanować” testy wzrokiem. Dla innych (ja wliczam się do tej grupy) jest to po prostu niepotrzebny szum, który nie dokłada żadnej użytecznej informacji – i sprawia, że testy są mniej czytelne.

Drugą, mniej rzucającą się w oczy różnicą, jest to w jaki sposób oba style wpływają na zanegowane wymagania. W stylu should negacja jest ustandaryzowana – test zawsze zaczyna się albo od prefixu should albo should not, przez co od razu widać, czy opisuje on przypadek pozytywny czy negatywny. W stylu does pozytywne i negatywne przypadki mają za każdym razem inne nazwy (np. has i does not have, can i cannot, writes i does not write itp.). Według niektórych osób, testy z ustandaryzowanym stylem negacji są łatwiejsze do zrozumiena. Moja osobista opinia jest taka, że aby w pełni zrozumieć wszystkie implikacje testu i tak trzeba zrozumieć co konkretnie jest negowane, więc ustandaryzowany prefix negacji nie rozwiązuje problemu, sprawia jedynie, że opis staje się dłuższy.

Podsumowując: z punktu widzenia czytelności wyników testu, preferuję wersję does, choć jest to kwestia indywidualnego gustu i nie ma obiektywnych argumentów za ani przeciw któremukolwiek ze styli.

Dokumentacja kontra specyfikacja

Istnieje subtelna, ineresująca różnica pomiędzy stylami should i does. Pierwszy z nich skłania się bardziej ku specyfikacji, podczas gdy drugi ku dokumentacji.

Fraza rozpoczynająca się słowem should (powinien) w naturalny sposób pasuje do nowych wymagań. Brzmi ona dobrze gdy specyfikujemy funkcjonalność, która jeszcze nie istnieje w sytemie: The system should allow an user to view his payment history, The sign up should require a valid email itp.

Z drugiej strony, should niezbyt pasuje do dokumentacji. W instrukcji użytkownika dużo lepiej brzmi sformułowanie An eraser tool cleans the canvas niż An eraser tool should clean the canvas. Użytkownik spodziewa się, że powiesz mu, jak twój system działa, co on faktycznie robi a nie co powinien robić. (An eraser should clean the canvas – “gumka” powinna wyczyścić obszar rysunku; Powinna? Czyli może nie wyczyścić? W jakich okolicznościach?).

To prowadzi nas do interesującego pytania: Jak traktujemy nasze testy? Jako specyfikację, czy jako dokumentację?

Jeżeli stosujesz TDD, piszesz testy najpierw, dla funkcjonalności, która jeszcze nie istnieje. Wydaje się więc naturalne, by traktować je jako specyfikację (frameworki w stylu BDD wręcz jawnie zastępują słowo “test” słowem “spec”). Z drugiej strony, nie kasujesz testów po tym jak napiszesz kod – pozostawiasz je by funkcjonowały jako dokumentacja, by pomóc przyszłemu Tobie i członkom Twojego zespołu przypomnieć sobie, jak system działa.

Która z tych dwóch faz jest ważniejsza? Z jednej strony faza specyfikacji jest kluczowa, ponieważ to właśnie ona kieruje designem systemu. Z drugiej strony, faza dokumentacji jest dużo dłuższa. Piszesz kod tylko raz, a żyć z nim musisz potem nieraz przez lata (wielokrotnie ponownie go czytając, refaktoryzując, wyjaśniając nowym członkom zespołu itd.).

Osobiście, skłaniam się ku stylowi dokumentacji (does). Jak dla mnie, bardziej naturalnie się go czyta podczas fazy utrzymania kodu (która, jak powyżej wspomniałem, trwa znacznie dłużej niż faza tworzenia kodu). Ponadto, z mojego doświadczenia, używanie stylu dokumentacji nie ogranicza mojej zdolności do projektowania kodu poprzez “słuchanie testów” w trakcie fazy specyfikacji.

Celowa niejednoznaczność kontra klarowna intencja

Ostania subtelna różnica pomiędzy stylami should i does leży w odczuwalnym poziomie niejednoznaczności.

Styl does jest bezkompromisowy, z klarowną, zdecydowaną intencją. System robi to i to. Jeżeli nie robi (jeżeli test się “wysypuje”), znaczy to, że system jest zepsuty, że w kodzie istnieje błąd.

Styl should pozostawia więcej miejsca na dyskusję. Jeżeli stwierdzasz “system robi to i to” nie pozostawiasz miejsca na polemikę. Jeżeli stwierdzasz “System powinien robić to i to”, otwierasz się na pytania w stylu “Czy rzeczywiście powinien? Jesteśmy tego pewni?”. (Takie otwarte podejście jest zalecane przez twórcę BDD, Dana Northa, w jego poście wprowadzającym do tej metody).

Styl should wpływa także na to, jak traktujemy testy, które nie “przechodzą”. Jeżeli system jedynie powinien coś robić, zakończony niepowodzeniem test nie musi koniecznie znaczyć, że w kodzie znajduje się błąd. Może on równie dobrze świadczyć o tym, że nasze poprzednie założenie na temat tego, co system powinien robić, jest niepoprawne i że powinniśmy przedyskutować jeszcze raz wymagania. Niektórzy nawet posuwają się aż do stwierdzenia, że nawet w przypadku faktycznego błędu w kodzie, styl does kłamie, ponieważ mówi on, że system coś robi, podczas gdy tak na prawdę w tej chwili tego nie robi – w związku z czym styl should jest bardziej poprawny.

Jeżeli chodzi o określenie intencji, wolę styl should niż does. Styl should jest bardziej uczciwy i lepiej sprawdza się jako inicjator dyskusji, co jest na prawdę ważne, jeśli chcemy być zwinni w stosunku do naszych wymagań.

Którego stylu powinienem w takim razie używać?

Jak widać, jest to głównie kwestia niuansów, a w dużej części wyłącznie indywidualnego gustu. Osobiście, skłaniam się nieco ku stylowi it does. Wprowadza on mniej szumu i lepiej się go czyta, a przy odpowiednim mentalnym nastawieniu nadal mogę być równie otwarty na dyskusję jak w przypadku stylu should. Jednakże nie podchodzę do tego dogmatycznie. Mogę pracować w dowolnym ze styli, jeśli tylko jest on konsekwentnie stosowany w całym projekcie.

Nie będę próbował Cię przekonywać ani do stylu should ani does. Wybierz ten, z którym się lepiej czujesz i który pozwala Ci wygodniej rozumować na temat zachowania systemu. Mam jedynie nadzieję, że powyższa analiza pomoże Ci zdecydować w bardziej świadomy sposób.


Chętnie dowiedziałbym się, co sprawdza się w Twoim przypadku. Który styl opisywania testów wolisz? Podziel się swoim zdaniem w komentarzach poniżej!

Zobacz na blogu

09.09.2022
Marcin Jahn
It’s Not Just HTTP It’s Not Just HTTP

In today’s world of cloud-based solutions, distributed systems, and microservices-based architectures, network communication is a...

23.08.2022
Adam Mrowiec
Konferencja IPC 2022 Berlin Konferencja IPC 2022 Berlin

Pandemia wreszcie się kończy, dlatego w tym roku postanowiliśmy wrócić do naszych wyjazdów na konferencje....