Witam ponownie! Dziś, tak jak zapowiadałem w ostatnim wpisie, znów powraca temat “Testowanie z Jasmine” :) Powoli robi się z tego taki mini kurs (czy jak to nazwać) no ale temat zdecydowanie wymaga kontynuowania… Zatem dziś kolejne aspekty frameworka Jasmine, a konkretniej matchery czyli sposób na testowanie oczekiwanej wartości; ponadto “setup” oraz “teardown” czyli sposób na inicjowanie testów i sprzątanie po nich; wspomnę także o metodach wyłączania i zawieszania testów. Zatem do rzeczy!

Testowanie oczekiwanej wartości czyli matchery

W poprzednim wpisie już co nieco na ten temat wspomniałem… Matcher jest to funkcja wywoływana na rzecz obiektu zwracanego przez funkcję expect (interfejs łańcuchowy typu fluent) i pozwala definiować asercję (funkcja expect przyjmuje jako parametr wartość testowaną, natomiast matcher przyjmuje wartość oczekiwaną). Dzięki temu możliwe jest testowanie oczekiwanej wartości. Dla przykładu, w poprzednim wpisie mieliśmy coś takiego:

expect(true).toBe(true);

Dodatkowo, Jasmine dostarcza nam możliwość zaprzeczenia za pomocą wstawienia not przed matcherem:

expect(false).not.toBe(true);

Jak się jednak zapewne domyślacie, toBe to nie jedyny dostępny w Jasmine matcher… Poniżej lista wszystkich:

  • toBe - porównuje na zasadzie wykorzystania operatora “===”
  • toEqual - służy do porównywania obiektów prostych, powinno także działać dla obiektów
  • toMatch - pozwala testować za pomocą wyrażenia regularnego
  • toBeDefined - sprawdza czy wartość jest zdefiniowana
  • toBeUndefined - sprawdza czy testowana wartość jest równa undefined
  • toBeNull - pozwala testować czy wartość jest równa null
  • toBeTruthy, toBeFalsy - służą do testowania rzutowania na typ bool na przykład: var foo = 'foo'; expect(foo).toBeTruthy();
  • toContain - sprawdzanie czy tablica zawiera element
  • toBeLessThan, toBeGreaterThan - testowanie czy wartość jest mniejsza (większa) od podanej
  • toBeCloseTo - to ciekawe :) sprawdza czy wartość, np. var pi = 3.14 jest bliska podanej wartości, np. 3
  • toThrow - sprawdza czy wyrażenie rzuca wyjątek

Jak widzicie, całkiem tego sporo… Wydaje się, że powinno wystarczyć do codziennej pracy, jeśli jednak brakuje nam jakiegoś matchera, zawsze istnieje możliwość napisania sobie własnego. Ten temat wykracza poza zakres tego wpisu, dlatego dociekliwych odsyłam do odpowiedniej dokumentacji dostępnej pod tym linkiem.

Inicjowanie i sprzątanie

Każdy, kto zetknął się już z jakimkolwiek frameworkiem do testowania, spotkał się w nim na pewno z odpowiednią składnią, która pozwala na inicjację testu **(na przykład inicjowanie danych) i jegosprzątanie (na przykład zamykanie połączeń z bazą danych). **Nie inaczej jest w przypadku Jasmine. Tutaj do tego celu służą dwie funkcje: beforeEach dla inicjowania oraz afterEach dla sprzątania. Spójrzmy na przykład (wprost z dokumentacji Jasmine):

describe('A spec (with setup and tear-down)', function() {
  var foo;

  beforeEach(function() {
    foo = 0;
    foo += 1;
  });

  afterEach(function() {
    foo = 0;
  });

  it('is just a function, so it can contain any code', function() {
    expect(foo).toEqual(1);
  });

  it('can have more than one expectation', function() {
    expect(foo).toEqual(1);
    expect(true).toEqual(true);
  });
});

Generalnie, wszystko to co dzieje się w funkcji callback przekazywanej do beforeEach oraz analogicznie do afterEach wykonywane jest raz dla każdego “spec’a”. W powyższym przykładzie mamy dwa “spec’i” (rozpoczynają się wywołaniem funkcji it) - dla każdego z nich, przed jego wykonaniem wywołana zostanie funkcja zwrotna przekazana do beforeEach, a po jego wykonaniu funkcja zwrotna przekazana do afterEach. Dzięki temu, każdy “spec” ma w tym przypadku tak samo przygotowane dane.

Wyłączanie i wstrzymywanie testów

Kolejną przydatną funkcją każdego frameworka do testowania jest możliwość takiego oznaczenia już napisanych testów aby można było czasowo wstrzymać ich wykonanie lub wręcz całkowicie je wyłączyć - w końcu każda aplikacja “żyje”, wymagania się zmieniają i niektóre testy mogą przestać mieć rację bytu, a nie zawsze warto je całkiem usuwać.

W Jasmine mamy możliwość całkowitego wyłączenia całych zestawów testów. Robi się to bardzo prosto, poprzez dodanie do wywołania funkcji describe przedrostka “x”. Zresztą spójrzcie na przykład:

xdescribe('A spec', function() {
  it('is just a function, so it can contain any code', function() {
    expect(true).toBe(true);
  });
});

Mamy też możliwość wstrzymania wykonania testów (ang. pending), przy czym wstrzymywanie dotyczy tylko “spec’ów”. Takie wstrzymanie spowoduje, że test pojawi się na liście rezultatów, oznaczony jako “pending”. W Jasmine wstrzymać wykonanie testu można na trzy sposoby:

  • Poprzez dodanie “x” jako przedrostek funkcji it:
xit('is just a function, so it can contain any code', function() {
    expect(true).toBe(true);
});
  • Poprzez zdefiniowanie “spec’a” bez funkcji callback:
it('is just a function, so it can contain any code');
  • Poprzez wywołanie funkcji pending w ciele funkcji callback:
it('is just a function, so it can contain any code', function() {
    expect(true).toBe(true);
    pending();
});

Podsumowanie

Jak widać, testowanie oczekiwanej wartości w Jasmine jest dzięki matcherom na prawdę proste. To wszystko co na dziś przygotowałem, jednak to nadal nie koniec serii wpisów na temat testowania z Jasmine. W następnej części zajmiemy się “szpiegami” czyli sposobem na tworzenie “stub’ów” we frameworku Jasmine. Zapraszam!

P.S. Wpis ten jest częścią mini-serii na temat testowania Jasmine. Poniżej wszystkie części tej serii: