Escribir pruebas unitarias nos ayudará a reducir de forma significativa los errores que puedan llegar a producción, en este articulo vamos a ver como empezar a utilizar el conjunto de herramientas que Angular nos provee para realizar pruebas.
Angular Testing Framework.
Desde la versión de Angular 2 en adelante Angular provee un conjunto de herramientas para poder preparar las pruebas unitarias y de esta manera podemos escribir pruebas fácilmente para los artefactos de Angular / Ionic, como componentes, directivas, pipes, providers etc.
Cuando iniciamos un proyecto con Angular CLI al momento de crear el proyecto con ng new nombre-proyecto
, nos entrega un proyecto ya preparado para ejecutar y escribir pruebas unitarias con Karma y Jasmine.
¿ Que es Karma ?
Karma es el encargado de correr todas las pruebas unitarias que escribamos y como resultado nos da un reporte que nos muestra las pruebas que pasaron y las pruebas que fallaron. En la mayoría de veces para ejecutar las pruebas unitarias lanza un navegador para correr las pruebas unitarias. Ver mas aquí
¿ Que es Jasmine ?
Jasmine es un framework que nos ayudará a escribir pruebas unitarias y se integra fácilmente con Angular.
Jasmine tiene varias herramientas que nos ayuda a escribir nuestras pruebas unitarias. Y vamos a ver las características más importantes, escribiendo pruebas para este modelo:
$ng g class models/person.model.ts
src/models/person.model.ts
export class Person {
protected _name: string;
protected _lastName: string;
protected _id: number;
constructor(data: any) {
if (data.hasOwnProperty('name')) {
this._name = data.name;
}
if (data.hasOwnProperty('lastName')) {
this._lastName = data.lastName;
}
if (data.hasOwnProperty('id')) {
this._id = data.id;
}
}
get name(): string {
return this._name;
}
get lastName(): string {
return this._lastName;
}
get id(): number {
return this._id;
}
}
Vamos a usar a la clase Person
y sobre este modelo vamos a escribir pruebas unitarias con Jasmine, revisemos un poco este modelo:
- Tiene con
constructor
que recibe un objeto. - Tiene varios
get
que nos devolvera los valores de cada atributo.
Ahora vamos a ponernos manos a la obra y ver las partes clave sobre Jasmine:
Describe:
La sentencia describe
se usa para poder agrupar un conjunto de pruebas, donde podemos escribir pruebas unitarias a una clase y luego agrupar pruebas por cada método de la clase así:
describe("Test for Person", ()=>{
describe("Test for Person with data", ()=>{
});
describe("Test for Person without data", ()=>{
})
})
It
La sentencia it
, define cada uno de los casos de prueba que vamos escribir y estarán dentro de cada describe
. Cada uno de los it
debe evaluar un caso de prueba en particular. Por ejemplo:
src/models/person.model.spec.ts
describe("Test for Person", ()=>{
describe("Test for Person with data", ()=>{
it("should be defined", ()=>{
//CODE
})
})
describe("Test for Person without data", ()=>{
it("shouldn't be defined", ()=>{
//CODE
})
})
})
BeforeEach:
La sentencia beforeEach
la podemos usar para no repetir código, todo lo que este dentro de la sentencia beforeEach
se ejecuta por cada describe
describe("Test for Person", ()=>{
beforeEach(()=>{
//code for each it
})
describe("Test for Person with data", ()=>{
})
describe("Test for Person without data", ()=>{
})
})
Expect
La sentencia expect
nos sirve para verificar cualquier comportamiento de nuestro código con lo que esperamos como resultado, por ejemplo:
expect(6+6).toEqual(12)
expect(1 === 1).toBeThuthy()
expect(null).toBeNull()
expect("Test").toEqual("Test")
Si miramos cada uno de los ejemplos estamos usando algunos verificadores de Jasmine en donde podemos verificar una variable contra una de las utilidades de Jasmine. Jasmine tiene varios muy útiles, puedes encontrarlos todos en la documentación oficial aquí.
Ahora podemos seguir con nuestro ejemplo y escribir cada unas de las verificaciones:
src/models/person.model.spec.ts
import { Person } from './person.model';
describe('Test for person', () => {
describe('Test for Person with data', () => {
it('should be defined', () => {
const person = new Person({name: 'Jhon', lastName: 'Doe', id: 24});
expect(person).toBeDefined();
expect(person.name).toEqual('Jhon');
expect(person.lastName).toEqual('Doe');
expect(person.id).toEqual(24);
});
});
describe('Test for Person without data', () => {
it('should not be defined', () => {
const person = new Person({});
expect(person).toBeDefined();
expect(person.name).toBeUndefined();
expect(person.lastName).toBeUndefined();
expect(person.id).toBeUndefined();
});
});
});
¿ Te gusta este articulo ? No te pierdas ninguna actualización uniendote al newsletter.
Ahora vamos a correr nuestras pruebas pruebas con el comando ng test
en la terminal y miremos el reporte que nos genera:
Podemos ver que ahora las nuevas pruebas que hemos agregado pasan correctamente con los valores esperados y nos aseguran que en una futura refactorización
no vayamos a quebrar nada.
Esto es todo, hasta un proximo post :)
Recuerda:
Si quieres ejecutar este demo en tu computadora, debes tener el entorno de ionic instalado y luego de descargar o clonar el proyecto debes ubicarte en tu proyecto en la terminal y luego ejecutar
npm install
esto es para descargar todas las dependencias del proyecto.