Tutorial de pruebas de AngularJS para principiantes

By raman 18 Min Read

¡Bienvenido a este tutorial práctico de pruebas en AngularJS para principiantes!

Las pruebas son cruciales para construir aplicaciones AngularJS robustas, pero muchos desarrolladores las encuentran desafiantes. Este tutorial pretende hacer que probar código Angular sea sencillo mediante ejemplos fáciles de seguir.

Siguiendo los principios fundamentales de pruebas sobre aislamiento y simulación (mocking), obtendrás experiencia práctica creando tests mantenibles que detecten problemas rápidamente. Al final, tendrás las habilidades esenciales para construir aplicaciones AngularJS de nivel productivo que cumplan con los requisitos de funcionalidad, compatibilidad, confiabilidad y rendimiento.

Con un enfoque en la simplicidad y la aplicabilidad en el mundo real, este Tutorial de Pruebas en AngularJS te dará la confianza necesaria para crear aplicaciones AngularJS libres de errores.

¡Así que comencemos!

Herramientas Comunes de Pruebas en AngularJS

  • Cypress – Framework de pruebas de extremo a extremo (E2E) que se ejecuta directamente en navegadores modernos.

  • Karma – Ejecutor de pruebas (test runner) para pruebas unitarias de código AngularJS.

  • Protractor – Framework de pruebas de extremo a extremo para aplicaciones AngularJS.

Aplicaciones AngularJS – Componentes Clave

Al construir aplicaciones AngularJS, los desarrolladores trabajan con varios componentes clave que forman la estructura y funcionalidad de la app. Estos componentes trabajan juntos para crear la lógica, las vistas y los servicios subyacentes que impulsan la experiencia del usuario.

1. Controladores (Controllers):
Estas son funciones JavaScript que proporcionan la lógica de negocio detrás de las vistas. En el patrón de diseño MVC, los controladores actúan como el «control», manejando la entrada del usuario, manipulando datos y decidiendo qué contenido renderizar. En la práctica, los desarrolladores crean controladores para conectar los ámbitos (scopes) de AngularJS a las vistas.

2. Vistas (Views):
Definidas usando HTML, las vistas renderizan datos desde los controladores y modelos. Una característica clave es su uso del enlace de datos (data binding) para actualizarse automáticamente cuando cambian los datos del modelo, lo que elimina la necesidad de actualizaciones manuales.

3. Modelos (Models):
Pueden ser objetos JavaScript simples o derivarse de un framework de persistencia como Firebase. Su propósito es representar los conceptos de datos de la aplicación en una estructura adecuada para las vistas.

4. Servicios (Services):
Los servicios de AngularJS realizan tareas como llamadas a API sin saturar el código del controlador. Además, los servicios pueden compartirse en toda la aplicación, lo que aumenta la flexibilidad y la reutilización.

5. Módulos (Modules):
Los desarrolladores definen módulos usando ng-app para declarar las dependencias de la aplicación y el componente de entrada. Este enfoque mejora la organización y mantiene una separación de responsabilidades (separation of concerns).

Al aprovechar estos componentes clave, los desarrolladores pueden construir aplicaciones web AngularJS robustas con una clara separación de responsabilidades entre las diferentes capas. En última instancia, la flexibilidad de los componentes de AngularJS permite crear experiencias de usuario complejas e impulsadas por datos.

Pruebas Unitarias en AngularJS

Las pruebas unitarias en AngularJS son esenciales para construir aplicaciones de alta calidad porque validan que componentes individuales como controladores, directivas y servicios funcionen como se espera.

Los beneficios clave incluyen: detectar errores temprano, permitir la refactorización segura del código y simplificar la integración de código de diferentes desarrolladores. Por lo tanto, antes de que una aplicación AngularJS pueda considerarse lista para producción, debe someterse a pruebas unitarias exhaustivas para detectar problemas en la etapa más temprana posible.

Como resultado, unas pruebas unitarias robustas conducen a aplicaciones que son más confiables, mejor optimizadas y más alineadas con los requisitos del negocio. También permiten diagnosticar y corregir errores rápidamente, dando a los usuarios una mayor confianza en las capacidades de la aplicación.

Fundamentos de las Pruebas Unitarias en AngularJS

Al escribir pruebas unitarias para tu código AngularJS, seguir estos fundamentos garantizará que tu conjunto de pruebas sea robusto, mantenible y sostenible a medida que tu aplicación evoluciona:

  • Aísla las Dependencias: Cada prueba unitaria debe probar un componente específico de forma aislada, sin depender de otros módulos o dependencias externas. Usa mocks, espías (spies) y stubs para simular dependencias.

  • Organizar, Actuar, Afirmar (AAA): Estructura tu prueba en tres secciones claramente definidas: organiza los datos/entradas de la prueba, ejecuta la lógica a probar (actuar) y afirma que se produjo la salida esperada.

  • Una Afirmación por Prueba: Cada caso de prueba debe validar un comportamiento o salida para facilitar la identificación de lo que falló. Evita afirmaciones que verifiquen múltiples salidas.

  • Haz las Pruebas Independientes: Escribe casos de prueba que configuren sus propios datos de prueba para que puedan ejecutarse de forma independiente y no dependan del orden de ejecución. Esto es especialmente útil al ejecutar pruebas en paralelo.

  • Mantén las Pruebas Breves y Legibles: Divide los casos de prueba extensos en funciones auxiliares más pequeñas que prueben un solo comportamiento o una subunidad de un componente.

Seguir estas pautas fundamentales garantizará que tu conjunto de pruebas unitarias de AngularJS permanezca robusto y fácil de extender con el tiempo a medida que crece la complejidad de la aplicación.

Configurar tu Entorno

Para comenzar con las pruebas unitarias, solo sigue estos pasos:

1. Instalar los Requisitos Previos

  • Instala Node.js en tu computadora, ya que es el framework sobre el que construiremos.

  • Abre tu editor de código favorito (por ejemplo, Visual Studio Code, Brackets o Sublime Text).

2. Crear la Estructura del Proyecto

  • Crea una nueva carpeta llamada «unit-testing» en tu computadora usando el comando mkdir. Aquí es donde almacenarás tus archivos de prueba.

  • Abre la carpeta unit-testing en tu editor de código y abre una ventana de terminal dentro de ella.

3. Inicializar el Proyecto e Instalar las Dependencias

Crea un archivo package.json e instala los paquetes necesarios:

bash
npm init
npm i angular --save
npm i -g karma --save-dev
npm i karma-jasmine jasmine-core --save-dev
npm i angular-mocks --save-dev
npm i karma-chrome-launcher --save-dev

4. Configurar Karma

  • En tu carpeta unit-testing, crea dos nuevas carpetas llamadas app y test.

  • Luego, dentro de la carpeta unit-testing, crea un nuevo archivo llamado karma.config.js.

  • Abre karma.config.js en tu editor de código y escribe karma init. Esto inicializará un repositorio vacío con algunas configuraciones estándar.

  • Se te harán una serie de preguntas sobre cómo deseas configurar Karma. Respóndelas según tus preferencias (los valores predeterminados están bien).

Pruebas de Extremo a Extremo (E2E) en AngularJS con Protractor o Cypress

Las pruebas de extremo a extremo (E2E) simulan cómo un usuario real interactuaría con tu aplicación de principio a fin. Si bien las pruebas unitarias se limitan a evaluar partes individuales del código de forma aislada, las pruebas E2E son significativas para detectar problemas que surgen cuando unes esos bloques de construcción en flujos de trabajo completos.

Por ejemplo, las pruebas unitarias podrían validar que un formulario de inicio de sesión y una consulta a la base de datos funcionen como se espera. Sin embargo, las pruebas E2E van más allá al iniciar sesión con credenciales reales, hacer clic en diferentes lugares y extraer datos reales.

En consecuencia, las pruebas E2E brindan confianza en que tu aplicación funciona sin problemas en condiciones del mundo real, encontrando brechas que caen entre las pruebas unitarias y de integración.

Beneficios de las Pruebas de Extremo a Extremo

Realizar pruebas E2E integrales proporciona varios beneficios importantes:

  • Detecta más errores desde el principio, lo que lleva a un software de mayor calidad.

  • Asegura que todos los componentes trabajen juntos sin problemas, aumentando la confianza.

  • Modela flujos de trabajo de usuarios del mundo real, mejorando la experiencia del usuario.

  • Ahorra tiempo y dinero al corregir problemas antes que después.

  • Promueve la colaboración entre equipos que trabajan en diferentes componentes.

  • Automatiza pruebas repetitivas, aumentando la productividad.

  • Acelera el tiempo de llegada al mercado al reducir defectos antes del lanzamiento.

En resumen, las pruebas E2E ofrecen un software más robusto y confiable que satisface las necesidades empresariales y de los usuarios al validar la calidad de principio a fin en toda la aplicación.

1. Configurar Cypress para Pruebas E2E
Configurar Cypress es sencillo:

  • Crea una nueva carpeta de proyecto e inicialízala: npm init

  • Instala Cypress en la carpeta del proyecto: npm install cypress --save-dev (o yarn add cypress --dev)

¡Y eso es todo! Con Cypress instalado, ahora puedes comenzar a crear y ejecutar pruebas de extremo a extremo para tu aplicación.

2. Instalar Protractor para Pruebas E2E

Requisito previo: Node.js debe estar instalado.

  • Abre una terminal y escribe: npm install -g protractor

    • Esto instala dos herramientas de línea de comandos: protractor (el ejecutor de pruebas) y webdriver-manager (gestiona el controlador web de Selenium).

  • Verifica la instalación con: protractor --version

Esto instalará la última versión de Protractor globalmente, haciendo que el ejecutor de pruebas y el administrador de Selenium estén disponibles desde la línea de comandos.

Pruebas de Integración en AngularJS

Las pruebas de integración validan que diferentes unidades o componentes de una aplicación funcionen correctamente cuando se combinan.

Es importante distinguir esto de otros tipos de prueba:

  • Las pruebas unitarias se centran en unidades individuales de forma aislada.

  • Las pruebas de extremo a extremo (E2E) replican flujos de trabajo completos del usuario.

Sin embargo, las pruebas de integración confirman que las interacciones entre las unidades integradas funcionan como se espera. Por ejemplo, puede probar que la capa de interfaz de usuario llame y muestre con éxito datos desde un endpoint de API.

Entonces, mientras las pruebas unitarias examinan módulos individuales y las E2E verifican flujos generales, las pruebas de integración se centran en verificar las conexiones entre componentes integrados.

Configurar una Prueba de Integración en Angular

Paso 1: Crear un Nuevo Proyecto Angular

Para crear un nuevo proyecto Angular, escribe el siguiente comando en tu terminal:

bash
ng new angular-todo-app

Espera a que Angular configure tu nuevo proyecto.

Paso 2: Aprovechar los Archivos de Prueba Generados Automáticamente

Angular genera automáticamente archivos de prueba (*.spec.ts) para componentes TypeScript. Para nuestra prueba de integración, utilizaremos el archivo app.component.spec.ts predeterminado que Angular genera en la carpeta raíz app. Este archivo spec está conectado al principal app.component.ts y está preconfigurado para pruebas.

Paso 3: Crear y Configurar un Conjunto de Pruebas (Test Suite)

Abre app.component.specs.ts y crea un nuevo conjunto de pruebas con el siguiente código:

typescript
describe('TodoList Integration', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;
  let service: TodoService;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [FormsModule],
      declarations: [AppComponent, TodoComponent],
      providers: [
        {
          provide: TodoService,
          useValue: {
            getTasks: () => {
              return dummyTodos;
            }
          }
        }
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    service = TestBed.inject(TodoService);
  });
});

const dummyTodos = [
  {
    id: 1,
    title: 'Todo 1',
    completed: false
  },
  {
    id: 2,
    title: 'Todo 2',
    completed: false
  }
];

Esta configuración incluye una configuración de prueba asíncrona, compilación de módulos y definición de datos ficticios (dummy data).

Paso 4: Escribir la Prueba de Integración

typescript
it('should load todos from service', async(() => {
  fixture.detectChanges();
  expect(component.todos.length).toBe(2);
  expect(service.getTasks()).toEqual(dummyTodos);
}));

Esta prueba activa el enlace de datos y afirma que los datos del componente coinciden con los datos del servicio.

Paso 5: Ejecutar la Prueba

Para ejecutar las pruebas de integración, navega a la raíz del proyecto en una terminal y ejecuta:

bash
ng test

O para ejecutar un archivo específico:

bash
ng test --include app.component.spec.ts

Angular configurará el entorno de prueba y reportará los resultados.

Probar Servicios en AngularJS

Los servicios son uno de los bloques de construcción más importantes en las aplicaciones AngularJS, ya que proporcionan lógica de negocio reutilizable. Pero, ¿cómo te aseguras de que tus servicios tengan una cobertura de pruebas robusta?

Esta sección ofrece mejores prácticas para las pruebas unitarias de tus servicios para que puedas:

  • Configurar el framework de pruebas de AngularJS desde cero.

  • Simular (mock) efectivamente las dependencias con las que interactúan tus servicios.

  • Validar el comportamiento del servicio a través de especificaciones de prueba (test specs) bien estructuradas.

  • Identificar casos de uso relevantes para maximizar la cobertura.

Probar los servicios a fondo descubre fallos temprano y da confianza en que las reglas de negocio hacen cumplir la integridad de los datos.

Probar Controladores en AngularJS

Los controladores son la columna vertebral del comportamiento dinámico en las aplicaciones AngularJS, conectando la interfaz de usuario con la lógica subyacente. Por lo tanto, probar los controladores a fondo previene problemas en la interfaz en el futuro.

Un conjunto de pruebas confiable te permite simular interacciones del usuario y validar que los controladores transformen y presenten los datos correctamente.

Inyectar Servicios en Controladores AngularJS

Al realizar pruebas unitarias de controladores, necesitarás simular sus dependencias. Hay dos formas estándar de inyectar estas dependencias:

1. Array en Línea

Define un array en línea que enumere las dependencias; útil para casos simples:

javascript
angular.module('myApp')
.controller('MyController', ['$scope', 'MyService', function($scope, MyService) {
  // ...
}]);

2. Propiedad $inject

Alternativamente, establece una propiedad $inject en la función del controlador:

javascript
angular.module('myApp')
.controller('MyController', MyController);

MyController.$inject = ['$scope', 'MyService'];

function MyController($scope, MyService) {
 // ...
}

Ambos enfoques funcionan para simular en pruebas. La clave es enumerar las dependencias explícitamente para asegurar que se resuelvan correctamente después de la minificación del código.

Conclusión de nuestro Tutorial de Pruebas en AngularJS

¡Felicidades por completar nuestro tutorial de pruebas en AngularJS! Ahora tienes el conocimiento fundamental y las habilidades para comenzar a construir conjuntos de pruebas robustos para tus aplicaciones AngularJS.

Si bien las pruebas pueden parecer abrumadoras al principio, perseverar con ellas tiene enormes dividendos en estabilidad de la aplicación, entrega más rápida y experiencia de usuario mejorada. Recuerda aplicar las mejores prácticas de pruebas, como el aislamiento, la simulación y la organización legible de las pruebas.

Esto era solo el comienzo. Hay mucho más por explorar, como probar directivas, pruebas de regresión visual y técnicas avanzadas para escenarios de prueba complicados.

La clave es mantener una actitud positiva, comenzar a probar temprano, refactorizar regularmente y pedir ayuda cuando la necesites. Lo más importante es que la práctica continua consolidará lo que has aprendido y generará confianza real.

Share This Article
Leave a comment