niedziela, 24 lutego 2013

Jasmine i testy jednostkowe w Javascript

Do tej pory testy jednostkowe dla javascriptu były dla mnie trochę jak YETI - niby tu i tam się o nich mówi ale trudno mi było znaleźć dowód na ich istnienie. Można oczywiście użyć Selenium i tak też zrobiliśmy ale musiało, poprostu musiało istnieć "lżejsze" rozwiązanie...

Jasmine

No i znalazło się. Jasmine to Javascript napisany do testowania Javascriptu i wio :

1. Pliki źródłowe oraz przykłady zastosowań biblioteki Jasmine można znaleźć tutaj --> http://pivotal.github.com/jasmine/.

2. Generalnie jedyny sposób jaki znalazłem na testowanie zmian w drzewie DOM to odpalenie testów w ramach samej strony. Poniższy kod odpala testy tylko jeśli dołączony jest określony parametr, którego nazwę określimy wcześniej. Czy powinniśmy z tym kodem iść na produkcję? - a dlaczego nie!

 <html>  
   <head>  
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
     <title>Home</title>  
          <link rel="stylesheet" type="text/css" href="/resources/jasmine/jasmine.css" />  
          <script type="text/javascript" src="/resources/jquery.js"></script>  
          <script type="text/javascript" src="/resources/example.js"></script>  
           <c:if test="${not empty param.tests}">  
                <script type="text/javascript" src="/resources/jasmine/jasmine.js"></script>  
                <script type="text/javascript" src="/resources/jasmine/jasmine-html.js"></script>  
                <script type="text/javascript" src="/resources/tests.js"></script>  
                <script type="text/javascript" src="/resources/runJasmine.js"></script>  
            </c:if>  
   </head>  
   <body>  
        <div id="result"></div>  
        <div id="clickMe">Click me</div>  
   </body>  
 </html>  

3. Możemy się nawet pobawić w TDD - tworzymy pierwszy test :

 describe("A suite", function() {  
  it("has a blue background after click", function() {  
   //given  
       var clickMe=$($("#clickMe"));  
      //when  
      clickMe.click();  
      //then  
      expect(clickMe.css("background-color")).toBe("rgb(0, 0, 255)");  
  });  
 });  
Który oczywiście nie przechodzi :

4. Implementujemy funkcję :

 $(document).ready(function() {  
      $("#clickMe").click(function() {  
           $(this).css("background-color", "blue");  
      });  
 });  
I działa :



Możemy sobie teraz zmieniać, ciąć i modyfikować javascript bez bólu, że znowu ni z ch.. ni z owego wszystko przestanie działać. (i tak przestanie ale teraz przynajmniej dokładnie kontrolujemy co psujemy)

Da się? Da się!.

A co z Ajaxem

A co jeśli chcemy przetestować wywołanie asynchroniczne? Też nie ma z tym problemu.
1. Kod na serwerze :

 @RequestMapping(value = "/add", produces = "application/json", method = GET)  
      public @ResponseBody  
      Integer add(@RequestParam Integer firstNumber,  
                @RequestParam Integer secondNumber) throws IOException {  
           return firstNumber + secondNumber;  
      }  

2. W teście trzeba dodać trochę rzeźby aby upewnić się, że wywołanie asynchroniczne się zakończyło. Funkcje runs oraz waitsFor są z Jasmine :

  it("adding two positive numbers uusing ajax", function() {  
        //given  
            var firstNumber=1;  
            var secondNumber=2;  
           //when  
             runs(function() {  
                 add(firstNumber,secondNumber);  
            });  
            waitsFor(function() {  
                 var result=$("#result").text();  
              return result.length>0;  
            }, "Async call to long", 1000);  
           //then  
             runs(function() {  
                 expect($("#result").text()).toBe('3');  
            });  
       });  

3. Implementacja :

 $.get("add", {firstNumber : first,secondNumber : second},  
           function(data) {  
           $("#result").text(data);  
      });  

Ogólna ocena

Moja produktywność pracy z Javascriptem skoczyła o jakieś 69% gdyż już nie trzeba się przeklikiwać przez wszystkie przypadki użycia interfejsu po każdej zmianie w skrypcie. Biblioteka godna polecenia.

Brak komentarzy:

Prześlij komentarz