JoLuGaMa Blog

Amante de la tecnología y las cosas bien hechas

Jasmine

Framework de testeo javascript

Un ejemplo de cómo hacer pruebas unitarias AngularJS con Yeoman a través de Grunt.

Dejo colgado el proyecto en github PruebasAngularJs en el que, a través de ejemplos, muestro el enorme potencial de AngularJS.

Si no sabes de Yeoman, antes mira el post de Yeoman - Agilización del proceso de inicio del desarrollo web

En este ejemplo concreto, tomaremos del menú la opción Lista. En ella se muestra los primeros pasos en AngularJs, con directivas ng-repeat, ng-click, ng-blur, el uso de $scope, así como crear un servicio y unirlo al controller. Después pasaremos para producción el proyecto.

Pasos a seguir

Nos servimos del api AngularJs generator

  • Creación del proyecto
  • 1
    2
    3
    4
    5
    
     yo angular
     npm install
     yo angular:route lista  //Creación de la vista y controlador lista 
     yo angular:service vocabularioIngles //donde se aloja los datos que se graban en localStorage  
     
    
  • Instalación de dependencias
  • Archivos a mirar:
    • bower.json: mantener la lista de dependencias que va a usar esta aplicación
    • Gruntfile.js: ver tutorial Grunt
    • Karma.conf.js: dentro de la carpeta test. Para pruebas unitarias en el functionamiento correcto de los módulos.
    • Directorio node_modules: contiene los módulos de nodeJs, que tienen que estar definidos en el archivo Package.json(raiz)
    Si se quiere que los items sean ordenables, que los datos se guarden en localStorage, y otras cualidades, se requiere instalar módulos.
    1
    2
    3
    
     bower install --save angular-ui-sortable jquery-ui   //para items ordenables
     bower install --save angular-local-storage
     
    
    Si tenemos grunt serve abierto, lo cerramos y verificamos que está cargado los enlaces de los script en index.html. Por defecto Yeoman debe hacerlo.
    1
    2
    3
    4
    
     <script src="bower_components/jquery-ui/jquery-ui.js"></script>
      <script src="bower_components/angular-ui-sortable/sortable.js"></script>
      <script src="bower_components/angular-local-storage/dist/angular-local-storage.js"></script>
      
    

    Tenemos que cargarlo de nuestra aplicación. Para ello hay que actualizar las definiciones del modulo angular, dentro de script/app.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
       .module('pruebasAngularApp', [
      'ngAnimate',
      'ngCookies',
      'ngResource',
      'ngRoute',
      'ngSanitize',
      'ngTouch',
      'ui.sortable',
      'LocalStorageModule'
      ])
      .config(['localStorageServiceProvider', function(localStorageServiceProvider){
          localStorageServiceProvider.setPrefix('pruebasA');
      }])
      
    
  • Test unitarios, en la carpeta test/spec/controllers, para el ejemplo ver lista.js
  • Antes de ver el código conviene ver el tutorial de la página oficial
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    
       describe('comprobando vocIngles:', function() {
          it('vocIngles debe tener más de 100 lineas', function () {
              expect(scope.vocIngles.length).toBeGreaterThan(100);
              console.log('scope.vocIngles.length: ' + scope.vocIngles.length);
              aleatorio=(Math.floor(Math.random()*scope.vocIngles.length));
          });
          it('Debe tener los objectos I T N L P R', function () {
              expect(scope.vocIngles[0].I).toBeDefined(); //id
              expect(scope.vocIngles[0].T).toBeDefined(); //tipo
              expect(scope.vocIngles[0].N).toBeDefined(); //nivel
              expect(scope.vocIngles[0].L).toBeDefined(); //lista
              expect(scope.vocIngles[0].P).toBeDefined(); //pregunta
              expect(scope.vocIngles[0].R).toBeDefined(); //respuesta
          });
    
          it('Ejemplo aleatorio:', function () {
              var t=scope.vocIngles[aleatorio];
              expect(t.I).toEqual(jasmine.any(Number));
              expect(t.T).toEqual(jasmine.any(String));
              expect(t.N).toEqual(jasmine.any(String));
              expect(t.L).toEqual(jasmine.any(String));
              expect(t.P).toEqual(jasmine.any(String));
              expect(t.R).toEqual(jasmine.any(String));
              console.log('ID:' + t.I + ' Tipo:' + t.T + ' Nivel:' + t.N + ' Lista:' + t.L + ' Pregunta:' + t.P + ' Respuesta:' + t.R);
          });
      });
    
    
      describe('añadiendo y borrando a vocIngles', function() {
          beforeEach(function() {
              scope.lineaVocabulario={};
              scope.lineaVocabulario.I=(scope.vocIngles[scope.vocIngles.length-1].I)+1;
              scope.lineaVocabulario.T='V';
              scope.lineaVocabulario.N='5';
              scope.lineaVocabulario.L='lista de prueba';
              scope.lineaVocabulario.P='holaaaaaaaaaaaaa';
              scope.lineaVocabulario.R='helloooooooooooo';
          });
          it('añadiendo',function() {
              scope.anadirVocabulario();
              console.log('Añadido vocabulario. ahora hay:' + scope.vocIngles.length + ' en total');
          });
          it('borrando', function(){
              scope.lineaVocabulario.I=40; //asigno al ngmodel del input ID el valor del que he creado.
              scope.borrarVocabulario();
              console.log('ha sido borrado. ahora hay:' + scope.vocIngles.length);
              scope.lineaVocabulario.I=41;
              scope.borrarVocabulario();
              console.log('ha sido borrado. ahora hay:' + scope.vocIngles.length);
              scope.lineaVocabulario.I=42;
              scope.borrarVocabulario();
              console.log('ha sido borrado. ahora hay:' + scope.vocIngles.length);
              scope.lineaVocabulario.I=43;
              scope.borrarVocabulario();
              console.log('ha sido borrado. ahora hay:' + scope.vocIngles.length);
          });
      });
      
    
  • Paso a producción, donde los script se comprueban, se comprimen y se unen, igual con los css. Si todo sale bien, en la carpeta dist estará disponible
  • 1
    2
    
     grunt
     
    
    Un dato a tener en cuenta es que Angular, al usar ajax, y si se intenta ejecutar desde local, chrome tiene protección y no lo abre. Pantalla blanca. Para el resto de navegadores como Firefox funciona perfectamente.

Comentarios