Angular Testing

Nota: faltan detalles

Jasmine y Karma

Angular usa Jasmine como framework de pruebas y Karma como test Runner. A partir de la versión 15 de Angular se eliminaron algunos archivos de configuración para hacer más fácil el entendimiento del framework para nuevos desarrolladores. Karma.conf.js ya no se crea por default con el ng new, sin embargo lo podemos agregar con el siguiente comando:

ng generate config karma

Automáticamente karma va a leer todos los archivos del proyecto que acaben con spec.ts para ejecutar las pruebas.

Estructura

describe('HomeComponent', () => {
  let component: HomeComponent;

  it('should create', () => {
    expect(component).toBeTruthy();
  });
  
});

describe - define una suite de tests. Una colección de tests. Recibe dos parámetros, un string con el nombre de la suite y una function() donde se definen los tests.

it - define un test en particular. Recibe como parámetro el nombre del test y una función a ejecutar por el test.

expect - Lo que esperar recibir ese test. Con expect se hace la comprobación del test.

Se puede seguir unos pasos muy utiles

Arrange:(Arreglar). Se establece el estado inicial, conocida como el sujeto a probar. Aquí se inicializan variables, importaciones. Se crea el ambiente a probar.

Act (Actuar): Se generan acciones o estímulos. Se llaman métodos, o se simulan clicks por ejemplo

Assert (Afirmar): observar el comportamiento. Los resultados son los esperados. Eje: Que algo cambie, se incremente, o no suceda nada.

Matchers

Reporte de covertura

Para poder generar un reporte de covertura (más visual y específico) que no estará en modo escucha continua, lo que debe hacer es correr el sigueinte comando en la términal

Con esto podemos tener mas detalle, por ejemplo de que funciones no tienen pruebas etc.

Se pueden enfocar en ciertas pruebas u omitir agregando la letra x o f al inicio de las palabras claves de los test.

  • con fdescribeejecuta únicamente el suite de test

  • con xdescribe se omite el suite de test

  • con fit ejecuta el focus sobre un test

  • con xit se omite un test

Umbral mínimo de covertura

En el archivo karma.conf.js se agrega lo siguiente para actualizarlo y saber qué necesita ser cubierto con pruebas de acuerdo al umbral.

Opcionalmente podemos tener un reporter adicional con mejoras visuales

Instalar Mocha Report

Agregar en karma.conf.js en plugins

Cambiar reporters a

Testing a Servicios

Cada que colocamos un it estamos indicando un escenario de prueba, cada escenario de prueba debería manejarse de manera insolada. Esto significa que una prueba no debería afectar a la siguiente o a otra prueba.

Lo que hacemos es crear las instancias que ocupamos para cada prueba, por ejemplo la creación del servicio. Para optimizar el código se usa la función beforeEach que va a ejecutarse antes de cada prueba.

Cada vez que se corra una funcion asíncrona dentro de un test y se resuelva la promesa dentro de una función then(), por ejemplo, se recibirá una funcion para indicar manualmente que ha terminado la ejecución. Generalmenet se usa done(). Aunque lo recomendable es usar async/await.

Test a Servicios con Dependencias

Recordar que si vamos a testear un servicio que tiene dependencias, nosotros no debemos usar las dependencias reales, es decir, ya que no le corresponde a nuestra prueba que las dependencias nos devuelval los valores deseados, nosotros solo debemos encargarnos de que nuestra prueba funcione, entonces podriamos hacer un mock de datos fake para completar nuestra prueba.

El resto de dependencias tendrán sus propias pruebas ya, así que no nos deben de importar para la nuestra. Ejemplo:

Tenemos otro servicio.

Para aislar completamente estas pruebas usamos el siguiente código.

y con un fakeValueService

Aunque esto es una solución un poco mas correcta, en custion de escalabilidad y mantenimiento puede ser un problema al largo plazo.

Otra forma de hacerlo es con un objeto, por que los objetos en JS funcionan casi como clases por lo que puedo hacer que se pase directamente con un objeto en master.service.spec.ts.

Esto es especialemente util al momento de probar funcionalidades que por ejemplo se conectan a una API como google maps, etc.

Spies

Para mejorar el tema del acceso a las dependencias que pueda tener un servicio podemos usar herramientas con las que cuenta Jasmine, como Spy.

Un Spy permite interceptar una función y trackear las llamadas a esta y sus argumentos, no necesariamente para obtener el valor que devuelve la función. Estos Spies solo existen en el bloque describe o it en el que fueron definidos, serán removidos luego de su implementación. Podemos definir que hara el Spy luego de ser invocado con and.

En este contexto nosotros estamos espiando un servicio que está siendo llamado desde el servicio que estamos probando que es el de MasterService.

Mocking

Son objetos simulados (pseudo-objetos, mock object, objetos de pega) a los que imitan el comportamiento de objetos reales de una forma controlada

Para este ejemplo usamos el concepto de mocking con jasmine a través de sus spies.

TestBed

Angular tiene una suit que nos permite hacer pruebas en un entorno de una manera más sencilla.

Para configurarlo, sería:

Con esto se obtiene un contexto más limpio ya que estamos usando el patrón de inyección de dependencias. Los providers ayudan a aislar cierto servicio, componente etc. Para ser probado, ahi solo debemos meter los módulos que estemos testeando.

TestBed unido con los spies nos ayudara para resolver la inyección de dependencias. Tomando como ejemplo a master service

master.service.spec.ts

HttpClientTestingModule

La responsabilidad del API donde se conecta el frontend es del backend, es decir, para las pruebas unitarias no debemos tener en cuenta si el servidor está corriendo o no.

HttpClientTestingModule es un módulo de Angular que se utiliza para realizar pruebas unitarias de componentes y servicios que utilizan HttpClient, que es la clase de Angular encargada de realizar solicitudes HTTP.

Al hacer una configuración http podemos decirle a la prueba que los valores los tome de un mock de datos en lugar de hacer una petición al servidor real. para este caso usamos HttpTestingController.

Mocking

Para esto podemos usar la librería Faker JS

y cambiamos el mocking en el archivo product.service.spec.ts

Testing a Componentes

Por defecto Angular crea un componente parecido a este:

Es muy similar al .spec al de los servicios pero tiene ciertas diferencias.

Con ComponentFixture tenemos un ambiente que nos Provee Angular para probar el componente, es la manera en que es renderizado y por tanto creado, de ese modo podemos utilizarlo. Con ayuda del artefacto fixture Angular creará el componente para obtener todos sus métodos.

Al igual que con las pruebas de servicios también necesitamos un módulo pequeño, para preparar nuestras pruebas usando TestBed.configureTestingModule (aunque de manera asíncrona).

Si queremos que la prueba a los elementos sea agnóstica a la plataforma debemos utilizar fixture.debugElement.

Cuando corremos en el navegador la aplicación de manera normal, Agular detecta los cambios en automático, sin embargo, en modo pruebas debemos utilizar fixture.detectChanges(); cada que realizamos un cambio dentro del componente, por ejemplo, la detección de un @Input().

Last updated