AngularJS #6 – Karma – pierwszy test

AngularJS



Kolejnym wpisem miało być rozszerzenie o filtrach, ale uznałem, że jest tam zbyt mało materiału, by robić z tego osobny element całego cyklu o AngularJS. Sam temat filtrów jest poza tym na tyle prosty, że nie warto poświęcać na niego zbyt wiele czasu. Znacznie bardziej należałoby się skupić na elemencie testowania aplikacji i dlatego też chciałbym Was wprowadzić w świat Jasmine i Karma.

Karma

Karma jest narzędziem, które pozwala uruchamiać testy kodu JavaScript pod różnymi przeglądarkami, a w zasadzie ich emulowanym środowiskiem. Karma nie jest pełnoprawnym frameworkiem do testowania, a jedynie rusztowaniem, na którego bazie zbudować możemy pełny stack testujący JavaScript. Karma zbudowana jest w oparciu o serwer Node.js oraz technologię Socket.io. Pozwala na wykonywanie testów w różnych środowiskach pracy (deweloperskim, testowym, produkcyjnym itd.), a ponadto wykonuje wszystkie testy w separacji od kodu właściwego. Pozwala także na wykonywanie testów pod różnymi przeglądarkami jednocześnie. W połączeniu z Istanbul, który to potrafi wygenerować i pokazać nam pokrycie naszego kodu testami, Karma stanowi pełnoprawne środowisko testowe, które ułatwia nam, a w zasadzie pozwala na szybkie i bezproblemowe testowanie kodu JavaScript.

Pełny opis instalacji oraz konfiguracji znajdziecie na oficjalnej stronie projektu. Znajduje się tam także film, który bardzo trafnie prezentuje możliwości jakie daje nam Karma.

Jasmine

Spośród kilku frameworków do testowania kodu JavaScript, miałem do tej pory okazję wykorzystywać właśnie Jasmine. Jasmine, to behavior-driven development framework, który pozwala na pisanie naszych testów w sposób bardzo opisowy, a ponadto świetnie integruje się ze środowiskiem Karma. Nie jest on zależny od żadnego frameworka JavaScript i nie wymaga także drzewa DOM do działania. Jasmine pozwala nie tylko na pisanie testów jednostkowych, ale również tak zwanych testów e2e. Kilkadziesiąt przykładów znajdziecie na stronie oficjalnej i w zasadzie nie pozostaje nic innego jak zacząć pisać testy!

Główny konkurent JasmineMocha jest nieco bardziej rozbudowany i dojrzały, ale “próg wejścia” jest także nieco większy. Jest jeszcze QUnit, który używany jest w projektach jQuery, jQuery UI oraz jQuery Mobile, ale nie cieszy się taką popularnością community jak pozostałe dwa.

Let’s write some code!

Nie będę tutaj opisywał jak skonfigurować sobie Karmę oraz Jasmine by działały razem, bo jest to świetnie opisane oraz pokazane na stronach oficjalnych obu narzędzi.

Przypuśćmy zatem, że chcemy przetestować działanie metody w naszym kontrolerze. Niech będzie to przykład metody, która po wykonaniu funkcji sayHello() zmienia wartość parametru name w $scope kontrolera APP.ApplicationCtrl na ‘World’.

'use strict';

var APP = angular.module('APP', []);

APP.ApplicationCtrl = function ($scope) {

    $scope.name = '';

    $scope.sayHello = function () {
        $scope.name = 'World';
    };

};

Klasa testowa wyglądać będzie następująco:

'use strict';

describe('APP.ApplicationCtrl', function () {

    var scope;

    // mockujemy nasz modul APP
    beforeEach(angular.mock.module('APP'));
    // mockujemy kontroler ApplicationCtrl
    // i przekazujemy do niego mock $scope utworzony na podstawie $rootScope
    beforeEach(angular.mock.inject(function ($rootScope, $controller) {
        // tworzymy pusty scope
        scope = $rootScope.$new();
        // tworzymy instancje kontrolera i przekazujemy do niego pusty $scope
        $controller('ApplicationCtrl', { $scope: scope });
    }));

    // .. i testujemy
    it('should set new value for $scope.name', function () {
        // having
        scope.name = '';

        // when
        expect(scope.name).toBe('');
        scope.sayHello();

        // then
        expect(scope.name).toBe('World');
    });

});

Wykonanie powyższego testu zwróci nam oczywiście pozytywny wynik. Tym oto prostym sposobem przetestowaliśmy banalną metodę naszego kontrolera.

Jasmine zawiera szereg predefiniowanych metod oraz asercji do testowania naszego kodu. Jesteśmy w stanie na przykład sprawdzić, czy dana metoda wykonała się w cyklu wykonywania innej z metod w naszym kontrolerze, a na dodatek sprawdzić, czy wykonała się określoną ilość razy. Jesteśmy w stanie porównywać całe kolekcje pod względem zawartości, czy emulować zapytania HTTP. Zachęcam do przyjrzenia się dokumentacji i własnych prób.

I na koniec jak zawsze http://egghead.io i prezentacja Karmy oraz Jasmine na równie prostym przykładzie.

[youtube_sc url=”https://www.youtube.com/watch?v=wFYID8eYQLs”]