07 marca 2010

Grails a TDD z perspektywy "Growing Object-Oriented Software, Guided by Tests"

Growing Object-Oriented Software, Guided by TestsKsiążka jest od dzisiaj obowiązkowa dla kogokolwiek, komu przyjdzie pracować ze mną, aby...zrozumiał moje postępowanie :)

Rozpocząłem rozdziały praktyczne w części Part II. The Process of Test-Driven Development i nie mam wątpliwości, że teoria, a teraz praktyka (wciąż jednak tylko w postaci lektury książki), pozostawią trwały ślad w moim postrzeganiu programowania. Uległem książce całkowicie i czuję się lekko rozdarty.

Z jednej strony książka nawołuje do rozpoczynania projektów od przekrojowych testów integracyjnych, gdzie testuje się wybrane funkcjonalności docelowej aplikacji...bez jej istnienia (chociażby jednej maluczkiej klaski), a z drugiej mam świadomość (albo i nie, ze względu na brak praktycznego doświadczenia), że potrzebna wiedza na początku projektu i do zrobienia tego pierwszego kroku jest niebagatelna, a nerwy trzeba trzymać mocno na postronku. Moje rozpalone są do czerwoności. Chciałoby się trochę poszaleć programistycznie, a tu każą uzbroić się w cierpliwość i zbudować szkielet testujący wybraną funkcjonalność. I nie ma to być trywiał w stylu odczyt z bazki, ale w przypadku aplikacji webowej, najlepiej uruchomić przeglądarkę, wskazać właściwą stronę i sprawdzić wynik! Dla mnie to novum, bo pisanie testów sprowadzałem zwyczajnie do testów jednostkowych, jeśli w ogóle.

W przypadku Grails sprawa się znacznie upraszcza, bo wykonanie dowolnego polecenia budującego typu grails create-controller czy grails create-domain-class tworzy nie tylko wskazany artefakt, ale i...test integracyjny (!) Człowiek, czy chce, czy nie, ugrzązł w TDD na dobre. To, czy wyjdzie to na dobre i czy w ogóle skorzysta się z tego dobrodziejstwa jest tematem na inne przemyślenia, ale fakt faktem Grails zdaje się być pomocnym. Czy aby rzeczywiście można nazywać to "pomocnym"?

I tu pojawiła się moja wątpliwość. Nawet, jeśli Grails faktycznie tworzy testy integracyjne dla wybranego artefaktu czy stworzymy go explicite z grails create-integration-test, to zastanawia mnie, czy to faktycznie odpowiada początkowemu testowaniu integracyjnemu z TDD jak opisano w tej książce. Zdanie z dokumentacji grails create-integration-test:

An integration test differs from a unit test in that the Grails environment is loaded for each test execution.

uspokaja mnie nieznacznie, bo w końcu cała infrastruktura Grails jest uruchamiana w całości przy każdym teście, ale zastanawiam się, czy nie powinienem raczej zbudować war (grails war), uruchomić Tomcata z podłączoną zewnętrzną bazą danych, wdrożyć i uruchomić aplikację i po uruchomieniu przeglądarki uruchomić testy integracyjne (pewnie z pomocą Selenium)?! Znacznie to więcej roboty, ale faktycznie odpowiada bardziej docelowej architekturze, a tak zrozumiałem potrzebę rozpoczęcia prac z testami integracyjnymi, które najbardziej zbliżą nas do docelowego środowiska produkcyjnego. Czy przypadkiem nie poniosło mnie za bardzo? Pomocy!

2 komentarze:

  1. Jestem już po pierwszym przeczytaniu tej książki (którą powinno się raczej 'studiować' niż tylko raz przeczytać) i tak się zastanawiam, czy w powyższym wpisie nie pomyliłeś koncepcji testu integracyjnego z testem end-to-end?

    To dwa rożne rodzaje testów, a wypowiadasz się o testowaniu integracyjnym jakby to był ten rodzaj, który przekrojowo testuje całą aplikację w pełnym środowisku takim jak docelowe (lub maksymalnie zbliżonym do docelowego).

    Autorzy dzielą testy na 3 rodzaje, testy jednostkowe - sprawdzają napisane przez nas klasy - głównie logikę biznesową: np. czy podejmowane są odpowiednie decyzje.

    Testy integracyjne sprawdzają jak się zachowuje nasza aplikacja na styku z bibliotekami/aplikacjami zewnętrznymi. W tego rodzaju testach często mockuje się nasze klasy biznesowe, ale do akcji wkracza np. baza danych i dostawca JPA razem z np. kontenerem EJB czy servletów.

    Dopiero testy end-to-end uruchamiają wszystko razem, bez żadnego ściemniania, mockowania czy podkładania sztucznych obiektów. Wszystko ma być "na żywo".

    OdpowiedzUsuń
  2. W wersji grails 1.2.0 przy tworzeniu domeny lub kontrolera nie powstaje test integracyjny a jednostkowy (testy tworzone sa automatycznie w katalogu unit, katalog integration pozostaje pusty).

    Natomiast budowanie wara, deploy na tomcat i odpalenie testow webowych to podchodzi pod testy funkcjonalne ktore rowniez maja wsparcie w grailsach w postaci Canoo WebTest Plugin. Testy funkcjonalne testuja aplikacje z perspektywy ostatecznego uzytkownika testujac cala aplikacja, jej wszyskie warstwy.

    Testy integracyjne natomiast skupiaja sie na testowaniu modulu lub podsystemu calej aplikacji ktory sklada sie z kilku modulow.

    Reasumujac moim zdaniem testy funkcjonalne sa testami ktore odpalane byc powinny w srodowisku ktore jest najblizsze srodowisku produkcyjnemy.

    OdpowiedzUsuń