2015-11-17 12 views
8

Jednostki testujące dyrektywę kątową nie są zbyt trudne, ale okazało się, że są na to różne sposoby.Jak przeprowadzić test jednostkowy dyrektywy kątowej

Dla celów niniejszego postu, pozwala zakładać następującą dyrektywę

angular.module('myApp') 
    .directive('barFoo', function() { 
     return { 
      restrict: 'E', 
      scope: true, 
      template: '<p ng-click="toggle()"><span ng-hide="active">Bar Foo</span></p>', 
      controller: function ($element, $scope) { 
       this.toggle() { 
        this.active = !this.active; 
       } 
      } 
     }; 
    }); 

Teraz mogę myśleć dwa sposoby testów jednostkowych tej

Metoda 1:

describe('Directive: barFoo', function() { 
    ... 
    beforeEach(inject(function($rootScope, barFooDirective) { 
     element = angular.element('<bar-foo></bar-foo>'); 
     scope = $rootScope.$new(); 
     controller = new barFooDirective[0].controller(element, scope); 
    })); 

    it('should be visible when toggled', function() { 
     controller.toggle(); 
     expect(controller.active).toBeTruthy(); 
    }); 
}); 

metoda 2 :

beforeEach(inject(function ($compile, $rootScope) { 
    element = angular.element('<bar-foo></bar-foo>'); 
    scope = $rootScope.$new(); 
    $compile(element)(scope); 
    scope.$digest(); 
})); 

it ('should be visible when toggled', function() { 
    element.click(); 
    expect(element.find('span')).not.toHaveClass('ng-hide'); 
}); 

Więc jestem ciekawy, co pro i minusy mają obie metody i która jest najbardziej wytrzymała?

+1

Zakładam, że kliknięcie na elemencie w testowanie jednostkowe jest jak badanie metod kontrolera w kątomierz – Appeiron

Odpowiedz

1

Co lubię robić, to tworzyć opowieści o moim teście, jak ten dummy przykład.

'use strict'; 

describe('app controller', function() { 

    var scope; 

    ... 

    beforeEach(angular.mock.module('MyModule')); 

    it('should have properties defined', function() { 

    expect(scope.user).toEqual(user); 
    ...  

    }); 

    it('should have getFaqUrl method', function() { 

    expect(scope.getFaqUrl).toEqual(refdataService.getFaqUrl); 

    }); 

    it('should signout and delete user data from local storage', function() { 

    ... 

    }); 

}); 

Więc myślę, że po prostu nie podać go w drugim przykładzie, ale w przypadku, gdy nie, należy opisać obudowę zawsze podczas testów, tylko dobre praktyki.

Jeśli chodzi o sam test, radziłbym unikać stosowania metody, w której wyraźnie wywołuje się zakres. $ Digest(), szczególnie, że nie jest to konieczne do celów testu.

Wkrótce pójdę do metody 1.

+0

dziękuję za odpowiedź. Czy mógłbyś zaktualizować swój post z przykładem, jak wygląda twój test w połączeniu z historią? –

+0

Przepraszam, że tylko edytowałem teraz, szukałem w jakimś manekinowym przykładzie, ponieważ nie mogę udostępnić kodu prod ... ale to wyjaśnić, co myślałem o shorty, i dla każdego kontrolera, dodając historię jak zestawy – desicne

1

znajdę pierwsza metoda bardziej „poprawne”, ponieważ nie robi zależy od przypadku kliknięcia. Wierzę, że jeśli chcesz przetestować kliknięcie elementu i jego efekty powinieneś użyć kątomierza i użyć jaśminu tylko do testów jednostkowych. W ten sposób będziesz miał ładną separację między testami jednostkowymi a testami interfejsu użytkownika.

Sprawia również, że test jest łatwiejszy w utrzymaniu. na przykład Jeśli zdecydujesz się zwolnić toggle po najechaniu kursorem, a nie po kliknięciu w drugą metodę, będziesz musiał również zaktualizować testy.

+0

Zakładasz, że pierwsza metoda, ponieważ druga metoda robi rzecz '.click()'? –

+0

@JeanlucaScaljeri yap, miałem na myśli pierwszy. Naprawiłem to. dzięki. –

+0

Testy jednostkowe utworzone dla metod testowania zwrotów i wpływu na testy danych i zachowań (kliknięcia itp.) Są używane do testowania rzeczywistych interakcji użytkownika. – Appeiron

2

Oto jak przetestować dyrektywę angularjs:

describe('Directive: barFoo', function() { 
 
    var createElement, element, parentScope, directiveScope; 
 
    
 
    beforeEach(module('myApp')); 
 

 
    beforeEach(inject(function($injector) { 
 
    var $compile = $injector.get('$compile'); 
 
    var $rootScope = $injector.get('$rootScope'), 
 

 
    parentScope = $rootScope.$new(); 
 
    parentScope.paramXyz = ... <-- prepare whatever is expected from parent scope 
 

 
    createElement = function() { 
 
     element = $compile('<bar-foo></bar-foo>')(parentScope); 
 
     directiveScope = element.isolateScope(); 
 
     parentScope.$digest(); 
 
     $httpBackend.flush(); <-- if needed 
 
    }; 
 
    })); 
 

 

 
    it('should do XYZ', function() { 
 
    parentScope.xyz = ... <-- optionnal : adjust scope according to your test 
 
    createElement(); 
 

 
    expect(...) <-- whatever, examples : 
 

 
    var submitButton = element.find('button[type="submit"]'); 
 
    expect(submitButton).to.have.value('Validate'); 
 
    expect(submitButton).to.be.disabled; 
 
    submitButton.click(); 
 
    });

+0

To podejście jest mniej więcej takie samo jak w przypadku metody 2. Czy możesz podać argumentację, dlaczego jest to lepsze niż metoda 1? –

+0

@JeanlucaScaljeri w metodzie 1) musisz stworzyć kontroler ręcznie iw metodzie 2) masz dodatkowy krok.Przykład, który proponuję (wzięty z naszych rzeczywistych testów w mojej firmie) wyświetla również strukturę testową, która pozwala na łatwiejsze testowanie, zezwalając na dodatkowe wywołania * przed * tworzenie instancji dyrektywy za pomocą 'createElement()'. Zwróć także uwagę na wyraźne oddzielenie zakresu nadrzędnego od podrzędnego. – Offirmo

+0

Podoba mi się to podejście. Jestem nowy w testowaniu dyrektyw. Zastanawiam się, jak rozpoznać jedną konkretną dyrektywę do przetestowania? Czy to konieczne? – Winnemucca

Powiązane problemy