Wróć do strony głównej
BDD

Behavior-Driven Development – złote, ale czy skromne?

Jeśli mieliście kiedykolwiek styczność z testowaniem aplikacji z pewnością zetknęliście się z podejściem Behavior-Driven Development. Często jednak fundamenty tej metodologii nie są do końca zrozumiałe i bywa ona stosowana niezgodnie z przeznaczeniem.

W tym artykule postaramy sie przedstawić Wam główne założenia BDD mając jednocześnie na uwadze jego wady i zalety oraz postaramy się odpowiedzieć na postawione w tytule pytanie. Innymi słowy, sprawdzimy czy BDD faktycznie jest lekarstwem na wszelkie bolączki związane z testowaniem.

Zacznijmy jednak od samego początku przywołując jakie wyróżniamy poziomy testowania.

  1. Poziomy testów aplikacji
  2. Czym jest Behavior-Driven Development?
  3. Problemy z jest Behavior-Driven Development
    3.1. Dodatkowy nakład pracy
    3.2. Buzzword-Driven Architecture
    3.3. Duże projekty
    3.4. Gherkin
  4. Czym w takim razie jest BDD i jak powinno się to podejście stosować w praktyce?
  5. Gherkin
    5.1. Składnia
  6. Problemy z Gherkinem
    6.1. Single Responsibility Principle
    6.2. Podejście imperatywne
  7. Podsumowanie
  8. Przydatne linki

Poziomy testów aplikacji

Podstawową definicją poziomów testowania jest tzw. V model. Poziom testowania natomiast to razem zorganizowana i zarządzana grupa testów mająca jakąś ściśle wyznaczoną odpowiedzialność w kontekście całej aplikacji oraz systemu.

 

Graficzna reprezentacja V modelu.

Z powyższego modelu wynika, że wyróżniamy co najmniej cztery różne poziomy testowania. Gdzie w tym modelu w takim razie należałoby zastosować Behavior-Driven Development?

Zacznijmy ponownie od samej definicji.

Czym jest Behavior-Driven Development?

Jest to podejście, proces mający na celu zapewnienie wysokiej jakości naszego produktu poprzez definicję konkretnych przypadków testowych opisujących realne zachowania użytkownika końcowego (bądź innego aktora) i ich efekty końcowe.

Podejście to można sprowadzić do 3 podstawowych etapów:

  • Discoveryokreślenie wymagań biznesowych dotyczących nowej funkcjonalności, omówienie szczegółowych zachowań na spotkaniach 3 amigos (o tym później),
  • Formulation – dokumentacja określonych wymagań w postaci konkretnych scenariuszy, które docelowo będą zautomatyzowane,
  • Automation – implementacja przypadków testowych oraz ich automatyzacja.

 

Reprezentacja iteracyjnego modelu BDD [1].

W ogólnym rozrachunku BDD wywodzi się z metodologii Test-Driven Development oraz Domain-Driven Design.

Z pierwszej wymienionej zaczerpnięte zostało podejście do określania przypadków testowych przed lub w trakcie implementacji nowej funkcjonalności, zapewniając tym samym, że produkt będzie spełniał wszystkie wymagania biznesowe.

W praktyce sprowadza się to do organizowania spotkań tzw. 3 amigos, czyli product ownera (reprezentującego biznes), testera oraz dewelopera, na których to szczegółowo omawiana jest nowa funkcjonalność z perspektywy użytkownika produktu. W przypadku nieoczywistego zagadnienia, obecność eksperta domenowego może być wskazana.

Z następnej metodologii natomiast zaczerpnięta została koncepcja ubiquitous language, czyli określenia wspólnego języka zarówno dla biznesu jak i testerów i programistów. Jednocześnie zapewnia on usprawniający proces most komunikacyjny pomiędzy wymienionymi.

Realizowane jest to przy użyciu języka jaki oferuje nam Gherkin, definiującego zestaw słów kluczowych oraz reguł za pomocą których tworzone są testowe scenariusze.

Wydaje się zatem, zgodnie z powszechną opinią, że BDD jest doskonałą metodologią, którą należałoby stosować w każdym projekcie. Spróbujmy zatem zweryfikować powyższą opinię. Na początku skupmy się na wadach tego rozwiązania.

Problemy z Behavior-Driven Development

Dodatkowy nakład pracy

Odpowiednio zdefiniowane scenariusze pokryją nam wszelkie zachowania i funkcjonalności naszej aplikacji, będzie się to wiązać natomiast z dodatkowym, bywa że niewspółmiernie dużym nakładem pracy.

Aby BDD funkcjonowało prawidłowo należy również za każdym razem upewnić się, że konkretna nowa funkcjonalność spełnia wszelkie oczekiwane zachowania, co z kolei wiąże się z dodatkowymi spotkaniami, dedykowanymi dla każdego nowego feature’a.

Buzzword-Driven Architecture

Z racji tego, że świat IT oraz technologie w nim wykorzystywane w dużej mierze napędzane są aktualnie panującą “modą”, często ma miejsce stosowanie BDD niezgodnie z przeznaczeniem, co wynika oczywiście z braku zrozumienia gdzie i jak powinno się je stosować.

Duże projekty

Przy rozległych projektach nakład pracy związany z realizacją wszystkich możliwych przypadków testowych jest znaczący, pojawiają się również trudności podczas implementacji skomplikowanych flow aplikacji, a sama egzekucja wszystkich scenariuszy potrafi trwać nawet kilkanaście godzin.

Gherkin

Pomimo korzyści jakie zapewnia Gherkin, wymusza on na nas pewne znormalizowane flow scenariuszy (m.in. Single Responsibility Principle). Jest to oczywiście jedna z jego kolejnych zalet, istnieją natomiast scenariusze gdzie realizacja przypadku testowego mając na uwadze powyższe, nie jest optymalna (o tym później).

Jak widać w powyższym zestawieniu w ogólnym rozrachunku podejście BDD niekoniecznie może być skromnym rozwiązaniem. Większość z wymienionych minusów wynika natomiast z błędnego rozumienia czym jest BDD. Przeprowadźmy więc ponowną ewaluację naszej pierwotnej definicji.

Czym w takim razie jest BDD i jak powinno się to podejście stosować w praktyce?

Jest to szereg reguł oraz zasad mających na celu wytwarzanie wysokiej jakości produktu poprzez określenie oczekiwanego zachowania danej aplikacji z punktu widzenia biznesu.

Historyjki testowe natomiast opisywane są za pomocą scenariuszy, które zawierają opis oczekiwanego zachowania produktu z punktu widzenia użytkownika systemu.

Mając na uwadze powyższe, BDD nie do końca sprawdza się do realizacji testów systemowych.

Testy systemowe powinny być w dalszym ciągu wykonywane z poziomu kodu (bezpośredni dostęp do aktualnego stanu aplikacji, duża szybkość wykonania), BDD natomiast powinno być aplikowane w przypadku testów akceptacyjnych (User Acceptance Tests), gdzie aktor posiada odpowiednią wiedzę i jest w stanie realizować skomplikowane scenariusze nawet “manualnie”.

Jak już wcześniej wspominaliśmy, konkretne scenariusze definiowane są przy użyciu znormalizowanej składni. Aby zrozumieć mocne i słabe strony tego podejścia omówmy pokrótce samą składnię.

Gherkin

Scenariusze testowe definiowane są poprzez użycie dedykowanych słów kluczowych udostępnianych i następnie analizowanych przez parser Gherkin, który umożliwia połączenie opisu z kodem. Wówczas język ten pełni rolę ubiquitous language, zrozumiałego przez wszystkie zaangażowane w tworzenie oprogramowania strony.

Składnia

Wyróżniamy trzy rodzaje kroków na które składa się typowy scenariusz:

  • Context (preconditions)doprowadzenie aplikacji do określonego stanu początkowego skąd dany scenariusz może być realizowany,
  • Events – akcja wykonywana przez użytkownika,
  • Outcomes – weryfikacja zachowania, rezultatu, po wykonaniu danej akcji.

 

Przykładowy scenariusz testujący funkcjonalność Drag and Drop.

Powyższy scenariusz zawiera szereg słów kluczowych oraz kroków, które z kolei są interpretowane przez narzędzie Cucumber i mapowane wraz z ich implementacją. Każde ze wspomnianych słów kluczowych spełnia ściśle określone zadanie:

  • Feature  – określa testowany kontekst; przykładowo mogą to być oczekiwane zachowania związane ze stroną logowania, stroną domową, bądź też bardziej specyficzne funkcjonalności. Poniżej krótkiego określenia zakresu danego Feature file’a powinien znajdować się opis z punktu widzenia użytkownika, jakie zachowanie jest weryfikowane oraz jaki jest oczekiwany wynik (w bardzo ogólnym znaczeniu w danym kontekście),
  • Scenario / Scenario Outline – oznacza początek specyficznego scenariusza wraz z jego krótkim opisem; różnica między tymi słowami kluczowymi polega na tym, że Scenario służy do definicji pojedynczego scenariusza, natomiast Scenario Outline pozwala na jego sparametryzowaną definicję, która jest wykonywana dla wszystkich wylistowanych parametrów,
  • Given – określenie kroku wykonującego jakąś wstępną inicjalizację, doprowadzenie produktu do jakiegoś stanu początkowego z którego to startując dany scenariusz będzie mógł zostać zrealizowany,
  • When – określa wykonywaną akcję przez użytkownika, która stanowi niejako kluczowy element danego scenariusza,
  • Then – kroki mające na celu weryfikację danego scenariusza, zachowania czy też funkcjonalności; przykładowo po kliknięciu w jakiś przycisk należy zweryfikować czy jakiś dodatkowy oczekiwany element jest widoczny na ekranie,
  • And – odzwierciedla krok poprzedzający w celu uniknięcia powtarzania danego słowa w każdym kroku oraz sprawia, że składnia odzwierciedla język angielski.

Bardziej szczegółowe omówienie składni można znaleźć w dokumentacji Cucumber.

Problemy z Gherkinem

Gherkin pozwala na opisową implementację przypadków testowych narzucając odpowiednią składnię zrozumiałą dla biznesu oraz ludzi technicznych. Pomimo niewątpliwych zalet ma to jednak również swoje wady.

Single responsibility principle

Definiując konkretny Scenariusz, musimy zachować odpowiednią kolejność kroków, tj. GivenWhenThen. Wówczas tylko taka kolejność jest dozwolona, nie należy stosować naprzemiennie kroków łamiących wspomnianą kolejność.

Jest to oczywiście konsekwencja spójności składni zrozumiałej przez Gherkin, w praktyce jednak możemy napotkać scenariusze, gdzie ograniczenie to może skutkować dodatkowym nakładem czasowym w kontekście długości wykonywania testów. Wówczas należy ograniczyć przypadki testowe tylko do krytycznych z punktu widzenia biznesu czy też końcowego aktora.

Single Responsibility Principle dodatkowo mówi o tym, że indywidualne kroki powinny odpowiadać tylko i wyłącznie za realizację pojedynczej akcji. Innymi słowy, słowo kluczowe and nie może występować w definicji kroku. Przykładowo, Given I am logged in and I am on a Home page, jest niezgodny z SRP, definicję tą należałoby rozbić na dwa osobne kroki.

Podejście imperatywne

Spotykanym również problemem jest niepoprawne definiowanie samych scenariuszy. W celu jak największej i jak najdłuższej kompatybilności danego scenariusza z aplikacją, jego definicja powinna być niezależna od implementacji samej aplikacji.

Należy wówczas zastosować podejście deklaratywne. W odróżnieniu od imperatywnego, powinniśmy się skupić na opisie jakie konkretne zachowania są oczekiwane w danym kontekście.

Przykładowo, chcąc przetestować funkcjonalność logowania, nie powinno się definiować indywidualnych kroków jakie wykonuje użytkownik ale jedynie co jest w danym przypadku oczekiwane.

Przykład nieprawidłowo napisanego scenariusza w sposób imperatywny:

  • Givenotworzyłem stronę logowania
  • When: wpisuję login w pierwszym polu tekstowym
  • And: wpisuję hasło w drugim polu tekstowym
  • And: klikam przycisk Zaloguj
  • Then: widzę spersonalizowaną stronę domową

Przykład prawidłowego scenariusza w stylu deklaratywnym:

  • Given: otworzyłem stronę logowania
  • When: loguję się prawidłowymi danymi
  • Then: widzę spersonalizowaną stronę domową

Podsumowanie

Mając na uwadze wszystkie aspekty BDD można stwierdzić, że podejście to powinno być stosowane tylko do realizacji testów akceptacyjnych, nie powinno się go natomiast stosować do testów systemowych, wówczas zalety BDD stają się de facto obciążeniem i w pewnym momencie mogą obrócić się przeciwko nam.

Dodatkowym argumentem przemawiającym za tym, że BDD powinno być stosowane tylko dla testów akceptacyjnych jest fakt, że przyczyny ewentualnie nie przechodzących testów trudno zidentyfikować.

 

Zestawienie plusów oraz minusów BDD omawianych w artykule.

Podejście Behavior-Driven Development jest świetne jeśli chodzi o zbieranie wymagań dotyczących logiki biznesowej aplikacji i weryfikację końcowej implementacji, często niestety metodologia ta jest stosowana niezgodnie ze swoim przeznaczeniem co powoduje zaciemnianie jej pozytywnych aspektów.

Parafrazując nieśmiertelne to zależy, metodologię tę należałoby zastosować tylko po dogłębnej analizie samego produktu oraz oczekiwań biznesu, mając na uwadze wszelkie omawiane w tym artykule aspekty.

 

Przydatne linki:

  1. Dokumentacja Cucumber, https://cucumber.io/docs/bdd/>
  2. Składnia Gherkin, https://cucumber.io/docs/gherkin/
  3. BDD guide, https://inviqa.com/blog/bdd-guide
  4. How to write good Gherkin, https://medium.com/@wladislavk/how-to-write-good-gherkin-514aea53948c
  5. BDD 4 rules writing good Gherkin, https://techbeacon.com/app-dev-testing/better-behavior-driven-development-4-rules-writing-good-gherkin
  6. Introducing BDD, http://dannorth.net/introducing-bdd/
  7. BDD 101, https://automationpanda.com/2017/01/30/bdd-101-writing-good-gherkin/

O autorze

Marcin Leśniczek

Wiecznie głodny wiedzy z pasją dla aplikacji mobilnych oraz hybrydowych. Zawsze otwarty na nowe pomysły i technologie, szukający dziury w całym. Po godzinach entuzjasta nauki i astronomii.

Chcesz razem z nami tworzyć treści na bloga? Dołącz do nas i twórz wartościowe treści dla sympatyków Angulara z Angular.love!

0 komentarzy

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *