PiszeO.IT

Behavior Driven Development – BDD. Jak pisać wymagania zrozumiałe dla wszystkich

Skuteczna komunikacja między zespołem deweloperskim, a interesariuszami oraz rozumienie potrzeb obu stron, to kluczowy element wytwarzania i rozwoju oprogramowania. Znalezienie wspólnego języka, który zapewni spójny opis funkcjonalności może znacząco poprawić jakość wytwarzanego oprogramowania.

Behavior Driven Development to zbiór praktyk, dzięki którym opis funkcjonalności będzie w pełni zrozumiały dla biznesu i zapewni poziom szczegółowość potrzeby programistom do implementacji. Dodatkowo specyfikacja zbudowana wg. BDD stanie się gotowym, w pełni automatycznym zestawem testów akceptacyjnych i dokumentacją niskiego poziomu.

Techniki BDD (dosł. programowanie sterowane zachowaniami) bazują na praktykach Agile i Lean, w szczególności technikach programowania sterowanego testami (TDD) oraz projektowania domenowego (Domain Driven Design — DDD). 

W BDD olbrzymią rolę odgrywa współpraca — zarówno między użytkownikami a zespołem projektowym, jak i wewnątrz samego zespołu. Analitycy biznesowi, programiści i testerzy podczas definiowania i specyfikowania cech funkcjonalnych współpracują z użytkownikami końcowymi, a członkowie zespołu czerpią pomysły ze swoich indywidualnych doświadczeń oraz know-how.

WSPÓŁPRACA W CELU SPECYFIKACJI CECH FUNKCJONALNYCH

„Złożony problem, taki jak odkrywanie sposobów na zdobycie uznania klientów, najlepiej jest rozwiązywany przez zróżnicowaną grupę ludzi, która ponosi odpowiedzialność za rozwiązanie problemu, samodzielnie się organizuje i wspólnie działa w celu opracowania rozwiązania.”

Stephen Denning, The Leader’’s Guide to Radical Management (Jossey-Bass, 2010)

Specyfiką BDD jest język naturalny, którego struktura wywodzi się z określonego z góry modelu. Zawiera wszystkie pojęcia, które będą użyte do definicji zachowania systemu. Umożliwia on płynną komunikację między klientami, a deweloperami. BDD nie dopuszcza dowolności w formatowaniu opisu cech/funkcjonalności, historii użytkowników oraz scenariuszy. Istnieją określone szablony przygotowane w oparciu o wcześniej stworzony język Gherkin.

Krótszy proces dostarczania

Kompleksowe testy sterowane zachowaniem przyczyniają się także do skrócenia procesu dostarczania nowych wersji aplikacji (CD). Zespół testerów nie musi już marnować czasu na długotrwałe ręczne testowanie elementów aplikacji przed każdym wydanie. Testerzy mogą skupić się na bardziej wyszukanych testach manualnych i badawczych (np. testach użyteczności).

Unikanie marnotrawstwa

Bardzo często zdarza się, że zespoły marnują swój czas na implementację funkcjonalności, które biznes wcale nie potrzebuje i nigdy nie będzie ich używał. Stosowanie praktyk BDD pozwala uniknąć marnotrawstwa czasu i wysiłków, ponieważ pomaga zespołom skoncentrować się na cechach funkcjonalnych, które są dostosowane do celów biznesowych. Określenie dokładnych scenariuszy zachowania pomaga w określeniu, które elementy są istotne dla danej implementacji, a które są zupełnie zbędne i nie warto się nimi zajmować.

Jak wygląda proces w BDD?

Proces BDD świetnie sprawdza się w zwinnych metodykach wytrzymywania oprogramowania.

  1. Jacek przychodzi do Krzyśka – analityka biznesowego i opowiada o funkcjonalnościach, które chciałby wdrożyć w aplikacji. Aby zmniejszyć ryzyko nieporozumień posługują się konkretnym przykładami tego, co dana funkcja ma realizować.
  2. Krzysiek – nasz analityk biznesowy przed rozpoczęciem pracy nad daną funkcjonalnością spotyka się z zespołem deweloperskim (programiści, testerzy). Wspólnie dyskutują na temat kluczowych przykładów i przekształcają je na zestaw wymagań (scenariuszy) zapisanych w formie specyficznego języka Gherkin dla BDD. Język ten jest zrozumiały dla wszystkich członków zespołu, w tym także interesariuszy.
  3. Programista używa narzędzi BDD do przekształcenia zapisanych wcześniej scenariuszy na zestaw testów automatycznych, które są uruchamiane i weryfikują obiektywnie na jaki etapie jest dana implementacja.
  4. Tester używa zapisanych scenariuszy jako punkt wyjścia do bardziej wyszukanych testów manualnych, które ciężko zautomatyzować.
  5. Testy automatyczne i przygotowane scenariusze spełniają funkcję niskopoziomowych dokumentacji technicznych i dostarczają realne przykłady działania aplikacji.

Cel biznesowy

Według BDD opis nowej funkcjonalności powinien rozpoczynać się od zdefiniowania historyjki użytkownika, która opisuje cel biznesowy, rolę i to co dana funkcja ma wykonywać. Ważne, aby wszyscy członkowie zespołu rozumieli co dany projekt ma realizować. Cele biznesowe muszą być przekazane zespołowi deweloperskiemu, aby znał dokładny kontekst tego co jest do zaimplementowania.

Opis każdej nowej funkcjonalności powinien rozpoczynać się od stwierdzeń:

W celu <osiągnięcia celu biznesowego lub dostarczenia wartości biznesowej>
Jako <interesariusz>
Chcę <czegoś>

W celu bardziej efektywnego planowania podróży
Jako podróżny
Chcę znać optymalną trasę pomiędzy dwoma stacjami

Specyfikacja przez przykład

Kolejnym krokiem jest dodanie scenariusza (przypadków użycia), który wyjaśni w jaki sposób ma działać dana implementacja, ale także będzie kryterium dla testów akceptacyjnych. Wykorzystanie przykładów do określenia oczekiwanych zachowań systemu jest kluczową częścią technik BDD. Naturalny porządek scenariusza to ZakładającGdyWtedy (ang. GivenWhenThen):

Słowo kluczowe Zakładając (ang. Given) opisuje warunki wstępne dla scenariusza i przygotowuje środowisko testowe.

Słowo kluczowe Gdy (ang. When) opisuje testowane działanie.
Słowo kluczowe Wtedy (ang. Then) opisuje oczekiwane rezultaty.
Słowa kluczowe I (ang. And) i Ale (ang. But) można wykorzystać do połączenia kilku etapów Zakładając, Gdy, Wtedy w taki sposób, by przyjęły bardziej czytelną formę.

Pełny opis funkcji z historyjką i przypadkami użycia oraz testami akceptacyjnymi:

Funkcja: Przelew środków pomiędzy rachunkami

Aby lepiej zarządzać własnymi środkami finansowymi
Chcę jako klient banku mieć możliwość przelewania środków pomiędzy moimi rachunkami zawsze gdy tego potrzebuję

  • Scenariusz 1: Przelew środków na rachunek oszczędnościowym
    Zakładając
    saldo mojego rachunku bieżącego wynosi 1000.00 PLN
    I saldo mojego rachunku oszczędnościowego wynosi 2000.00 PLN
    Gdy przeleję 500.00 PLN z rachunku bieżący na rachunek oszczędnościowy
    Wtedy powinienem mieć saldo 500.00 PLN na moim rachunku bieżącym
    I powinienem mieć saldo 2500.00 PLN na moim rachunku oszczędnościowym
  • Scenariusz 2: Przelew przy niedostatecznej ilości środków
    Zakładając
    saldo mojego rachunku bieżący wynosi 1000.00 PLN
    I saldo mojego rachunku oszczędnościowy wynosi 2000.00 PLN
    Gdy przeleję 1500.00 PLN z rachunku bieżący na rachunek oszczędnościowy
    Wtedy powinienem uzyskać komunikat o błędzie 'niewystarczające środki’
    Wtedy powinienem mieć saldo 1000.00 PLN na moim rachunku bieżący
    I powinienem mieć saldo 2000.00 PLN na moim rachunku oszczędnościowy

Jak widać na przykładzie, stosując odpowiedni zapis otrzymujemy pełnowartościowy opis funkcjonalności, który zawiera precyzyjne informacje i przykłady. Można go jeszcze rozszerzyć o dane w formie tabeli, które będą obrazowały zmianę wartości w konkretnych przypadkach. Na tej podstawie zespół programistów jest już w stanie zaimplementować daną funkcjonalność.

Narzędzia wspomagające proces BDD

Narzędzia wspomagające BDD są zależne od języka programowania, w którym budujemy nasze rozwiązania. W przypadku PHP może być to framework Behat, a w przypadku Javy np. JBehave. Narzędzi jest całkiem sporo i wybór odpowiedniego frameworka zależy już od preferencji zespołu projektowego.

Przykładowy plik .feature z frameworka Behat:

Feature: weather indicator
    In order to get weather information
    As a user
    I want to get a human readable version of xml weather forcast

    Scenario:
        Given xml input "<some>strange</parsing error>"
        When I run my application
        Then I should get an exception with message "service currently not available"

    Scenario:
        Given xml input "<weather><cloud>0</cloud><temperature>-10</temperature><rain>0</rain></weather>"
        When I run my application
        Then I should get no error
        But I should be able to get weather information

    Scenario Outline:
        Given value <cloud> for clouds
        When I call cloudiness
        Then I should get cloudiness <cloudiness>

        Examples:
            | cloud | cloudiness    |
            | 0     | bright        |
            | 20    | partly cloudy |
            | 50    | cloudy        |
            | 90    | clouded       |

    Scenario:
        Given value 20 for clouds
        And value 27 for temperature
        And value 0 for rain
        When I call summary
        Then I should get summary "a beautiful warm day"

(więcej przykładów znajdziecie tutaj: https://github.com/Behat/Behat/tree/master/features)

Testy jednostkowe

Zastosowanie kilku prostych rozwiązań, takich jak np. używanie nazewnictwa testów jednostkowych przed implementacją funkcjonalności w formie pełnych zdań z użyciem słowa „should” (z ang. „powinien”), pomaga programistom pisać bardziej sensowne testy, co z kolei przekłada się na pisanie kodu wyższej jakości.

public class WhenTransferringInternationalFundsTest {

class WhenTransferringInternationalFundsTest
{
    public function testShouldTransferFundsToLocalAccount()
    {
        ...
    }

    public function testShouldTransferFundsToDifferentBank()
    {
        ...
    }

    public function testShouldDeductFeesAsSeparateTransaction()
    {
        ...
    }
}

Podsumowanie

W tekście przedstawiłem jedynie część elementów ze zbioru praktyk BDD. Pełne wdrożenie BDD w organizacji wymaga wykorzystania odpowiednich narzędzi w zależności od języka programowania w jakich budujemy rozwiązania. Daje to wymierne korzyści takie jak: automatycznie generowanie szablonów testów, generowanie dynamicznej specyfikacji niskiego poziomu, a także możliwość śledzenia etapów poszczególnych implementacji oraz ich statusów. Przedstawione praktyki mogą być wykorzystywane w każdej organizacji i w każdym projekcie praktycznie od zaraz.

Czytelnikom zainteresowanych technikami BDD polecam zapoznać się z publikacją „BDD w działaniu. Sterowanie zachowaniem w rozwoju aplikacji” autorstwa Johna Fergusona Smarta, która opisuje szczegółowo całe zagadnienie.

Miłosz Karolczyk

Nazywam się Miłosz Karolczyk i tworzenie oprogramowania jest moją pasją.

Jestem gorącym zwolennikiem architektury ewolucyjnej, podejścia Domain Driven Design, Event Stormingu oraz modularyzacji. Uwielbiam proste rozwiązania i szczupłe podejście do zarządzania oraz tworzenia produktów.