czwartek, 29 kwietnia 2010

Tumbler

To, że jestem fanem TDD wie pewnie każdy kto czyta ten blog. Za szczególnie dobrą jego formę uznaję BDD. W kodzie, który powstaje u nas w firmie staramy się stosować to podejście - nazewnictwo wyrażające intencję twórcy, testy pisane w formie przykładów (często z wykorzystaniem promowanego przez Szczepana Fabera szablonu //given //when //then), skupienie na celu powstawania kodu. Niedawno do naszego zespołu projektowego dołączyli nowi programiści (pracownicy naszego klienta) nieposiadający doświadczenia w TDD. Pierwsze o co zapytali to szczegółowa dokumentacja kodu. Nasze przekonywanie, że testy są kompletne i dokładnie dokumentują kod nie spotkały się ze specjalnym zrozumieniem z ich strony ;-) Doszedłem więc do wniosku, że gdybyśmy mogli wygenerować z naszych testów dokumentację - nawet tylko w formie listy funkcjonalności oferowanych przez nasz kod - to pewnie ich opory byłyby znacząco mniejsze. A że akurat prowadziłem tygodniowe szkolenie poza Warszawą (miałem więc codziennie parę wolnych godzin po pracy), postanowiłem napisać narzędzie, które pomogłoby w tworzeniu testów tak, by:
  1. jeszcze wyraźniej dawały znać co robią - tak, by nawet niewprawione w TDD oko rozpoznało o co chodzi (po prostu wystarczy czytać zdania...)
  2. dawały się generować w formie specyfikacji
  3. pozwalały lepiej myśleć o kodzie zanim jeszcze on powstanie (zapomniana faza 'think' z TDD) - w idealnym przypadku pozwalały na przygotowanie całego zbioru przykładów najpierw - np. wraz z kimś z biznesu, implementację pozostawiając na później (klasyczne Acceptance-Test Driven Development)
  4. dawały aktualną informacje o stanie implementacji w formie raportu (które funkcjonalności jeszcze nie są zaimplementowane, które są i działają, które nie działają)
  5. dawało się generować testy z pełnotekstowego opisu funkcjonalności
  6. wspierały IDE tak, by było tam widać całe zdania opisu a nie nazwy metod testowych
Gdy wracałem ze szkolenia podstawowe funkcje były już prawie gotowe. Samolot nie odleciał (Eyafjoell...) więc miałem do tego 7 godzin w pociągu ;-) I tak powstał Tumbler - biblioteka wspomagająca myślenie o testach jako o przykładach, służąca do prowadzenia myślenia o tym CO zrobić a nie JAK. Nie będę tu duplikował dokumentacji, zainteresowanym polecam ją przejrzeć - nie jest tego dużo.

Chętnie wysłucham komentarzy i pomysłów co można by lepiej/bardziej/na dodatek.

6 komentarzy:

  1. Dziękuję za opublikowanie narzędzia, bo nim, a właściwie jego źródłami, mam zamiar poduczyć się Twojego podejścia BDD :-) Już czytam dokumentację, a tam:

    library.lend(sampleBook).to(reader)

    i tu pojawia się moje pytanie: Czy skoro library.lend(sampleBook) jest dozwolone, w jakim stanie będzie library i sampleBook? Czy lend() nie powinno akceptować dwóch argumentów - co i komu?

    OdpowiedzUsuń
  2. @Paweł
    Koncepcja super! Nie mam teraz dostępu do IDE, ale muszę wypróbować. Dzięki!

    @Jacek
    Też o tym myślałem.
    Można by z tego wybrnąć zwracając nie Library, ale np. LendingInfo powiązane ściśle z biblioteką i książką.
    Jeśliby zwracać Library to nie tylko trzeba by trzymać stan biblioteki (i rzucać IllegalStateException, jeśli programista coś zawalił i nie dokończył procesu wypożyczania), ale właściwie byłoby to thread-unsafe. Nie dałoby się zabezpieczyć przed równoległym wypożyczaniem w wielu wątkach.
    Co o tym myślicie?

    OdpowiedzUsuń
  3. @Jacek - generalnie w przykładach w ogóle nie chodzi o to (tylko o całą resztę ;-)) Jak chcesz zobaczyć użycie narzędzia, to popatrz w jego testy.
    Co do Twojego pytania, to chyba napiszę post o fluid interfaces, to się wytłumaczę ;-)
    Generalnie albo można olać kontekst i założyć, że klient wie jak to wołać (złe rozwiązanie, ale proste) albo wbudować maszynę stanową.

    @Bartek
    Nie do końca masz rację - da się to zrobić, tylko stan trzeba trzymać wtedy w threadlocal'u.

    OdpowiedzUsuń
  4. Paweł, tak proszę o fluid API i jak to się ma do TDD/BDD, jeśli w ogóle. Potrzeba mi tej wiedzy, aby zrozumieć, dlaczego Ci, za którymi podążamy wybrali tę drogę. Czytam książkę, w której to podejście byłoby nieakceptowalne - niebiesko-czarna o TDD, wiesz która? :P

    OdpowiedzUsuń
  5. "Ci za którymi podążamy" - co paliłeś i gdzie to można dostać? ;-)
    O fluidach napiszę jeszcze w tym tygodniu. A do BDD to ma się w takim zakresie, że jak definiuję zachowania i już mam np. Tumblerowe całe zdania, to chcę żeby mój kod nie odbiegał znacznie czytelnością. A płynne interfejsy bardzo zwiększają czytelność.

    A czemu by było nieakceptowalne?

    OdpowiedzUsuń
  6. @Paweł
    > Nie do końca masz rację - da się to zrobić, tylko stan trzeba trzymać wtedy w threadlocal'u.

    To bardzo poproszę o przykład. Chętnie się nauczę czegoś nowego, bo tego nie umiem.

    OdpowiedzUsuń