niedziela, 21 października 2012

Postanowiłem nie rozwijać dalej bloga, ponieważ z przykrością muszę stwierdzić, że nikomu nie polecam technologii Grails. Po wielu godzinach przepracowanych z jej udziałem, stwierdzam, że nie jest ona godna polecenia na dłuższą metę. Twórcy zmieniają API, testy wykonują się poprawnie w jednej wersji natomiast w kolejnej okazuje się, że kilkanaście testów nagle nie przechodzi.

Sam pomysł technologii jest fajny, ale uważam że jak na produkt tak uznanej i sprawdzonej firmy jak SpringSource jest niewystarczająco dojrzały. Co z tego, że uda się szybko napisać kod, który spełnia jakąś funkcjonalność, podczas gdy spędzi się nadmierną liczbę godzin nad inną z powodu błędów Grails. Osobom zainteresowanym podobnym podejściem do tworzenia aplikacji polecam zainteresować się RubyOnRails i JRuby.

wtorek, 27 grudnia 2011

Sky używa Grails

Grails nie jest niestety zbyt popularną technologią (sam myślę o tym, aby przerzucić się na inne twory z powodu ograniczonego rynku pracy), jednakże duże serwisy wykorzystują ją z powodzeniem. Przykładem tego jest sky.com, brytyjski gigant telewizyjny.

Artykuł opisujący przejście Sky.com na Grails

poniedziałek, 5 grudnia 2011

Testowanie kontrolerów Grails 2.0

Grailsy 2.0 (wydano już wersję RC3, więc finalna już bardzo niedługo) wprowadzają nową jakość do testowania. Porzucono całkowicie ideę (i słusznie) rozszerzenia klas dziedziczących po GrailsUnitTestCase i zastosowano tzw. mechanizm Mixins. Jest to jedna z fajnych właściwości języka Groovy, umożliwiająca dodawanie metod do klasy w runtime, więcej o niej tutaj.

Przejdźmy jednak do meritum. Poniższy kod prezentuje klasę testową kontrolera.

@TestMixin(DomainClassUnitTestMixin)
@TestFor(IndexController)
class IndexTests {

  def position

  @Before
  void setUp() {
    mockDomain(BusinessType)
    new BusinessType(name: "otherType.name").save()
  }

  @Test
  void shouldReturnLocatedPosition() {
      assert controller.index().position == position
  }
}

Dla osób, które pisały w Grails w wersji 1.x niektóre elementy wydadzą się znajome, a mianowicie metody mockDomain oraz obiekt controller. Jednakże tutaj uzyskujemy je dzięki adnotacjom @TestMixin oraz @TestFor.

TestFor jest standardową adnotacją, gdy chcemy testować, któreś z elementów MVC w Grails 2.0. Automatycznie rozpozna on typ klasy (Controller, Domain...) oraz wstrzyknie odpowiednie metody. Dla testów kontrolerów są to między innymi obiekt controller oraz obiekt response. Więcej o nich jednak w dokumentacji.

Druga adnotacja @TestMixin służy do łączenia testów różnych elementów MVC. W podanym przykładzie jako argument podałem DomainClassUnitTestMixin, co umożliwia mi wykorzystanie metody mockDomain, która to działa analogicznie z metodą mockDomain w GrailsUnitTestCase znaną z wersji 1.x.

Gdy chcemy testować z użyciem klas Domain, możemy także posłużyć się adnotacją @Mock([BusinessType]), która to automatycznie wykona metodę mockDomain (w tym przypadku nie musimy już korzystać z @TestMixin).

piątek, 2 grudnia 2011

Mockowanie konstruktorów

Gmock oferuje także bardzo przydatną funkcję mockowania konstruktorów. Jest to, co prawda pewnego rodzaju zły design, jeśli trzeba wykorzystać tą funkcjonalność, jednak jako że Groovy jest językiem dynamicznym i nie lubimy kodować niepotrzebnych fabryk, to taka funkcjonalność może być z powodzeniem wykorzystana. Dla przykładu podam kawałek kodu nad którym dzisiaj siedziałem. Musiałem skorzystać z generatora losowego, jednakże zależy mi w tym wypadku na wielowątkowości, więc musi być on tworzony dla każdego obiektu. Nie widzę sensu w tym przypadku, na tworzenie dodatkowej klasy fabryki dla typowego obiektu Java, więc zdecydowałem się na skorzystanie z mockowania konstruktora (kodu z wykorzystaniem generatora losowego z oczywistych względów nie można testować bez obiektów pozornych).
@Test
void shouldReturnDiscount2() {
  def mockRandom = mock(Random, constructor(anything()))
  mockRandom.nextInt(3).returns(2)
  play {returnValue = sut.getRandomActiveDiscount()}
}

I tak ten mały kawałek kodu mi to umożliwił. W tym przypadku mockuję konstruktor klasy Random, do którego przekazywany jest jakikolwiek parametr. Konstruktor ten zwróci mi obiekt mockRandom, na którym mogę wykonywać dalsze potrzebne mi operacje.

środa, 16 listopada 2011

Partial Mock

Partial mock jest to sposób na "udawanie" tylko niektórych metod z obiektu. W ten sposób, gdy chcemy aby obiekt działał normalnie, a chcemy w jakimś celu skorzystać z funkcjonalności frameworka do obiektów pozornych możemy to uczynić.

W Grailsach jest to przydatne narzędzie, ponieważ często używane są dynamicznie wstrzykiwane metody (np. do kontrolerów) do których nie mamy dostępu w środowisku testowym, a z których korzysta kod.

Poniższy przykład demonstruje użycie partial mock we frameworku gmock:

def controller = new SomeController()
def mockRequest = mock()
mockController.request.returns(mockRequest)

Dla instancji controller podmieniamy w tym przypadku właściwość request na nasz mockRequest. Jak widać składnia partial mock jest identyczna jak składnia przy typowych obiektach pozornych, więc skorzystanie z tej techniki będzie wyjątkowo łatwe.

niedziela, 13 listopada 2011

Gmock

W TDD istnieją dwa podejścia do testów interakcji:
  • klasyczne, gdzie wykorzystuje się prawdziwe obiekty, jeśli można
  • z wykorzystaniem obiektów pozornych (Mock objects) 
Drugie podejście jest bliższe idei testów jednostkowych, ponieważ pozwala przetestować kod w prawdziwej izolacji od innych obiektów. Dzięki dobremu wykorzystaniu obiektów pozornych można łatwo sprawdzić interakcje między obiektami, nawet jeśli nie zwracają one żadnych wartości.

Takie podejście w projektach opartych o architekturę MVC, do których oczywiście zaliczają się Grailsy, jest bardzo przydatne m.in. w kontrolerach, które zwykle operują na obiektach klas domenowych czy też serwisów. Dzięki zastosowaniu mocków możemy łatwo sprawdzić czy kontroler wykonuje powierzone mu zadania i nie jesteśmy uzależnieni od faktycznej implementacji innych warstw.

Dzięki dynamiczności języka Groovy, obiekty pozorne można tworzyć bez użycia wyspecjalizowanych frameworków, jednakże jest to dość niewygodne. Powstało kilka projektów mających na celu uczynienie tego łatwiejszym. Jeden z nich (MockFor) jest zintegrowany w Groovy on Grails, jednakże mi osobiście nie podpasował. Wobec czego polecam Gmock, z którego sam także korzystam.

Instalacja Gmock w projekcie Grails nie jest skomplikowana, jednakże aktualnie nie istnieje żaden plugin, który bo to jeszcze ułatwiał. Skorzystamy, więc z Mavena i pliku conf/BuildConfig.groovy. W sekcji odpowiadającej za dependencies dopisujemy:
test 'org.gmock:gmock:0.8.1'
Aby wykorzystać Gmock w swoim teście możemy zastosować jedną z 3 metod:
  • dziedziczyć po klasie GMockTestCase (to jest opisane w dokumentacji Gmock, jednakże to podejście nie jest najlepsze z różnych przyczyn, więc nie będę go szerzej opisywał)
  • dodać adnotację @WithGMock do klasy testu (to jest najfajniejsze rozwiązanie, jednakże w aktualnej wersji nie działa z Grails 2.0)
  • użyć obiektu typu GMockController() 
We wszystkich poniższych przykładach zakładam, że istnieje już obiekt typu GMockController o nazwie gmock (jeśli ktoś korzysta z metody 1 lub 2, to we wszelkich wołaniach można go pominąć. Czyli zamiast gmock.metoda() piszemy metoda()).

 Tworzenie obiektów pozornych jest bardzo łatwe i opiera się na prostym DSL stworzonym w tym celu.

I tak dla klasy SpringSecurityService tworzymy go w następujący sposób:
def springSecurityMock = gmock.mock(SpringSecurityService)
W ten sposób mamy utworzony obiekt pozorny, jednakże jeszcze bez żadnych metod, czy też sprawdzania warunków. Aby dodać warunki skorzystamy z poniższego kodu:

springSecurityMock.encodePassword("password").returns("asd").times(1)
 Powyższy kod można rozbić na kilka członów:
  • springSecurityMock.encodePassword("password") - jest to zdefiniowanie metody encodePassword, która spodziewa się podanego parametru
  • returns("asd") - zdefiniowane wartości zwracanej dla metody z poprzedniego kroku
  • .times(1) - nasze założenie testowe
Powyższy kod można wobec tego przeczytać jako: spodziewaj się jednokrotnego wywołania metody encodePassword z parametrem "password" i zwróc "asd".

Tak przygotowane założenie sprawdzamy za pomocą metody play:
gmock.play { sut.someMethodThatCallsEncodePassword() }

 Poniżej prezentuję całą metodę testową z wykorzystaniem Gmock:
@Test
void shouldCallEncodePassowrd() {
  def gmock = new GMockController()
  sut.springSecurity = gmock.mock(SpringSecurityService)
  sut.springSecurity.
    encodePassword("password").returns("asd").times(1)   gmock.play { sut.someMethodThatCallsEncodePassword() } }
Powyższy kod wykona się poprawnie, gdy metoda  someMethodThatCallsEncodePassword faktycznie zawoła metodę encodePassword z parametrem "password".

Gmock jest bardzo ciekawą biblioteką, ponieważ potrafi podmieniać także metody statyczne, bądź też metody na żywych obiektach (tzw. partial mock), jednakże o tym w następnych postach.

sobota, 12 listopada 2011

Grails 2.0

W związku z niedługim wydaniem nowej wersji Grails postanowiłem zacząć pisać bloga o tej technologii. Postaram się tutaj opisywać raczej ciekawostki i nowości niż samouczek dla początkujących, ponieważ takich trochę w internecie jest, ale znajdą się tutaj też informacje na różnym stopniu zaawansowania. Na początek pójdzie testowanie z użyciem GMock. Pierwszy wpis już wkrótce.