Tutorial: Medir la cobertura de las pruebas del front
1. Objetivos de aprendizaje
Sección titulada «1. Objetivos de aprendizaje»Al terminar este tutorial vas a ser capaz de:
- Instalar el paquete que mide la cobertura y correr las pruebas con ella.
- Leer la tabla de cobertura y encontrar las líneas que ninguna prueba ejecuta.
- Ver esas líneas marcadas en el reporte del navegador.
- Escribir la prueba que falta y comprobar que el número sube.
- Explicar por qué una prueba puede subir la cobertura sin proteger nada.
- Saber qué hace el pipeline del grupo con ese reporte.
Prerrequisito: el tutorial de pruebas del front con Vitest, porque aquí se mide la cobertura de esas pruebas. La teoría está en Pruebas del front con Vitest.
2. Qué mide la cobertura
Sección titulada «2. Qué mide la cobertura»La cobertura cuenta qué parte del código se ejecutó mientras corrían las pruebas. No mide si lo ejecutado se verificó: eso lo muestra la sección 7. Vitest la reporta con cuatro columnas:
| Columna | Qué cuenta |
|---|---|
% Stmts |
Las sentencias (cada instrucción) que se ejecutaron |
% Branch |
Las ramas de los if, los ?: y los && que se tomaron |
% Funcs |
Las funciones que se llamaron al menos una vez |
% Lines |
Las líneas que se ejecutaron |
Una última columna, Uncovered Line #s, lista las líneas que ninguna prueba ejecutó.
Es la más útil.
Antes de empezar, corre las pruebas: deben terminar en verde.
pnpm test --watch=false3. Instalar el paquete de cobertura
Sección titulada «3. Instalar el paquete de cobertura»Vitest no trae el medidor. Si corres con cobertura sin instalarlo, Angular lo avisa y no corre nada:
The following packages are required but were not found: - Code coverage requires either "@vitest/coverage-v8" or "@vitest/coverage-istanbul" to be installed.El paquete debe tener exactamente la misma versión que vitest. Mira cuál tienes:
pnpm list vitestY instala el medidor con esa versión (en el ejemplo, 4.1.11):
pnpm add -D @vitest/coverage-v8@4.1.114. Correr con cobertura y leer la tabla
Sección titulada «4. Correr con cobertura y leer la tabla»pnpm test --watch=false --coverage --coverage-reporters=lcov --coverage-reporters=textEl reporte text sale en la consola, y el lcov deja archivos en
coverage/<nombre-del-proyecto>/. Esta es la tabla del proyecto de referencia, con las
filas que importan para este tutorial:
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s-------------------|---------|----------|---------|---------|-------------------All files | 86.81 | 85.89 | 88.46 | 88.11 | app | 90.24 | 82.35 | 72.72 | 86.2 | ...st.service.ts | 80 | 57.14 | 70 | 75 | 43-45,65 app/album-list | 60.71 | 88.88 | 100 | 55.55 | album-list.html | 42.1 | 100 | 100 | 38.46 | 6-20Tres cosas para leerla:
- Los nombres largos se recortan con
...:...st.service.tsesartist.service.ts. - Una fila por archivo, y una por carpeta que resume los archivos de adentro. También
aparecen las plantillas
.html, porque el código de la plantilla también se ejecuta. 43-45,65son líneas deartist.service.tsque ninguna prueba ejecutó: las del métodoalbumResourcey la del métodocrear. Es el primer código sin cubrir.
Tu tabla tendrá otros números y otros archivos. Busca en la columna de líneas sin cubrir un archivo tuyo con pocas pruebas: ese es el que vas a trabajar.
5. Ver las líneas en el navegador
Sección titulada «5. Ver las líneas en el navegador»La tabla dice los números de línea, pero no el código. El reporte lcov genera además una
página que lo muestra. Ábrela en el navegador:
coverage/<nombre-del-proyecto>/lcov-report/index.htmlEntra a un archivo desde la lista. Las líneas que ninguna prueba ejecutó quedan marcadas
en rojo, y las ramas que no se tomaron, en amarillo. Abre artist.service.ts y verás
marcadas las tres líneas del método albumResource y la del método crear.
6. Cubrir el código que falta: la prueba nueva
Sección titulada «6. Cubrir el código que falta: la prueba nueva»La línea 65 de artist.service.ts es el POST que guarda un artista nuevo, el método
crear del Release 3: ninguna prueba lo ejecuta. Si tu servicio tiene otro método sin
cubrir, aplica el mismo patrón con ese. Agrega esta prueba en artist.service.spec.ts,
dentro del describe, y el import del modelo arriba:
import { NuevoArtista } from './album-list/album'; it('crear hace un POST a /artistas con el artista nuevo en el cuerpo', () => { const nuevo: NuevoArtista = { nombre: 'Ana', fotoArtistaUrl: 'https://ejemplo.com/ana.jpg', paisOrigen: 'Colombia', biografia: 'Cantautora', fechaNacimiento: '1990-01-01', };
service.crear(nuevo).subscribe();
const req = http.expectOne(environment.ARTISTAS_URL); expect(req.request.method).toBe('POST'); expect(req.request.body).toEqual(nuevo); req.flush({ ...nuevo, id: 1, albumes: [] }); });Corre la cobertura otra vez. La fila del servicio cambia, y la línea 65 desaparece de la lista:
| % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s ...st.service.ts | 85 | 57.14 | 80 | 81.25 | 43-45Antes eran 80, 57.14, 70 y 75 en las cuatro columnas. Subieron tres, y la de ramas
no cambió porque crear no tiene ningún if ni ?:. Las líneas 43 a 45, las de
albumResource, quedan como ejercicio: una prueba que le pase un id y compruebe la URL
de la petición.
7. Una prueba que sube el número sin proteger nada
Sección titulada «7. Una prueba que sube el número sin proteger nada»Mira esta versión del mismo caso:
it('crear se ejecuta', () => { // `nuevo` es el mismo artista de la prueba anterior. service.crear(nuevo).subscribe(); http.match(() => true).forEach((req) => req.flush({})); });Llama al método y responde cualquier petición, pero no comprueba nada: ni la URL, ni
el verbo, ni el cuerpo. Con esa prueba en lugar de la buena, la cobertura es la misma
(85, 57.14, 80 y 81.25, y la línea 65 sigue cubierta). Ahora rompe el código: en
crear, cambia environment.ARTISTAS_URL por environment.ALBUMES_URL.
| Prueba | Cobertura del servicio | Con la URL rota |
|---|---|---|
crear hace un POST a /artistas con el artista nuevo en el cuerpo |
85 / 57.14 / 80 / 81.25 | Falla: Expected one matching request for criteria "Match URL: http://localhost:8080/artistas", found none. Requests received are: POST http://localhost:8080/albumes |
crear se ejecuta |
85 / 57.14 / 80 / 81.25 | Pasa: las 16 pruebas en verde |
La cobertura no distingue las dos pruebas. Por eso sirve para encontrar código sin pruebas, y no para saber si las pruebas son buenas: eso lo muestra la sección “Romper el código a propósito” del tutorial de Vitest, rompiendo el código a propósito. Restaura la URL y deja la prueba buena.
8. Qué hace el pipeline con esto
Sección titulada «8. Qué hace el pipeline con esto»El Jenkinsfile del curso hace tres cosas con la cobertura del front, sin que tengas que
tocar nada:
- Instala el medidor si falta. Si el proyecto no trae
@vitest/coverage-v8, lo agrega con la versión devitest. - Corre
pnpm test --coverage --coverage-reporters=lcov, que dejacoverage/<proyecto>/lcov.info. - Se lo entrega a SonarQube, que lee ese
lcov.infoy muestra la cobertura del proyecto junto con la del back. Excluye del cálculomain.ts,app.config.tsy la carpetaenvironments, que no tienen lógica propia.
Por eso no necesitas configurar el pipeline: con las pruebas en tu proyecto, el reporte aparece solo. Lo que sí controlas es qué tanto del código ejecutan esas pruebas, y eso es lo que este tutorial te enseñó a mirar.
9. Errores frecuentes
Sección titulada «9. Errores frecuentes»Code coverage requires either "@vitest/coverage-v8" or .... Falta instalar el medidor (sección 3).Running mixed versions is not supported. El medidor yvitesttienen versiones distintas. Reinstala el medidor con la versión que muestrapnpm list vitest.- No encuentras
lcov-reportnilcov.info. Corriste con cobertura pero sin--coverage-reporters=lcov, o miras en otra carpeta: está encoverage/<nombre-del-proyecto>/. - La cobertura subió pero rompes el código y nada falla. La prueba ejecuta el código sin comprobar nada. Vuelve a la sección 7.
pnpm testfalla conERR_PNPM_IGNORED_BUILDS. Es un aviso de pnpm 11 sobre los scripts de instalación, no de tus pruebas:pnpm approve-builds --alllo resuelve.
¿Dónde quedaste?
Sección titulada «¿Dónde quedaste?»Al final de este tutorial sabes:
- Correr las pruebas con cobertura y leer la tabla y el reporte del navegador.
- Encontrar el código que ninguna prueba ejecuta y escribir la que falta.
- Distinguir una prueba que protege de una que solo sube el número.
- Qué hace el pipeline con el reporte.