Material‎ > ‎Software‎ > ‎Angular JS‎ > ‎

AngularJS - Testing



Automated JS Test Runner - Sitio oficial

Primer ejemplo: testeando el conversor

Basándonos en este tutorial, definimos tests unitarios para el conversor.

Dependencias de desarrollo

Debemos instalar las dependencias de desarrollo, esto lo podemos hacer en cualquier proyecto mediante la siguiente instrucción:


npm install karma karma-jasmine jasmine-core karma-chrome-launcher angular-mocks --save-dev
npm install -g karma-cli


Esto generará dependencias en el package.json con versiones similares a:
{
"name": "conversor-ui-angular",
"description": "Conversor AngularJS",
"author": "",
"dependencies": {
...
},
"devDependencies": {
"angular-mocks": "^1.6.4",
"jasmine-core": "^2.6.4",
"karma": "^1.7.0",
"karma-chrome-launcher": "^2.1.1",
"karma-jasmine": "^1.1.0"
}
}


Definición de la configuración de Karma

Karma necesita generar un archivo de configuración, de manera similar a lo que npm nos pide:

karma init

A cada pregunta contestamos el valor default, solo que debemos pedir evite instalar el plugin Require. Esto genera en nuestro directorio raíz un archivo karma.conf.js

Definición de archivos de tests

En algún directorio de nuestro proyecto debemos generar los archivos spec correspondientes. Por ejemplo en nuestro caso elegimos la ruta
"./js/tests/" y el archivo elegido es conversor.spec.js.

Escribimos un test sencillo, que instancia dos conversores
  • al primero lo dejamos en estado inicial
  • al segundo le pedimos que convierta 100 millas a kilómetros
Como resultado tenemos 3 casos de prueba:
  • un conversor inicial tiene 0 millas
  • un conversor inicial tiene ' Ingrese kilómetros ' como valor en kilómetros
  • un conversor con 100 millas al que le peidmos que convierte queda con la cantidad equivalente en kilómetros
Vemos cómo se resuelve esto

describe('Tests para el conversor - objeto de dominio', () => {
const conversor = new Conversor()
const conversorInicial = new Conversor()

beforeEach( () => {
conversor.millas = 100
conversor.convertir()
})

it('Convertir 100 millas debe dar 169.0344 kilometros', () => {
expect(160.934).toBe(conversor.kilometros)
})

it('Un conversor inicial no tiene kilometros definidos', () => {
expect(' <ingrese millas> ').toBe(conversorInicial.kilometros)
})

it('Un conversor inicial tiene 0 millas definidas', () => {
expect(0).toBe(conversorInicial.millas)
})

})

js/tests/conversor.spec.js

Actualización de la configuración de Karma

Claro, para que esto funcione debemos actualizar la configuración de Karma de manera de
  • decirle dónde están nuestros archvos spec
  • y dónde están las definiciones que necesitamos (por ejemplo, para poder instanciar un conversor)
// Karma configuration
// Generated on Fri Jun 23 2017 10:49:28 GMT-0300 (ART)

module.exports = function(config) {
config.set({

// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',


// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],


// list of files / patterns to load in the browser
files: [
'./js/conversor.js',
'./js/tests/*.js'
],

karma.conf.js (directorio raíz)

Ejecución de tests con Karma

Desde una terminal (git bash o la terminal de Linux) ejecutamos 


fernando@fernando-laptop ~/workspace/angular-2017/eg-conversor-angular-es6 $ kma start
23 06 2017 11:19:37.781:WARN [karma]: No captured browser, open http://localhost:9876/
23 06 2017 11:19:37.799:INFO [karma]: Karma v1.7.0 server started at http://0.0.0.0:9876/
23 06 2017 11:19:37.801:INFO [launcher]: Launching browser Chrome with unlimited concurrency
23 06 2017 11:19:38.076:INFO [launcher]: Starting browser Chrome
23 06 2017 11:19:39.470:INFO [Chrome 55.0.2883 (Linux 0.0.0)]: Connected on socket ibzq_JSiCFp8XexfAAAA with id 33183260
Chrome 55.0.2883 (Linux 0.0.0): Executed 3 of 3 SUCCESS (0.02 secs / 0.018 secs)


Aquí vemos que los 3 tests ejecutaron correctamente (SUCCESS). Si modificamos el valor esperado en la conversión, veremos que eso se refleja tan pronto grabemos el archivo de test:

23 06 2017 11:21:57.347:INFO [watcher]: Changed file "/home/fernando/workspace/angular-2017/eg-conversor-angular-es6/js/tests/conversor.spec.js".
Chrome 55.0.2883 (Linux 0.0.0) Tests para el conversor - objeto de dominio Convertir 100 millas debe dar 169.0344 kilometros FAILED
Expected 160.2934 to be 160.934.
   at Object.it (js/tests/conversor.spec.js:11:26)
Chrome 55.0.2883 (Linux 0.0.0): Executed 3 of 3 (1 FAILED) (0.021 secs / 0.011 secs)

Esto puede descargarse en el ejemplo del conversor.

Segundo ejemplo: testeando el controller de apuestas

Inicialización de Karma en nuestro proyecto

Basándonos en la segunda parte del tutorial,

Repetimos los pasos para instalar Karma en nuestro proyecto


npm
install karma karma-jasmine jasmine-core karma-chrome-launcher angular-mocks --save-dev
npm install -g karma-cli
karma init


Tests del controller

Nuestro controller de apuestas 
  • conoce una apuesta
  • tiene un método apostar que termina delegando en la apuesta pero también sabe manejar los errores, a través de una variable errorMessage que guarda el mensaje de error. También recibe una referencia al form HTML para marcarlo como inválido. Cuando la apuesta se hace, el controller tiene una variable resultado donde el usuario puede ver si ganó o perdió
Con esto que sabemos podemos generar algunos tests:
  • el controller que vamos a instanciar será un mock
  • podemos simular la carga de datos en la pantalla pasándole una apuesta incompleta o bien una apuesta válida
    • si la apuesta es inválida debe haber algo en la variable errorMessage
    • si la apuesta es válida, no sabemos si el usuario ganará o perderá, pero sí que debe haber algo en la variable resultado
Vemos la implementación:

describe('ApuestaController', () => {
let apuestaController
let apuestaValida
const apuestasForm = {}

beforeEach(angular.mock.module('ui.bootstrap'))
beforeEach(angular.mock.module('apuestasApp'))

// Inject the $controller service to create instances of the controller (UsersController) we want to test
beforeEach(inject(($controller) => {
apuestaController = $controller('apuestasCtrl', {})
apuestaValida = new Apuesta()
apuestaValida.fecha = new Date()
apuestaValida.tipoApuesta = new Pleno()
apuestaValida.valorApostado = 5
apuestaValida.monto = 150
}))

// Verificamos que existe el controller
it('should be defined', () => {
expect(apuestaController).toBeDefined()
})

it('si no ingresa nada no debe permitir apostar', () => {
apuestaController.apostar(apuestasForm)
expect('Debe ingresar tipo de apuesta').toBe(apuestaController.errorMessage)
})

it('si no ingresa nada el formulario queda invalido', () => {
apuestaController.apostar(apuestasForm)
expect(true).toBe(apuestasForm.$invalid)
})

it('si no ingresa valores no debe permitir apostar', () => {
apuestaController.apostar(apuestasForm)
expect('Debe ingresar tipo de apuesta').toBe(apuestaController.errorMessage)
})

it('no se puede apostar una fecha anterior a la de hoy', () => {
const fechaVieja = new Date(2011, 4, 4)
apuestaController.apuesta.fecha = fechaVieja
apuestaController.apostar({})
expect('Debe ingresar una fecha actual o posterior al día de hoy').toBe(apuestaController.errorMessage)
})
it('una apuesta valida no da error', () => {
apuestaController.apuesta = apuestaValida
apuestaController.apostar({})
expect('').toBe(apuestaController.errorMessage)
})

it('una apuesta valida produce algun resultado', () => {
apuestaController.apuesta = apuestaValida
apuestaController.apostar({})
expect('').not.toBe(apuestaController.resultado)
})

})

/tests/apuestas.spec.js

Archivo de configuración de Karma

El archivo de configuración de karma debe referenciar no solo a los objetos de dominio, sino también a los de angular y sus mocks:

// Karma configuration
// Generated on Fri Jun 23 2017 17:56:23 GMT-0300 (ART)

module.exports = function(config) {
config.set({

// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',


// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],


// list of files / patterns to load in the browser
files: [
'./node_modules/angular/angular.js',
'./node_modules/angular-ui-router/release/angular-ui-router.js',
'./node_modules/angular-mocks/angular-mocks.js',
'./node_modules/angular-ui-bootstrap/ui-bootstrap-tpls.js',
'./js/domain/resultado.js',
'./js/domain/apuesta.js',
'./js/controllers/apuesta.js',
'./js/app.js',
'./tests/*.js'
],


// list of files to exclude
exclude: [
],


// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
},


// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],


// web server port
port: 9876,


// enable / disable colors in the output (reporters and logs)
colors: true,


// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,


// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,


// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome'],


// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,

// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity
})
}

./karma-conf.js

Solo es necesario modificr la configuración de files, el resto son valores por defecto.

fernando@fernando-laptop ~/workspace/angular-2017/eg-apuestas-angular-es6 $ karma start
26 06 2017 08:11:13.039:WARN [watcher]: Pattern "/home/fernando/workspace/angular-2017/eg-apuestas-angular-es6/node_modules/angular-ui-router/release/angular-ui-router.js" does not match any file.
26 06 2017 08:11:13.185:WARN [karma]: No captured browser, open http://localhost:9876/
26 06 2017 08:11:13.199:INFO [karma]: Karma v1.7.0 server started at http://0.0.0.0:9876/
26 06 2017 08:11:13.200:INFO [launcher]: Launching browser Chrome with unlimited concurrency
26 06 2017 08:11:13.245:INFO [launcher]: Starting browser Chrome
26 06 2017 08:11:14.093:INFO [Chrome 55.0.2883 (Linux 0.0.0)]: Connected on socket 7u-v1W32PA25hC9rAAAA with id 4790145
Chrome 55.0.2883 (Linux 0.0.0): Executed 7 of 7 SUCCESS (0.119 secs / 0.109 secs)

Jasmine permite bajo una sintaxis simple implementar la lógica de tests en un lenguaje natural orientado a BDD - Sitio oficial

Otros frameworks de testing



E2E (end-to-end) test framework for AngularJS applications.
Protractor corre tests, emulando ser un usuario real en un navegador web realizando acciones sobre tu aplicación web - Sitio oficial
Comments