Las pruebas de software son vitales para garantizar que tus aplicaciones funcionan según lo esperado, especialmente cuando introduces cambios. Detectar y corregir errores en una fase temprana del desarrollo es crucial para mantener un código resistente y de alta calidad.

De las muchas herramientas y frameworks disponibles para las pruebas de JavaScript, Jest es una de las más populares. Jest, un producto de Meta, cuenta con amplias capacidades de comprobación para aplicaciones JavaScript y las construidas con marcos JavaScript.

Exploremos el framework Jest, sus características y la mejor forma de integrarlo en tu flujo de trabajo de desarrollo.

¿Qué es Jest?

Jest es un framework flexible y sencillo de utilizar. Además de sus funciones básicas de comprobación de JavaScript, ofrece configuraciones y complementos para admitir la comprobación de aplicaciones basadas en Babel, webpack, Vite, Parcel o TypeScript.

Jest ha sido ampliamente adoptado por los desarrolladores y cuenta con una serie de complementos creados y mantenidos por la comunidad. Destaca por su facilidad de uso: Las pruebas de JavaScript no requieren configuraciones ni plugins adicionales. Pero también puedes realizar pruebas más avanzadas – como probar frameworks JavaScript – utilizando algunas opciones de configuración adicionales.

Cómo Configurar Jest para Tu Proyecto JavaScript

Repasemos como configurar Jest en un proyecto JavaScript existente.

Requisitos previos

Para seguir este tutorial, asegúrate de que tienes lo siguiente:

Instala el paquete Jest

  1. Si aún no tienes un proyecto para seguir este tutorial, utiliza este repositorio como punto de partida.

La rama starter-files te proporciona una base para construir la aplicación mientras sigues el tutorial. Consulta la rama main para ver el código de este tutorial y cotejar tu código.

  1. Para instalar Jest con npm, ve al directorio del proyecto en tu terminal y ejecuta el siguiente comando:
npm install --save-dev jest

La opción --save-dev indica a npm que instale el paquete en devDependencies, que contiene las dependencias que necesitas para el desarrollo.

Configura Jest

Aunque Jest suele funcionar sin configuración adicional, hay dos formas de ampliar su potencia: en el archivo package.json y mediante un archivo de configuración de Jest.

Configurar Jest en package. json

En tu archivo package.json, añade un objeto llamado jest con las propiedades que se muestran a continuación:

{
  …
  "jest": {
    "displayName": "Ecommerce",
    "globals": {
      "PROJECT_NAME": "Ecommerce TD"
    },
    "bail": 20,
    "verbose": true
  },
}

Durante la prueba, Jest busca en este objeto y aplica estas configuraciones. Puedes ver opciones adicionales en la página de configuraciones de Jest, pero las propiedades de este objeto incluyen:

  • displayName – Jest añade el valor de esta propiedad como etiqueta a los resultados de tus pruebas.
  • globals – Contiene un valor de objeto para definir las variables globales disponibles en tus entornos de prueba.
  • bail – Por defecto, Jest ejecuta todas las pruebas y muestra los errores en los resultados. bail indica a Jest que detenga la ejecución tras un número determinado de fallos.
  • verbose – Cuando se establece en true, muestra informes de pruebas individuales durante la ejecución de la prueba.

Configurar Jest en un archivo de configuración

También puedes configurar Jest en un archivo jest.config.js. Jest también admite las extensiones .ts, .mjs, .cjs y .json. Al ejecutar las pruebas, Jest busca estos archivos y aplica la configuración del archivo que encuentra.

Por ejemplo, considera este archivo jest.config.js:

const config = {
  displayName: "Ecommerce",
  globals: {
    "PROJECT_NAME": "Ecommerce TD"
  },
  bail: 20,
  verbose: true
}

module.exports = config;

El código exporta un objeto de configuración Jest con las mismas propiedades que el ejemplo anterior.

También puedes utilizar un archivo personalizado que contenga un objeto de configuración serializable en JSON y pasar la ruta del archivo a la opción --config al ejecutar tus pruebas.

Crea un archivo de prueba básico

Con Jest configurado, crea tus archivos de prueba. Jest revisa los archivos de prueba de tu proyecto, los ejecuta y proporciona los resultados. Los archivos de prueba suelen seguir un formato como [name].test.js o [name]-test.js. Este patrón facilita tanto a Jest como a tu equipo la identificación de tus archivos de prueba.

Considera un archivo string-format.js que tenga el siguiente código:

function truncate(
  str,
  count,
  withEllipsis = true
) {
  if (str.length < = count)
    return str

  const substring = str.substr(0, count)

  if (!withEllipsis)
    return substring

  return substring + '...'
}

module.exports = { truncate }

La función truncate() trunca las cadenas hasta una longitud determinada con la opción de añadir una elipsis.

Escribe la prueba

  1. Crea un archivo de prueba llamado string-format.test.js.
  1. Para mantener tus archivos organizados, coloca string-format.test.js en el mismo directorio en el que tienes el archivo string-format.js o en un directorio de prueba específico. Independientemente de dónde esté tu archivo de prueba dentro del proyecto, Jest lo encuentra y lo ejecuta. Con Jest, puedes probar tus aplicaciones en varios escenarios.
  2. Escribe una prueba básica en string-format.test.js de la siguiente manera::
const { truncate } = require('./string-format')

test('truncates a string correctly', () = > {
  expect(truncate("I am going home", 6)).toBe('I am g...')
})

El caso de prueba tiene la descripción truncates a string correctly. Este código utiliza la función expect proporcionada por Jest, que comprueba si un valor coincide con el resultado esperado.

El código pasa truncate("I am going home", 6) como argumento a expect. Este código prueba el valor devuelto al llamar a truncate con los argumentos "I am going home" y 6. La llamada a expect devuelve un objeto expectativa, que ofrece acceso a las coincidencias de Jest.

También contiene el comparador toBe, que tiene "I am g…" como argumento. El emparejador toBe comprueba la igualdad entre los valores esperados y los reales.

Ejecutar la prueba

Para ejecutar tus pruebas, define el comando jest.

  1. En el archivo package.json de tu proyecto, añade este script test:
"scripts": {
  "test": "jest"
}
  1. Ahora ejecuta npm run test, npm test, o npm t en tu terminal. Ejecuta Jest para el proyecto.

Cuando ejecutes las pruebas, éste será el resultado:

Resultado satisfactorio de la prueba Jest para string-format.test.js.
Resultado satisfactorio de la prueba Jest para string-format.test.js.

Los resultados muestran un conjunto de pruebas (el archivo string-format.test.js), una prueba ejecutada con éxito ("truncates a string correctly"), y el displayName (Ecommerce) que definiste en la configuración.

  1. En string-format.js, si añades un punto de más para romper el código y ejecutar la prueba, ésta falla:
Resultado de la prueba Jest fallido por una función truncar rota.
Resultado de la prueba Jest fallido por una función truncar rota.

Este resultado sugiere que has roto la función truncate o has hecho actualizaciones que requieren actualizar las pruebas.

Cómo Escribir Pruebas con Jest

Sintaxis de las pruebas Jest

La sintaxis propia de Jest es sencilla de utilizar. Jest expone métodos y objetos globales a tu proyecto para escribir pruebas. Algunos de sus términos fundamentales son describe, test, expect, y matchers.

  • describe: Esta función agrupa pruebas relacionadas en un archivo.
  • test: Esta función ejecuta la prueba. Es un alias de it. Contiene aserciones para los valores que quieres probar.
  • expect: Esta función declara las aserciones para varios valores. Proporciona acceso a emparejadores para varias formas de aserciones.
  • Matchers: Te permiten afirmar un valor de varias formas. Puedes afirmar la igualdad de valores, la igualdad booleana y la igualdad contextual (como si una matriz contiene el valor).

Para utilizarlos, considera el siguiente ejemplo:

  1. Sustituye la prueba del archivo string-format.test.js por el siguiente código:
describe("all string formats work as expected", () = > {
  test("truncates a string correctly", () = > {
    expect(
      truncate("I am going home", 6)
    ).toBe("I am g...")
  })
})
  1. Ejecuta el código.

El resultado debe ser el siguiente:

Resultado satisfactorio de la prueba Jest que muestra la etiqueta describir.
Resultado satisfactorio de la prueba Jest que muestra la etiqueta describir.

La captura de pantalla muestra que la etiqueta de la función describe crea un bloque. Aunque describe es opcional, agrupar las pruebas en un archivo con más contexto resulta útil.

Organizar las pruebas en conjuntos de pruebas

En Jest, un caso de prueba consta de la función test, la función expect y un emparejador. Una colección de casos de prueba relacionados es un conjunto de pruebas. En el ejemplo anterior, string-format .test.js es un conjunto de pruebas que incluye un caso de prueba para comprobar el archivo string-format.js.

Supongamos que tienes más archivos en tu proyecto, como file-operations.js, api-logger.js y number-format.js. Puedes crear conjuntos de pruebas para estos archivos, como file-operations.test.js, api-logger.test.js y number-format.test.js.

Escribir aserciones sencillas con comparadores Jest

Hemos explorado un ejemplo de uso del comparador toBe. Las aserciones con otros comparadores Jest incluyen:

  • toEqual – Para comprobar la igualdad «profunda» en instancias de objetos.
  • toBeTruthy – Para comprobar si un valor es verdadero en un contexto booleano.
  • toBeFalsy – Para comprobar si un valor es falso en un contexto booleano.
  • toContain – Para comprobar que una matriz contiene un valor.
  • toThrow – Para comprobar si una función invocada produce un error.
  • stringContaining – Para comprobar que una cadena contiene una subcadena.

Veamos algunos ejemplos en los que se utilizan algunos de estos emparejadores.

Por ejemplo, puedes esperar que una función o código devuelva un objeto con propiedades y valores específicos.

  1. Utiliza el fragmento de código siguiente para probar esta funcionalidad. En este caso, quieres afirmar que el objeto devuelto es igual al objeto esperado.
expect({
  name: "Joe",
  age: 40
}).toBe({
  name: "Joe",
  age: 40
})

Este ejemplo utiliza toBe. La prueba falla porque este comparador no comprueba la igualdad en profundidad: comprueba el valor, no todas las propiedades.

  1. Utiliza el comparador toEqual para comprobar la igualdad profunda:
expect({
  name: "Joe",
  age: 40
}).toEqual({
  name: "Joe",
  age: 40
})

Esta prueba se supera porque ambos objetos son «profundamente iguales», es decir, todas sus propiedades son iguales.

  1. Prueba otro ejemplo de comparador que comprueba si la matriz definida contiene un elemento concreto.
expect(["orange", "pear", "apple"]).toContain("mango")

Esta prueba falla porque toContain afirma que la matriz ["orange", "pear", "apple"] contiene un valor esperado "mango", pero la matriz no lo contiene.

  1. Utiliza variables para realizar la misma prueba que con el código siguiente:
const fruits = ["orange", "pear", "apple"];
const expectedFruit = "mango";

expect(fruits).toContain(expectedFruit)

Prueba código asíncrono

Hasta ahora, hemos probado código síncrono: expresiones que devuelven un valor antes de que el código ejecute la línea siguiente. También puedes utilizar Jest para código asíncrono con async, await, o Promesas.

Por ejemplo, el archivo apis.js tiene una función para realizar una solicitud de API:

function getTodos() {
  return fetch('https://jsonplaceholder.typicode.com/todos/1')
}

La función getTodos envía una solicitud GET a https://jsonplaceholder.typicode.com/todos/1.

  1. Crea un archivo llamado apis.test.js con el siguiente código para probar la API falsa:
const { getTodos } = require('./apis')

test("gets a todo object with the right properties", () = > {
  return getTodos()
    .then((response) = > {
      return response.json()
    })
    .then((data) = > {
      expect(data).toHaveProperty('userId')
      expect(data).toHaveProperty('id')
      expect(data).toHaveProperty('title')
      expect(data).toHaveProperty('completed')
      expect(data).toHaveProperty('description')
    })
})

Este caso de prueba invoca la función getTodos que obtiene un objeto todo. Cuando resuelve la Promise, utiliza el método .then para obtener el valor resuelto.

En ese valor, el código devuelve response.json(), que es otra Promise que convierte la respuesta al formato JSON. Otro método .then obtiene el objeto JSON que contiene los expect y los emparejadores. El código afirma que el objeto JSON incluye cinco propiedades: userId, id, title, completed, y description.

  1. Ejecuta las pruebas:
Resultado de la prueba Jest que muestra una prueba fallida para el código asíncrono.
Resultado de la prueba Jest que muestra una prueba fallida para el código asíncrono.

 

Como muestra la captura de pantalla, la prueba para getTodos() falla. Espera la propiedad description, pero la API no la devuelve. Con esta información, ahora puedes pedir al equipo de gestión de la API de tu empresa que incluya esa propiedad si la aplicación la necesita o actualizar las pruebas para que se ajusten a la respuesta de la API.

  1. Elimina la aserción para la propiedad description y vuelve a ejecutar las pruebas:
Resultado de la prueba Jest que muestra una prueba superada para el código asíncrono.
Resultado de la prueba Jest que muestra una prueba superada para el código asíncrono.

La captura de pantalla muestra que todo ha superado la prueba.

  1. Ahora prueba a utilizar async/await en lugar del manejo tradicional de Promise:
test("gets a todo object with the right properties", async () = > {
  const response = await getTodos()
  const data = await response.json()

  expect(data).toHaveProperty("userId")
  expect(data).toHaveProperty("id")
  expect(data).toHaveProperty("title")
  expect(data).toHaveProperty("completed")
})

La palabra clave async está ahora antes de la función. El código utiliza await antes de getTodos() y await antes de response.json().

Funciones Avanzadas de Jest

Funciones y módulos simulados

Puede que quieras probar una expresión con dependencias externas al escribir pruebas. En algunos casos, especialmente en las pruebas unitarias, tus pruebas unitarias deben estar aisladas de los efectos externos. En ese caso, puedes simular tus funciones o módulos con Jest para controlar mejor tus pruebas.

  1. Por ejemplo, considera un archivo functions.js que contiene el siguiente código:
function multipleCalls(count, callback) {
  if (count < 0) return;

  for (let counter = 1; counter <= count; counter++) {
    callback()
  }
}

La función multipleCalls se ejecuta en función del valor de count. Depende de la función de devolución de llamada: la dependencia externa. Su finalidad es saber si multipleCalls ejecuta correctamente la dependencia externa.

  1. Para simular la dependencia externa y seguir el estado de la dependencia en tu archivo de prueba, functions.test.js, utiliza este código:
const { multipleCalls } = require('./functions')

test("functions are called multiple times correctly", () => {
  const mockFunction = jest.fn()

  multipleCalls(5, mockFunction)

  expect(
    mockFunction.mock.calls.length
  ).toBe(5)
})

Aquí, el método fn del objeto jest crea una función simulada. A continuación, el código ejecuta multipleCalls pasando 5 y la función simulada como argumentos. A continuación, afirma que el mockFunction es llamado cinco veces. La propiedad mock contiene información sobre cómo el código llama a la función y los valores devueltos.

  1. Cuando ejecutes la prueba, éste será el resultado esperado:
Resultado satisfactorio de la prueba Jest con una función simulada.
Resultado satisfactorio de la prueba Jest con una función simulada.

Como se ha demostrado, el código llama al mockFunction cinco veces.

En el código, la función simulada imita una dependencia externa. No importa cuál sea la dependencia externa cuando la aplicación utilice multipleCalls en producción. A tu prueba unitaria no le importa cómo funciona la dependencia externa. Sólo verifica que multipleCalls funciona como se espera.

  1. Para simular módulos, utiliza el método mock y pasa una ruta de archivo, que es el módulo:
const {
  truncate,
} = require("./string-format")

jest.mock("./string-format.js")

Este código imita todas las funciones que exporta string-format.js y realiza un seguimiento de la frecuencia con que las llama. El truncate del módulo se convierte en una función imitada, lo que hace que la función pierda su lógica original. Puedes averiguar cuántas veces se ejecuta truncate en tus pruebas en la propiedad truncate.mock.calls.length.

Si tienes un error o tu código no funciona, compara tu código con la implementación completa.

Prueba Componentes React con Jest y la Biblioteca de Pruebas React

Si aún no tienes un proyecto para seguir este tutorial, puedes utilizar este proyecto React de ejemplo como punto de partida. La rama starter-files te ayudará a empezar a componer el código mientras sigues el tutorial. Utiliza la main como referencia para cotejar tu código con el código completo de este tutorial.

Puedes utilizar Jest para probar frameworks de JavaScript como React. Cuando creas proyectos React con Create React App, éstos admiten React Testing Library y Jest de forma predeterminada. Si creas un proyecto React sin Create React App, instala Jest para probar React con Babel y React testing library. Si clonas la rama starter-app, no necesitas instalar dependencias ni aplicar configuraciones.

  1. Si utilizas el proyecto de ejemplo, utiliza este comando para instalar las dependencias necesarias:
npm install --save-dev babel-jest @babel/preset-env @babel/preset-react react-testing-library

También puedes utilizar Enzyme en lugar de React Testing Library.

  1. Actualiza tus configuraciones de Babel en babel.config.js o crea este archivo si no existe:
module.exports = {
  presets: [
    '@babel/preset-env',
      ['@babel/preset-react', {runtime: 'automatic'}],
  ],
};
  1. Considera el archivo src/SubmitButton.js que tiene el siguiente código:
import React, { useState } from 'react'

export default function SubmitButton(props) {
  const {id, label, onSubmit} = props
  const [isLoading, setisLoading] = useState(false)

  const submit = () => {
    setisLoading(true)
    onSubmit()
  }

  return 

Este componente SubmitButton recibe tres props:

  • id – El identificador del botón.
  • label – Qué texto mostrar en el botón.
  • onSubmit – Qué función activar cuando alguien pulse el botón.

El código asigna la propiedad id al atributo data-testid, que identifica un elemento para la prueba.

El componente también rastrea el estado isLoading y lo actualiza a true cuando alguien pulsa el botón.

  1. Crea la prueba para este componente. Coloca el siguiente código en un archivo SubmitButton.test.js:
import {fireEvent, render, screen} from "@testing-library/react"
import "@testing-library/jest-dom"
import SubmitButton from "./SubmitButton"

test("SubmitButton becomes disabled after click", () => {
  const submitMock = jest.fn()

  render(
    <SubmitButton
      id="submit-details"
      label="Submit"
      onSubmit={submitMock}
    / >
  )

  expect(screen.getByTestId("submit-details")).not.toBeDisabled()

  fireEvent.submit(screen.getByTestId("submit-details"))

  expect(screen.getByTestId("submit-details")).toBeDisabled()
})

El código anterior renderiza el componente SubmitButton y utiliza el método de consulta screen.getByTestId para obtener el nodo DOM mediante el atributo data-testid.

El primer expect es getByTestId("submit-details") y utiliza el modificador not y el comparador toBeDisabled (expuesto desde react-testing-library) para afirmar que el botón no está desactivado. Utiliza el modificador not con cada emparejador para afirmar lo contrario del emparejador.

A continuación, el código dispara el evento submit en el componente y comprueba que el botón está desactivado. Puedes encontrar más comparadores personalizados en la documentación de la biblioteca de pruebas.

  1. Ahora, ejecuta las pruebas. Si has clonado la rama starter-files, asegúrate de que tienes instaladas todas las dependencias del proyecto ejecutando npm install antes de iniciar las pruebas.

Resultado de la prueba Jest que muestra que se ha superado la prueba de un componente react.
Resultado de la prueba Jest que muestra que se ha superado la prueba de un componente react.

Ejecuta informes de cobertura del código

Jest también ofrece informes de cobertura de código para mostrar qué parte de tu proyecto estás probando.

  1. Pasa la opción --coverage a Jest. En tu script Jest en package.json (en el proyecto JavaScript), actualiza el comando Jest con esta opción de cobertura:
"scripts": {
  "test": "jest --coverage"
}
  1. Ejecuta npm run test para probar tu código. Obtendrás un informe como el siguiente
Informe de cobertura satisfactoria de Jest para cada traje de prueba.
Informe de cobertura satisfactoria de Jest para cada traje de prueba.

Este informe muestra que Jest ha probado el 100% de las funciones de SubmitButton.js y string-format.js. También indica que Jest no ha probado ninguna declaración ni línea en string-format.js. La cobertura de las pruebas muestra que las líneas no probadas en string-format.js son 7 y 12.

En la línea 7, return str de la función truncate no se ejecuta porque la condición if (str.length <= count) devuelve false.

En la línea 12, también en la función truncate, el return substring no se ejecuta porque la condición if (!withEllipsis) devuelve false.

Integra Jest con Tu Flujo de Trabajo de Desarrollo

Veamos cómo puedes integrar estas pruebas para mejorar tu flujo de trabajo de desarrollo.

Ejecuta pruebas en Watch Mode

En lugar de ejecutar manualmente las pruebas, puedes ejecutarlas automáticamente cuando cambies el código utilizando el modo Watch Mode.

  1. Para activar el modo vigilancia, actualiza tu script de comandos Jest en package.json (en el proyecto JavaScript) añadiendo la opción --watchAll:
"scripts": {
  "test": "jest --coverage --watchAll"
}
  1. Ejecuta npm run test. Activa Jest en Watch Mode:
Ejecuta Jest en Watch Mode.
Ejecuta Jest en Watch Mode.

Las pruebas se ejecutan cada vez que modificas tu proyecto. Este enfoque promueve la retroalimentación continua a medida que construyes tu aplicación.

Configura Ganchos Pre-Commit

En los entornos Git, los ganchos ejecutan secuencias de comandos cada vez que se produce un evento concreto (como pull, push o commit). Los ganchos de pre-commit definen qué scripts se ejecutan para el evento de pre-commit (que el código activa antes de hacer una confirmación).

La confirmación sólo tiene éxito si el script no lanza un error.

Ejecutar Jest antes de la confirmación previa garantiza que ninguna de tus pruebas falle antes de la confirmación.

Puedes utilizar varias bibliotecas para configurar ganchos git en tu proyecto, como ghooks.

  1. Instala ghooks en devDependencies:
npm install ghooks --save-dev
  1. Añade un objeto configs en el nivel superior de tu archivo package.json (en el proyecto JavaScript).
  2. Añade un objeto ghooks debajo de configs.
  1. Añade una propiedad con una clave de pre-commit y un valor de jest.
{
  …
  "config": {
    "ghooks": {
      "pre-commit": "jest"
    }
  },
}
  1. Confirma el código. El código activa el gancho pre-commit, que ejecuta Jest:

Ejecutar Jest durante el pre-commit usando ghooks.
Ejecutar Jest durante el pre-commit usando ghooks.

Resumen

Ahora ya sabes cómo integrar Jest en tu flujo de trabajo de desarrollo para que se ejecute automáticamente cada vez que hagas un cambio. Este enfoque proporciona una retroalimentación continua para que puedas corregir rápidamente cualquier problema de código antes de lanzar tus cambios a producción.

Alojando tu aplicación con Kinsta, te beneficias de una infraestructura rápida y segura, desplegando tus proyectos en una infraestructura construida sobre la red Premium Tier de Google Cloud Platform y máquinas C2. Elige entre los centros de datos de 37 y una CDN habilitada para HTTP/3 con PoPs de 260+.

Mantente seguro con la tecnología de contenedores aislados, dos potentes cortafuegos y la protección DDoS avanzada de Cloudflare. Y puedes integrar aplicaciones o automatizar flujos de trabajo con la API Kinsta.

Configura Jest y explora los recursos de Kinsta hoy mismo para mejorar tus aplicaciones JavaScript.

Marcia Ramos Kinsta

I'm the Editorial Team Lead at Kinsta. I'm a open source enthusiast and I love coding. With more than 7 years of technical writing and editing for the tech industry, I love collaborating with people to create clear and concise pieces of content and improve workflows.