Desarrollo de software

¿Qué son las pruebas de software? Unitarias y E2E

Le explicamos la diferencia entre las pruebas unitarias, de integración y de extremo a extremo, cuántas hay que escribir de cada tipo y qué aporta la automatización de pruebas a un proyecto.

Aurora YazılımEquipo editorial 6 min de lectura
¿Qué son las pruebas de software? Unitarias y E2E
¿Qué son las pruebas de software?

Las pruebas de software son el conjunto de comprobaciones que se realizan para verificar que un programa funciona como se espera y no contiene errores. Pueden hacerse a mano o de forma automática con código. Los tres tipos más habituales son las pruebas unitarias, las pruebas de integración y las pruebas de extremo a extremo (E2E); en un proyecto sano se equilibran en forma de pirámide.

¿Qué son las pruebas de software y por qué hacen falta?

Las pruebas de software son la manera de demostrar que el código que ha escrito hace de verdad lo que usted quiere. Que en una tienda online el código de descuento se calcule bien, que en un software hotelero no se puedan hacer dos reservas para la misma habitación o que un formulario rechace datos erróneos, todo eso se garantiza con pruebas.

En los proyectos sin pruebas, cada función nueva corre el riesgo de romper algo que antes funcionaba. A esto se le llama regresión. Las pruebas automáticas reducen ese riesgo; cuando se hace un cambio, indican en minutos qué se ha roto.

El momento en que se encuentra el error determina el coste. Un error detectado durante el desarrollo se corrige en pocos minutos; uno que descubre el cliente en el sistema en producción cuesta dinero, tiempo y confianza.

Tipos de pruebas: unitarias, de integración y E2E

Los tipos de pruebas se distinguen por el ámbito que abarcan y por su velocidad. Probar piezas pequeñas es rápido y barato; probar todo el sistema es lento, pero realista.

TipoAlcanceVelocidadCoste de mantenimiento
Prueba unitariaUna sola función / componenteMuy rápidaBajo
Prueba de integraciónPiezas que trabajan juntasMedioMedio
Prueba E2ETodo el flujo del usuarioLentoAlta

¿Qué es una prueba unitaria?

La prueba unitaria comprueba una sola función o clase aislándola del mundo exterior. No intervienen la base de datos, la red ni el sistema de archivos; si hace falta, se simulan con objetos falsos (mocks). Se ejecuta en milisegundos y señala con precisión dónde está el error.

Prueba de integración

La prueba de integración verifica que varias piezas funcionan correctamente juntas: la aplicación y la base de datos, un servicio y otro servicio, el sistema y una API externa. Los endpoints que explicamos en nuestro artículo qué es una API se prueban sobre todo a este nivel. En flujos como el pago, los envíos y la integración con marketplaces, estas pruebas son críticas.

Prueba E2E

La prueba E2E (de extremo a extremo) usa el sistema como un usuario real: abre el navegador, añade el producto al carrito, va al paso de pago y comprueba que se crea el pedido. Es la prueba más realista, pero también la más lenta y la más frágil.

La pirámide de pruebas: ¿cuántas de cada tipo?

La pirámide de pruebas es un modelo muy extendido que explica cuántas pruebas conviene escribir de cada tipo. En la base hay muchas pruebas unitarias rápidas; en el medio, menos pruebas de integración; y en la cima, pocas pruebas E2E que solo cubren los flujos críticos.

Que la pirámide se invierta, es decir, intentar verificarlo todo con pruebas E2E, es un error frecuente. En ese caso el tiempo de ejecución se alarga, las pruebas se rompen sin motivo y con el tiempo el equipo deja de confiar en ellas.

No hay una proporción exacta; depende del tipo de proyecto. En un software con mucho cálculo pesan más las pruebas unitarias, mientras que en un proyecto que se conecta con muchos sistemas externos aumenta la parte de las pruebas de integración.

Ejemplo con Jest y Playwright

En el mundo de JavaScript, Jest y Vitest son opciones habituales para las pruebas unitarias, y Playwright y Cypress para las E2E. A continuación puede ver una prueba unitaria sencilla escrita para una función de descuento.

Si quiere detectar los errores de tipo antes incluso de escribir la prueba, consulte también nuestro artículo qué es TypeScript; el sistema de tipos alivia en parte la carga de las pruebas, pero no las sustituye.

javascriptPrueba unitaria con Jest
// indirim.js
export function indirimUygula(tutar, oran) {
  if (oran < 0 || oran > 100) throw new Error('Porcentaje no válido');
  return Math.round(tutar * (100 - oran)) / 100;
}

// indirim.test.js
import { indirimUygula } from './indirim.js';

test('el descuento del 20 % se calcula correctamente', () => {
  expect(indirimUygula(200, 20)).toBe(160);
});

test('un porcentaje no válido lanza un error', () => {
  expect(() => indirimUygula(200, 120)).toThrow();
});
javascriptPrueba E2E con Playwright
import { test, expect } from '@playwright/test';

test('el producto se añade al carrito', async ({ page }) => {
  await page.goto('https://ornek-magaza.test/urun/zeytinyagi');
  await page.getByRole('button', { name: 'Sepete Ekle' }).click();
  await expect(page.getByTestId('sepet-adet')).toHaveText('1');
});

Automatización de pruebas y proceso de CI

La automatización de pruebas consiste en ejecutar las pruebas no a mano, sino de forma automática con cada cambio de código. Cuando el código se sube al repositorio, un pipeline de CI (integración continua) ejecuta las pruebas; si una falla, el cambio no pasa a producción.

Este sistema resulta aún más valioso a medida que crece el equipo. Todos se someten al mismo nivel de calidad y los errores se detectan antes de que lleguen al cliente.

  1. El desarrollador hace el cambio en una rama y lo sube al repositorio.
  2. El pipeline de CI instala las dependencias y ejecuta las pruebas unitarias y de integración.
  3. Las pruebas E2E de los flujos críticos se ejecutan en el entorno de pruebas.
  4. Si todas las pruebas pasan, tras la revisión de código se pone en producción.

Otros tipos de pruebas

Que funcione correctamente no basta; el software también debe ser rápido, seguro y usable. Por eso, además de las pruebas funcionales, existen otros tipos de pruebas.

  • Prueba de rendimiento: mide cómo se comporta el sistema bajo carga. La velocidad de página forma parte también del trabajo de velocidad y rendimiento.
  • Prueba de seguridad: busca accesos no autorizados, inyecciones y vulnerabilidades similares.
  • Prueba de usabilidad: comprueba si usuarios reales pueden usar la interfaz sin dificultad; es una parte natural del proceso de diseño UI/UX.
  • Prueba de accesibilidad: verifica la adecuación para usuarios de lectores de pantalla y de teclado.
  • Prueba de regresión visual: compara capturas de pantalla para detectar desajustes de diseño inesperados.
  • Pruebas de módulos compilados: piezas como los módulos Wasm que explicamos en el artículo qué es WebAssembly también necesitan su propio pipeline de pruebas.

Errores frecuentes al hacer pruebas

Escribir pruebas es una habilidad; las pruebas mal escritas pueden ser una carga en lugar de una ayuda. Estos son los errores más comunes.

  • Obsesionarse con el porcentaje de cobertura: un porcentaje alto no significa buenas pruebas; lo importante es probar los comportamientos críticos.
  • Probar la estructura interna de la aplicación: cuando se reorganiza el código, las pruebas se rompen sin motivo. Pruebe el comportamiento.
  • Pruebas E2E frágiles: en lugar de tiempos de espera fijos, use estructuras que esperen a que el elemento aparezca.
  • Conectar las pruebas a datos reales: las pruebas deben preparar sus propios datos y limpiarlos después.
  • Desactivar una prueba que falla y olvidarse: eso destruye rápidamente la confianza en las pruebas.

¿Por dónde empezar a hacer pruebas?

Añadir de golpe cientos de pruebas a un proyecto que no tiene ninguna no es realista. El camino más eficiente es empezar por la parte más arriesgada y avanzar de forma gradual. Incluso escribir una prueba por cada error corregido crea en pocos meses una red de seguridad considerable.

Al principio no hay que buscar la cobertura perfecta, sino pruebas fiables. Pocas pruebas que den siempre un resultado coherente valen más que muchas inestables.

  1. Haga una lista de las funciones relacionadas con dinero, stock y datos de usuarios.
  2. Para esas funciones, escriba primero pruebas unitarias.
  3. Añada pruebas de integración en los puntos que se conectan con sistemas externos.
  4. Monte pruebas E2E para los dos o tres flujos de usuario más críticos.
  5. Conecte las pruebas al pipeline de CI y no ponga nada en producción con una prueba en rojo.

¿Qué aportan las pruebas a la empresa?

Para el propietario de un negocio, las pruebas son una inversión invisible pero que se nota. Por eso es importante, al desarrollar soluciones de software a medida, someter a pruebas los flujos críticos. Una página de pago que se cae el día de una campaña o una tienda que muestra un stock erróneo salen mucho más caras que el coste de las pruebas.

Cuando los flujos de pedidos, facturas y stock circulan entre varios sistemas, aumenta la probabilidad de errores. Por eso, en proyectos de integración de e-commerce y de plataforma de e-commerce, construir una estructura probada y predecible reduce el coste de mantenimiento a largo plazo.

Preguntas frecuentes

01¿Hace falta escribir pruebas para un proyecto pequeño?

No es necesario probar cada línea, pero las funciones críticas relacionadas con dinero o con datos deben probarse sin falta. Empezar poco a poco le permite hacer cambios con seguridad cuando el proyecto crezca.

02¿Las pruebas manuales son totalmente innecesarias?

No. Las pruebas manuales exploratorias encuentran problemas que la automatización no prevé. Las comprobaciones repetitivas deben automatizarse y la mirada humana debe reservarse para evaluar las funciones nuevas y la experiencia.

03¿Qué es TDD?

El desarrollo guiado por pruebas (TDD) es el método de escribir primero la prueba que falla y después el código que la hace pasar. Simplifica el diseño y evita que quede código sin pruebas; eso sí, el equipo tarda en acostumbrarse a esta disciplina.

04¿Debería usar Jest o Vitest?

Ambas son herramientas maduras para pruebas unitarias y su sintaxis es parecida. En proyectos basados en Vite, Vitest se integra con más facilidad; en grandes proyectos existentes, Jest destaca por su extensión.

Las pruebas de software son la manera de detectar los errores antes que el cliente y de hacer crecer el software con seguridad. Una estructura equilibrada que toma como base las pruebas unitarias y asegura los flujos críticos con pruebas E2E es, a largo plazo, el camino de menor coste. Para un software probado y sostenible, puede conocer las soluciones de software y los servicios de integración de Aurora.