Testowanie jednostkowe AngularJS: samouczek Karma Jasmine

Jednฤ… z najbardziej genialnych funkcji Angular.JS jest Testy aspekt. Kiedy programiล›ci w Google opracowywali AngularJS, pamiฤ™tali o testowaniu i upewniali siฤ™, ลผe caล‚y framework AngularJS nadawaล‚ siฤ™ do testowania.

W AngularJS testowanie jest zwykle przeprowadzane przy uลผyciu Karmy (framework). Testowanie Angular JS moลผna przeprowadziฤ‡ bez Karmy, ale framework Karma ma tak ล›wietnฤ… funkcjonalnoล›ฤ‡ do testowania kodu AngularJS, ลผe sensowne jest uลผycie tego frameworka.

  • W AngularJS moลผemy wykonaฤ‡ Testรณw jednostkowych oddzielnie dla kontrolerรณw i dyrektyw.
  • Moลผemy rรณwnieลผ przeprowadziฤ‡ koล„cowe testy AngularJS, czyli testowanie z perspektywy uลผytkownika.

Wprowadzenie i instalacja frameworku Karma

Karma jest narzฤ™dzie do automatyzacji testรณw stworzony przez zespรณล‚ Angular JS w Google. Pierwszym krokiem do korzystania z Karmy jest jej zainstalowanie. Karmฤ™ instaluje siฤ™ poprzez npm (ktรณry jest menedลผerem pakietรณw sล‚uลผฤ…cym do ล‚atwej instalacji moduล‚รณw na komputerze lokalnym).

Instalacja Karmy

Instalacja Karmy poprzez npm odbywa siฤ™ w procesie dwuetapowym.

Krok 1) Wykonaj poniลผszฤ… liniฤ™ z poziomu wiersza poleceล„

npm install karma karma-chrome-launcher karma-jasmine

W ktรณrym,

  1. npm to narzฤ™dzie wiersza poleceล„ dla menedลผera pakietรณw wฤ™zล‚รณw, uลผywane do instalowania niestandardowych moduล‚รณw na dowolnym komputerze.
  2. Parametr install informuje narzฤ™dzie wiersza poleceล„ npm, ลผe wymagana jest instalacja.
  3. W wierszu poleceล„ okreล›lone sฤ… 3 biblioteki wymagane do pracy z karmฤ….
    • karma jest podstawowฤ… bibliotekฤ…, ktรณra bฤ™dzie uลผywana do celรณw testowych.
    • karma-chrome-launcher to osobna biblioteka, ktรณra umoลผliwia rozpoznawanie poleceล„ karmy przez przeglฤ…darkฤ™ Chrome.
    • karma-jasmine โ€“ instaluje jaล›min, ktรณry jest zaleลผnym frameworkiem dla Karmy.

Krok 2) Nastฤ™pnym krokiem jest instalacja narzฤ™dzia wiersza poleceล„ karma. Jest to wymagane do wykonywania poleceล„ linii karmy. Narzฤ™dzie karma line zostanie uลผyte do zainicjowania ล›rodowiska karmy do testรณw.

Aby zainstalowaฤ‡ narzฤ™dzie wiersza poleceล„, wykonaj poniลผszy wiersz z poziomu wiersza poleceล„

npm install karma-cli

w ktรณrej,

  • karma-cli sล‚uลผy do instalowania interfejsu wiersza poleceล„ dla karmy, ktรณry bฤ™dzie uลผywany do zapisywania poleceล„ karmy w interfejsie wiersza poleceล„.
  • Konfiguracja frameworku Karma

    Nastฤ™pnym krokiem jest skonfigurowanie karmy, czego moลผna dokonaฤ‡ za pomocฤ… polecenia

    "karma โ€“init"

    Po wykonaniu powyลผszego kroku karma utworzy plik karma.conf.js. Plik prawdopodobnie bฤ™dzie wyglฤ…daล‚ jak fragment pokazany poniลผej

    files: [
      'Your application Name'/AngularJS/AngularJS.js',
      'Your application Name'/AngularJS-mocks/AngularJS-mocks.js',
      'lib/app.js',
      'tests/*.js'
    ]

    Powyลผsze pliki konfiguracyjne przekazujฤ… silnikowi wykonawczemu Karma nastฤ™pujฤ…ce informacje

    1. โ€žNazwa Twojej aplikacjiโ€ โ€“ Zostanie ono zastฤ…pione nazwฤ… Twojej aplikacji.
    2. "Nazwa Twojej aplikacji'/AngularJS/AngularJS.js' โ€“ To mรณwi karmie, ลผe Twoja aplikacja zaleลผy od podstawowych moduล‚รณw AngularJS
    3. โ€žNazwa Twojej aplikacjiโ€/AngularJS-mocks/AngularJS-mocks.jsโ€ โ€“ To mรณwi karmie, aby uลผyล‚a funkcjonalnoล›ci testรณw jednostkowych dla AngularJS z pliku Angular.JS-mocks.js.
    4. Wszystkie gล‚รณwne pliki aplikacji lub logiki biznesowej znajdujฤ… siฤ™ w folderze lib Twojej aplikacji.
    5. Folder testรณw bฤ™dzie zawieraล‚ wszystkie testy jednostkowe.

    Aby sprawdziฤ‡ czy karma dziaล‚a utwรณrz plik o nazwie Sample.js, umieล›ฤ‡ w nim poniลผszy kod i umieล›ฤ‡ go w katalogu test.

    describe('Sample test', function() {
      it('Condition is true', function() {
        expect('AngularJS').toBe('AngularJS');
      });
    });

    Powyลผszy kod ma nastฤ™pujฤ…ce aspekty

    1. Funkcja opisu sล‚uลผy do opisywania testu. W naszym przypadku do naszego testu nadajemy opis โ€žTest prรณbnyโ€.
    2. Funkcja โ€žitโ€ sล‚uลผy do nadania nazwy testowi. W naszym przypadku podajemy nazwฤ™ naszego testu jako โ€žWarunek jest prawdziwyโ€. Nazwa testu musi byฤ‡ zrozumiaล‚a.
    3. Kombinacja sล‚รณw kluczowych โ€žoczekiwaฤ‡โ€ i โ€žbyฤ‡โ€ okreล›la, jaka jest oczekiwana i rzeczywista wartoล›ฤ‡ wyniku testu. Jeล›li wartoล›ฤ‡ rzeczywista i oczekiwana sฤ… takie same, test zakoล„czy siฤ™ pomyล›lnie, w przeciwnym razie zakoล„czy siฤ™ niepowodzeniem.

    Po wykonaniu poniลผszego wiersza poleceล„ zostanie wykonany powyลผszy plik testowy

    KARMA start

    Poniลผsze dane wyjล›ciowe pochodzฤ… z IDE Webstorm w ktรณrym wykonano powyลผsze czynnoล›ci.

    Konfiguracja Frameworku Karma

    1. Dane wyjล›ciowe znajdujฤ… siฤ™ w eksploratorze Karmy Webstorm. To okno pokazuje wykonanie wszystkich testรณw zdefiniowanych w ramach karmy.
    2. Tutaj moลผesz zobaczyฤ‡, ลผe pokazany jest opis wykonanego testu, ktรณry jest โ€žTestem prรณbkiโ€.
    3. Nastฤ™pnie widaฤ‡, ลผe wykonywany jest sam test o nazwie โ€žWarunek jest prawdziwyโ€.
    4. Naleลผy pamiฤ™taฤ‡, ลผe obok wszystkich testรณw znajduje siฤ™ zielona ikona โ€žOKโ€, ktรณra symbolizuje pomyล›lne zakoล„czenie wszystkich testรณw.

    Testowanie kontrolerรณw AngularJS

    Struktura testowania karmy ma rรณwnieลผ funkcjฤ™ kompleksowego testowania kontrolerรณw. Obejmuje to testowanie obiektu $scope uลผywanego w kontrolerach.

    Spรณjrzmy na przykล‚ad, jak moลผemy to osiฤ…gnฤ…ฤ‡.

    W naszym przykล‚adzie

    Najpierw musielibyล›my zdefiniowaฤ‡ kontroler. Ten kontroler wykona poniลผsze kroki

    1. Utwรณrz zmiennฤ… ID i przypisz jej wartoล›ฤ‡ 5.
    2. Przypisz zmiennฤ… ID do obiektu $scope.

    Nasz test sprawdzi istnienie tego kontrolera, a takลผe sprawdzi, czy zmienna ID obiektu $scope jest ustawiona na 5.

    Najpierw musimy siฤ™ upewniฤ‡, ลผe speล‚nione sฤ… nastฤ™pujฤ…ce warunki wstฤ™pne

    Zainstaluj bibliotekฤ™ Angular.JS-mocks poprzez npm. Moลผna to zrobiฤ‡, wykonujฤ…c poniลผszy wiersz w wierszu poleceล„

    npm install Angular JS-mocks

    Nastฤ™pnie naleลผy zmodyfikowaฤ‡ plik karma.conf.js, aby upewniฤ‡ siฤ™, ลผe do testu zostanฤ… doล‚ฤ…czone odpowiednie pliki. Poniลผszy segment pokazuje tylko czฤ™ล›ฤ‡ plikรณw karma.conf.js, ktรณra wymaga modyfikacji

    files: ['lib/AngularJS.js','lib/AngularJS-mocks.js','lib/index.js','test/*.js']
    • Parametr โ€žplikiโ€ w zasadzie informuje Karmฤ™ o wszystkich plikach wymaganych do przeprowadzenia testรณw.
    • Do uruchomienia testรณw jednostkowych AngularJS wymagane sฤ… pliki AngularJS.js i AngularJS-mocks.js
    • Plik Index.js bฤ™dzie zawieraล‚ nasz kod dla kontrolera
    • Folder test bฤ™dzie zawieraล‚ wszystkie nasze testy AngularJS

    Poniลผej znajduje siฤ™ nasz kod Angular.JS, ktรณry zostanie zapisany jako plik Index.js w folderze testowym naszej aplikacji.

    Poniลผszy kod wykonuje nastฤ™pujฤ…ce czynnoล›ci

    1. Tworzenie Moduล‚ AngularJS o nazwie przykล‚adowa aplikacja
    2. Utwรณrz kontroler o nazwie AngularJSController
    3. Utwรณrz zmiennฤ… o nazwie ID, nadaj jej wartoล›ฤ‡ 5 i przypisz jฤ… do obiektu $scope
    var sampleApp = AngularJS.module('sampleApp',[]);
    sampleApp.controller('AngularJSController', function($scope) {
        $scope.ID =5;
    });

    Po pomyล›lnym wykonaniu powyลผszego kodu nastฤ™pnym krokiem bฤ™dzie utworzenie pliku Przypadek testowy aby upewniฤ‡ siฤ™, ลผe kod zostaล‚ napisany i wykonany poprawnie.

    Kod naszego testu bฤ™dzie taki, jak pokazano poniลผej.

    Kod bฤ™dzie w osobnym pliku o nazwie ControllerTest.js, ktรณry zostanie umieszczony w folderze test. Poniลผszy kod wykonuje nastฤ™pujฤ…ce kluczowe czynnoล›ci

    1. beforeEach funkcja โ€“ Ta funkcja sล‚uลผy do zaล‚adowania naszego moduล‚u AngularJS.JS o nazwie โ€žsampleAppโ€ przed uruchomieniem testowym. Zauwaลผ, ลผe jest to nazwa moduล‚u w pliku Index.js.
    2. Obiekt $controller tworzony jest jako obiekt makiety dla kontrolera โ€žAngular JSControllerโ€, ktรณry jest zdefiniowany w naszym pliku Index.js. W kaลผdym rodzaju testรณw jednostkowych obiekt prรณbny reprezentuje obiekt fikcyjny, ktรณry faktycznie bฤ™dzie uลผywany do testowania. Ten prรณbny obiekt bฤ™dzie w rzeczywistoล›ci symulowaล‚ zachowanie naszego kontrolera.
    3. beforeEach(inject(function(_$controller_)) โ€“ Sล‚uลผy do wstrzykniฤ™cia prรณbnego obiektu w naszym teล›cie, tak aby zachowywaล‚ siฤ™ jak rzeczywisty kontroler.
    4. var $zakres = {}; To jest obiekt prรณbny tworzony dla obiektu $scope.
    5. var kontroler = $kontroler('AngularJSController', { $zakres: $zakres }); โ€“ Tutaj sprawdzamy istnienie kontrolera o nazwie โ€žAngular.JSControllerโ€. Tutaj przypisujemy rรณwnieลผ wszystkie zmienne z naszego obiektu $scope w naszym kontrolerze w pliku Index.js do obiektu $scope w naszym pliku testowym
    6. Na koniec porรณwnujemy $scope.ID z 5
    describe('AngularJSController', function() {
        beforeEach(module('sampleApp'));
    
        var $controller;
    
        beforeEach(inject(function(_$controller_){
                  $controller = _$controller_;
        }));
    
        describe('$scope.ID', function() {
            it('Check the scope object', function() {
                var $scope = {};
                var controller = $controller('AngularJSController', { $scope: $scope });
                expect($scope.ID).toEqual(5);
            });
        });
    });

    Powyลผszy test zostanie uruchomiony w przeglฤ…darce karmy i da taki sam wynik pozytywny, jak pokazano w poprzednim temacie.

    Testowanie dyrektyw AngularJS

    Struktura testowania karmy ma rรณwnieลผ funkcjฤ™ testowania niestandardowych dyrektyw. Obejmuje to szablony URL uลผywane w dyrektywach niestandardowych.

    Spรณjrzmy na przykล‚ad, jak moลผemy to osiฤ…gnฤ…ฤ‡.

    W naszym przykล‚adzie najpierw zdefiniujemy niestandardowฤ… dyrektywฤ™, ktรณra wykonuje nastฤ™pujฤ…ce czynnoล›ci

    1. Utwรณrz moduล‚ AngularJS o nazwie sampleApp
    2. Utwรณrz niestandardowฤ… dyrektywฤ™ o nazwie โ€“ Guru99
    3. Utwรณrz funkcjฤ™ zwracajฤ…cฤ… szablon ze znacznikiem nagล‚รณwka wyล›wietlajฤ…cym tekst โ€žTo jest testowanie AngularJSโ€.
    var sampleApp = AngularJS.module('sampleApp',[]);
    sampleApp.directive('Guru99', function () {
        return {
            restrict: 'E',
            replace: true,
            template: '<h1>This is AngularJS Testing</h1>'
        };
    });

    Po pomyล›lnym wykonaniu powyลผszego kodu nastฤ™pnym krokiem bฤ™dzie utworzenie przypadku testowego, aby upewniฤ‡ siฤ™, ลผe kod zostaล‚ napisany i wykonany poprawnie. Kod naszego testu bฤ™dzie taki, jak pokazano poniลผej

    Kod bฤ™dzie w osobnym pliku o nazwie DirectiveTest.js, ktรณry zostanie umieszczony w folderze test. Poniลผszy kod wykonuje nastฤ™pujฤ…ce kluczowe czynnoล›ci

    1. beforeEach funkcja โ€“ Ta funkcja sล‚uลผy do zaล‚adowania naszego moduล‚u Angular JS o nazwie โ€žsampleAppโ€ przed uruchomieniem testowym.
    2. Do kompilacji dyrektywy uลผywana jest usล‚uga $compile. Ta usล‚uga jest obowiฤ…zkowa i musi zostaฤ‡ zadeklarowana, aby Angular.JS mรณgล‚ jej uลผyฤ‡ do skompilowania naszej niestandardowej dyrektywy.
    3. $rootscope to podstawowy zakres dowolnej aplikacji AngularJS.JS. Obiekt $scope kontrolera widzieliล›my juลผ we wczeล›niejszych rozdziaล‚ach. Cรณลผ, obiekt $scope jest obiektem podrzฤ™dnym obiektu $rootscope. Powodem tej deklaracji jest to, ลผe wprowadzamy zmianฤ™ w rzeczywistym tagu HTML w DOM za pomocฤ… naszej niestandardowej dyrektywy. Dlatego musimy skorzystaฤ‡ z usล‚ugi $rootscope, ktรณra faktycznie nasล‚uchuje i wie, kiedy nastฤ…pi jakakolwiek zmiana z poziomu dokumentu HTML.
    4. element var = $kompiluj(โ€œ โ€) โ€“ Sล‚uลผy do sprawdzania, czy nasza dyrektywa zostaล‚a wstrzykniฤ™ta tak, jak powinna. Nazwa naszej niestandardowej dyrektywy to Guru99 i wiemy z naszego rozdziaล‚u o niestandardowych dyrektywach, ลผe kiedy dyrektywa zostanie wstrzykniฤ™ta do naszego kodu HTML, zostanie wstrzykniฤ™ta jako โ€ž '. Dlatego ta instrukcja jest uลผywana do sprawdzenia.
    5. oczekiwanie(element.html()).toContain(โ€œTo jest test AngularJSโ€) โ€“ sล‚uลผy do poinstruowania funkcji oczekiwania, ลผe โ€‹โ€‹powinna znaleลบฤ‡ element (w naszym przypadku znacznik div), ktรณry bฤ™dzie zawieraล‚ tekst w formacie internalHTML โ€žThis is Testowanie AngularJSโ€.
    describe('Unit testing directives', function() {
      var $compile,
          $rootScope;
       beforeEach(module('sampleApp'));
    
      beforeEach(inject(function(_$compile_, _$rootScope_){
        $compile = _$compile_;
        $rootScope = _$rootScope_;
     }));
    
     it('Check the directive', function() {
        // Compile a piece of HTML containing the directive
        var element = $compile("<ng-Guru99></ng-Guru99>")($rootScope);
        $rootScope.$digest();
        expect(element.html()).toContain("This is AngularJS Testing");
      });
    });

    Powyลผszy test zostanie uruchomiony w przeglฤ…darce karmy i da taki sam wynik pozytywny, jak pokazano w poprzednim temacie.

    Kompleksowe testowanie aplikacji AngularJS JS

    Framework do testowania karmy wraz ze frameworkiem o nazwie Protractor ma funkcjonalnoล›ฤ‡ kompleksowego testowania aplikacji internetowej.

    Zatem nie jest to tylko testowanie dyrektyw i kontrolerรณw, ale takลผe testowanie czegokolwiek innego, co moลผe pojawiฤ‡ siฤ™ na stronie HTML.

    Spรณjrzmy na przykล‚ad, jak moลผemy to osiฤ…gnฤ…ฤ‡.

    W naszym przykล‚adzie poniลผej bฤ™dziemy mieฤ‡ aplikacjฤ™ AngularJS, ktรณra tworzy tabelฤ™ danych za pomocฤ… dyrektywy ng-repeat.

    1. Najpierw tworzymy zmiennฤ… o nazwie โ€žsamouczekโ€ i przypisujemy jej kilka par klucz-wartoล›ฤ‡ w jednym kroku. Kaลผda para klucz-wartoล›ฤ‡ bฤ™dzie uลผywana jako dane podczas wyล›wietlania tabeli. Zmienna samouczka jest nastฤ™pnie przypisywana do obiektu zakresu, tak aby moลผna byล‚o uzyskaฤ‡ do niej dostฤ™p z naszego widoku.
    2. Dla kaลผdego wiersza danych w tabeli uลผywamy dyrektywy ng-repeat. Ta dyrektywa przechodzi przez kaลผdฤ… parฤ™ klucz-wartoล›ฤ‡ w obiekcie zakresu tutoriala przy uลผyciu zmiennej ptutor.
    3. Na koniec uลผywamy tag wraz z parami klucz-wartoล›ฤ‡ (ptutor.Name i ptutor.Description), aby wyล›wietliฤ‡ dane tabeli.
    <table >
                 <tr ng-repeat="ptutor in tutorial">
                       <td>{{ ptutor.Name }}</td>
    	               <td>{{ ptutor.Description }}</td>
                 </tr>
       </table>
    </div>
      <script type="text/javascript">
          var app = AngularJS.module('DemoApp', []);
            app.controller('DemoController', function($scope) {
               $scope.tutorial =[
                    {Name: "Controllers" , Description : "Controllers in action"},
                    {Name: "Models" , Description : "Models and binding data"},
    	            {Name: "Directives" , Description : "Flexibility of Directives"}
    			]   });

    Po pomyล›lnym wykonaniu powyลผszego kodu nastฤ™pnym krokiem bฤ™dzie utworzenie przypadku testowego, aby upewniฤ‡ siฤ™, ลผe kod zostaล‚ napisany i wykonany poprawnie. Kod naszego testu bฤ™dzie taki, jak pokazano poniลผej

    Nasz test tak naprawdฤ™ przetestuje dyrektywฤ™ ng-repeat i upewni siฤ™, ลผe zawiera ona 3 wiersze danych, tak jak powinno to wynikaฤ‡ z powyลผszego przykล‚adu.

    Najpierw musimy siฤ™ upewniฤ‡, ลผe speล‚nione sฤ… nastฤ™pujฤ…ce warunki wstฤ™pne

    Zainstaluj bibliotekฤ™ kฤ…tomierza za poล›rednictwem npm. Moลผna to zrobiฤ‡, wykonujฤ…c poniลผszy wiersz w wierszu poleceล„

    "npm install protractor"

    Kod naszego testu bฤ™dzie taki, jak pokazano poniลผej.

    Kod bฤ™dzie w osobnym pliku o nazwie CompleteTest.js, ktรณry zostanie umieszczony w folderze test. Poniลผszy kod wykonuje nastฤ™pujฤ…ce kluczowe rzeczy

    1. Funkcjฤ™ przeglฤ…darki zapewnia biblioteka kฤ…tomierza i zakล‚ada, ลผe โ€‹โ€‹nasza aplikacja AngularJS (z kodem pokazanym powyลผej) dziaล‚a na adresie URL naszej witryny โ€“ http://localhost:8080/Guru99/
    2. var list=element.all(by.repeater(ptutor in tutorial')); -Ta linia kodu faktycznie pobiera dyrektywฤ™ ng-repeat, ktรณra jest wypeล‚niana przez kod 'ptutor in tutorial'. Element i by.repeater to specjalne sล‚owa kluczowe dostarczane przez bibliotekฤ™ protractor, ktรณre pozwalajฤ… nam uzyskaฤ‡ szczegรณล‚y dyrektywy ng-repeat.
    3. oczekiwaฤ‡(list.liczba()).toEqual(3); โ€“ Na koniec uลผywamy funkcji oczekiwanie, aby sprawdziฤ‡, czy rzeczywiล›cie w wyniku dyrektywy ng-repeat rzeczywiล›cie zapeล‚niajฤ… siฤ™ 3 pozycje w naszej tabeli.
    Describe('Unit testing end to end', function() {
      beforeEach(function() {
    browser.get('http://localhost:8080/Guru99/');
    })
       it('Check the ng directive', function() {
          var list=element.all(by.repeater(ptutor in tutorial'));
          expect(list.count()).toEqual(3);  }); });

    Powyลผszy test zostanie uruchomiony w przeglฤ…darce karmy i da taki sam wynik pozytywny, jak pokazano w poprzednim temacie.

    Podsumowanie

    • Testowanie w AngularJS odbywa siฤ™ przy uลผyciu frameworku karma, ktรณry zostaล‚ opracowany przez samo Google.
    • Framework karma instaluje siฤ™ za pomocฤ… menedลผera pakietรณw wฤ™zล‚รณw. Kluczowymi moduล‚ami, ktรณre naleลผy zainstalowaฤ‡ w celu przeprowadzenia podstawowych testรณw, sฤ… karma, karma-chrome-launcher, karma-jasmine i karma-cli.
    • Testy sฤ… zapisywane w oddzielnych plikach js, zwykle przechowywanych w folderze testowym aplikacji. Lokalizacja tych plikรณw testowych musi byฤ‡ podana w specjalnym pliku konfiguracyjnym o nazwie karma.conf.js. Karma uลผywa tego pliku konfiguracyjnego podczas wykonywania wszystkich testรณw.
    • Karmy moลผna uลผywaฤ‡ rรณwnieลผ do testowania kontrolerรณw i niestandardowych dyrektyw.
    • Aby mรณc kompleksowo testowaฤ‡ sieฤ‡, naleลผy zainstalowaฤ‡ innฤ… platformฤ™ zwanฤ… kฤ…tomierzem za poล›rednictwem wฤ™zล‚a, menedลผera pakietรณw. Ten framework udostฤ™pnia specjalne metody, ktรณrych moลผna uลผyฤ‡ do testowania wszystkich elementรณw strony HTML.

    Podsumuj ten post nastฤ™pujฤ…co: