Mike (@mikerb95)CodeByMike

Reportes de pruebas

Qué emite el runner cuando corren las 1200 pruebas del proyecto, en los7 formatos que sabe producir: 4 van a la consola y3 escriben un archivo. Referencia para saber cuál pedir según lo que se necesite: depurar, guardar evidencia o alimentar otra herramienta.

Cada bloque de salida es una captura real de correr ese reporter contratests/phone.test.ts (14 casos), recortada pero no reescrita. La corrida completa y sus tiempos están enEjecución de pruebas.

--reporter=defaultTexto con colorsolo consola

El día a día. Una línea por archivo y el detalle solo de lo que falla.

npm test

Salida real

 RUN  v4.1.9 /home/mike/dev/work/github.com/portfolio

 ✓ tests/phone.test.ts (14 tests) 12ms

 Test Files  1 passed (1)
      Tests  14 passed (14)
   Start at  19:54:56
   Duration  333ms (transform 75ms, setup 0ms, import 103ms, tests 12ms)

A favor

Silencioso cuando todo pasa: el ruido aparece solo si hay algo que mirar.

En contra

No dice el tiempo de cada prueba, solo el del archivo.

--reporter=verboseTexto con color, una línea por casosolo consola

Ver el nombre y el tiempo de cada caso mientras se trabaja en un módulo.

npx vitest run --reporter=verbose

Salida real

 ✓ tests/phone.test.ts > normalizePhone > normaliza las formas en que se escribe un móvil colombiano 3ms
 ✓ tests/phone.test.ts > normalizePhone > acepta números extranjeros solo con + explícito 1ms
 ✓ tests/phone.test.ts > normalizePhone > rechaza lo que no es un teléfono 1ms
 ✓ tests/phone.test.ts > normalizePhone > rechaza un + en medio del número 0ms
 ✓ tests/phone.test.ts > normalizePhone > es idempotente: normalizar lo ya normalizado no lo cambia 0ms
 ✓ tests/phone.test.ts > isE164 > distingue el formato canónico 0ms
 ✓ tests/phone.test.ts > formatPhone > agrupa los colombianos 3-3-4 0ms

A favor

Es donde se ve que el nombre del caso hace de documentación ejecutable.

En contra

Con 1181 pruebas son 1181 líneas: ilegible para la suite completa.

--reporter=dotUn carácter por pruebasolo consola

Corridas largas donde solo interesa el avance y el recuento final.

npx vitest run --reporter=dot

Salida real

 RUN  v4.1.9 /home/mike/dev/work/github.com/portfolio

··············

 Test Files  1 passed (1)
      Tests  14 passed (14)

A favor

Cabe entero en pantalla por muchas pruebas que haya.

En contra

Un punto no dice qué se probó. Sirve de barra de progreso, no de informe.

--reporter=tap-flatTAP 13 (texto estandarizado)solo consola

Entregar el resultado a otra herramienta que hable TAP, sin XML de por medio.

npx vitest run --reporter=tap-flat > informes/tests.tap

Salida real

TAP version 13
1..14
ok 1 - tests/phone.test.ts > normalizePhone > normaliza las formas en que se escribe un móvil colombiano # time=5.14ms
ok 2 - tests/phone.test.ts > normalizePhone > acepta números extranjeros solo con + explícito # time=1.01ms
ok 3 - tests/phone.test.ts > normalizePhone > rechaza lo que no es un teléfono # time=1.47ms
ok 4 - tests/phone.test.ts > normalizePhone > rechaza un + en medio del número # time=0.77ms

A favor

Formato abierto y viejo (1987), legible por humanos y por máquinas a la vez.

En contra

Ignora --outputFile: hay que redirigir la salida con >, como se ve en el comando.

--reporter=junitXMLescribe archivo

El formato que este proyecto usa como fuente del informe y de /docs/ejecucion-pruebas.

npx vitest run --reporter=junit --outputFile=informes/tests-junit.xml

Salida real

<?xml version="1.0" encoding="UTF-8" ?>
<testsuites name="vitest tests" tests="14" failures="0" errors="0" time="0.013608159">
    <testsuite name="tests/phone.test.ts" timestamp="2026-08-24T00:57:18.679Z"
               tests="14" failures="0" errors="0" skipped="0" time="0.013608159">
        <testcase classname="tests/phone.test.ts"
                  name="normalizePhone &gt; normaliza las formas en que se escribe un móvil colombiano"
                  time="0.004271544">
        </testcase>

A favor

Es el mismo formato que produce Maven Surefire en Java, así que cualquier CI y cualquier evaluador lo reconoce. Trae el tiempo de cada caso.

En contra

Ilegible en crudo: hay que renderizarlo para poder presentarlo.

--reporter=jsonJSONescribe archivo

Procesar el resultado con un script propio sin parsear XML.

npx vitest run --reporter=json --outputFile=informes/tests.json

Salida real

{
  "numTotalTests": 14,
  "numPassedTests": 14,
  "startTime": 1787533039636,
  "success": true,
  "testResults": [{
    "assertionResults": [{
      "fullName": "normalizePhone normaliza las formas en que se escribe un móvil colombiano",
      "status": "passed",
      "duration": 3.2443159999999978
    }]
  }]
}

A favor

Se consume con JSON.parse, sin dependencias ni regex.

En contra

Aplana la jerarquía describe/it en un solo fullName con espacios.

--reporter=htmlAplicación web interactivaescribe archivorequiere @vitest/ui

Explorar la suite en el navegador con filtros y código fuente.

npm i -D @vitest/ui && npx vitest run --reporter=html

Salida real

 MISSING DEPENDENCY  Cannot find dependency '@vitest/ui'

Error: Failed to load custom Reporter from @vitest/ui/reporter
  [cause]: Error: Failed to load url @vitest/ui/reporter. Does the file exist?

A favor

Es el equivalente más directo al informe navegable de JaCoCo.

En contra

Exige una dependencia que este repo no tiene, y produce una SPA para desarrollar, no un dato procesable. Por eso el informe del proyecto se genera desde JUnit y no desde aquí.

Anatomía de un fallo

Lo interesante de un log no es el verde, sino qué información da cuando algo se rompe. Este es un fallo real, provocado a propósito escribiendo mal el número esperado: la función devolvía+573104641228 y la prueba esperaba un dígito menos.

En consola (reporter default)

 ❯ tests/zz-fallo-demo.test.ts (1 test | 1 failed) 20ms
     × normaliza un móvil colombiano a E.164 17ms

⎯⎯⎯⎯⎯⎯⎯ Failed Tests 1 ⎯⎯⎯⎯⎯⎯⎯

 FAIL  tests/zz-fallo-demo.test.ts > normalizePhone > normaliza un móvil colombiano a E.164
AssertionError: expected '+573104641228' to be '+57310464122' // Object.is equality

Expected: "+57310464122"
Received: "+573104641228"

 ❯ tests/zz-fallo-demo.test.ts:6:44
      4| describe('normalizePhone', () => {
      5|   it('normaliza un móvil colombiano a E.164', () => {
      6|     expect(normalizePhone('310 464 1228')).toBe('+57310464122')
       |                                            ^
      7|   })
      8| })

El mismo fallo en XML (reporter junit)

<testcase classname="tests/zz-fallo-demo.test.ts"
          name="normalizePhone &gt; normaliza un móvil colombiano a E.164" time="0.008989228">
    <failure message="expected &apos;+573104641228&apos; to be &apos;+57310464122&apos;"
             type="AssertionError">
AssertionError: expected &apos;+573104641228&apos; to be &apos;+57310464122&apos;

Expected: &quot;+57310464122&quot;
Received: &quot;+573104641228&quot;

 ❯ tests/zz-fallo-demo.test.ts:6:44
    </failure>
</testcase>
Ruta completa del casoArchivo, describe e it concatenados. Es lo que permite volver a correr solo ese caso con -t.
Tipo de errorAssertionError distingue "la prueba comprobó y no cuadró" de un TypeError, que es la prueba rota.
Expected / ReceivedLos dos valores enfrentados. En el ejemplo sobra un dígito: el error estaba en la prueba, no en la función.
Archivo:línea:columnaLa posición exacta de la aserción que falló, no la del inicio del test.
Fragmento de código con el cursorEl contexto alrededor con un ^ bajo la expresión culpable. Es lo que ahorra abrir el editor.

Equivalencia con el instrumental de Java

El vocabulario estándar de pruebas viene en buena medida del mundo Maven, y la correspondencia no es obvia porque los nombres coinciden a medias: aquí "JUnit" es un formato de archivo, no el framework que ejecuta las pruebas.

En Java / MavenEn este proyectoQué cambia
JUnit 5 (@Test)Vitest (it / test)El framework de pruebas. El nombre legible es el string de it(), no una anotación @DisplayName aparte.
Maven Surefirevitest runEl que ejecuta la suite y produce el reporte. Surefire escribe XML por defecto; Vitest hay que pedírselo.
target/surefire-reports/*.xmlinformes/tests-junit.xmlMismo esquema XML: testsuite, testcase, atributo time en segundos, hijo failure.
JaCoCocoverage v8 (npm run test:coverage)Cobertura. JaCoCo instrumenta bytecode y cuenta instrucciones; v8 mide sobre el motor y cuenta sentencias. Los porcentajes no son comparables entre sí.
PIT (pitest)Stryker (npm run test:mutation)Mutación: mide si las pruebas detectan un cambio en el código, que es lo que la cobertura no responde.

El proyecto genera su informe a partir del reporter junit, no delhtml: el XML no cuesta dependencias, lo reconoce cualquier CI y, por ser un dato procesable, alimenta a la vez el informe entregable y la página deEjecución de pruebas. Una SPA no permite ninguna de las dos cosas.