Les proves unitàries són una part fonamental del desenvolupament de programari, ja que permeten verificar que les unitats individuals de codi funcionen correctament. En el context d'Angular, les proves unitàries es realitzen principalment amb el framework de proves Jasmine i l'eina de test Karma.

Objectius del Mòdul

  • Comprendre la importància de les proves unitàries.
  • Aprendre a configurar l'entorn de proves en una aplicació Angular.
  • Escriure i executar proves unitàries per components, serveis i altres unitats de codi.

Continguts

Introducció a les proves unitàries

Les proves unitàries són proves automàtiques que verifiquen el comportament d'una unitat de codi, com ara una funció, un mètode o una classe. Aquestes proves ajuden a detectar errors en una fase primerenca del desenvolupament i faciliten el manteniment del codi.

Beneficis de les proves unitàries

  • Detecció primerenca d'errors: Les proves unitàries permeten identificar errors abans que el codi arribi a producció.
  • Facilitat de manteniment: Amb proves unitàries, és més fàcil refactoritzar el codi sense introduir nous errors.
  • Documentació: Les proves unitàries serveixen com a documentació viva del comportament esperat del codi.

Configuració de l'entorn de proves

Angular ve amb una configuració de proves predefinida que utilitza Jasmine i Karma. Quan es crea una nova aplicació Angular amb Angular CLI, l'entorn de proves ja està configurat.

Passos per configurar l'entorn de proves

  1. Crear una nova aplicació Angular:

    ng new my-app
    cd my-app
    
  2. Estructura de fitxers de proves:

    • Els fitxers de proves es troben al mateix directori que els fitxers de codi, amb l'extensió .spec.ts.
    • Exemple: app.component.spec.ts per a app.component.ts.
  3. Fitxers de configuració:

    • karma.conf.js: Configuració de Karma.
    • tsconfig.spec.json: Configuració de TypeScript per a les proves.

Escriure proves unitàries

Les proves unitàries en Angular es defineixen en fitxers .spec.ts utilitzant Jasmine. A continuació es mostra un exemple bàsic de prova unitària per a un component.

Exemple de prova unitària per a un component

import { TestBed, ComponentFixture } from '@angular/core/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [AppComponent]
    }).compileComponents();

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

  it('hauria de crear el component', () => {
    expect(component).toBeTruthy();
  });

  it('hauria de tenir com a títol "my-app"', () => {
    expect(component.title).toEqual('my-app');
  });

  it('hauria de renderitzar el títol', () => {
    const compiled = fixture.nativeElement;
    expect(compiled.querySelector('.content span').textContent).toContain('my-app app is running!');
  });
});

Explicació del codi

  • TestBed: És una utilitat d'Angular per configurar i inicialitzar l'entorn de proves.
  • ComponentFixture: Proporciona accés a una instància del component i al seu element HTML.
  • beforeEach: Configura l'entorn de proves abans de cada prova.
  • it: Defineix una prova individual.

Executar proves unitàries

Per executar les proves unitàries, utilitza la següent comanda:

ng test

Aquesta comanda iniciarà Karma, que executarà les proves i mostrarà els resultats en una finestra del navegador.

Exemples pràctics

Prova unitària per a un servei

import { TestBed } from '@angular/core/testing';
import { DataService } from './data.service';

describe('DataService', () => {
  let service: DataService;

  beforeEach(() => {
    TestBed.configureTestingModule({});
    service = TestBed.inject(DataService);
  });

  it('hauria de ser creat', () => {
    expect(service).toBeTruthy();
  });

  it('hauria de retornar dades', () => {
    const data = service.getData();
    expect(data).toEqual(['data1', 'data2', 'data3']);
  });
});

Prova unitària per a una directiva

import { TestBed, ComponentFixture } from '@angular/core/testing';
import { HighlightDirective } from './highlight.directive';
import { Component } from '@angular/core';

@Component({
  template: `<p appHighlight="yellow">Text de prova</p>`
})
class TestComponent {}

describe('HighlightDirective', () => {
  let fixture: ComponentFixture<TestComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [HighlightDirective, TestComponent]
    });
    fixture = TestBed.createComponent(TestComponent);
    fixture.detectChanges();
  });

  it('hauria de destacar el text amb color groc', () => {
    const p: HTMLElement = fixture.nativeElement.querySelector('p');
    expect(p.style.backgroundColor).toBe('yellow');
  });
});

Exercicis

Exercici 1: Prova unitària per a un component

  1. Crea un component UserComponent que tingui una propietat name i un mètode getName().
  2. Escriu una prova unitària per verificar que el component es crea correctament i que el mètode getName() retorna el nom correcte.

Exercici 2: Prova unitària per a un servei

  1. Crea un servei AuthService que tingui un mètode isAuthenticated() que retorni true o false.
  2. Escriu una prova unitària per verificar que el servei es crea correctament i que el mètode isAuthenticated() funciona com s'espera.

Solucions

Solució Exercici 1

// user.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-user',
  template: `<p>{{ name }}</p>`
})
export class UserComponent {
  name: string = 'John Doe';

  getName(): string {
    return this.name;
  }
}

// user.component.spec.ts
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { UserComponent } from './user.component';

describe('UserComponent', () => {
  let component: UserComponent;
  let fixture: ComponentFixture<UserComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [UserComponent]
    }).compileComponents();

    fixture = TestBed.createComponent(UserComponent);
    component = fixture.componentInstance;
  });

  it('hauria de crear el component', () => {
    expect(component).toBeTruthy();
  });

  it('hauria de tenir com a nom "John Doe"', () => {
    expect(component.name).toEqual('John Doe');
  });

  it('hauria de retornar el nom correcte', () => {
    expect(component.getName()).toEqual('John Doe');
  });
});

Solució Exercici 2

// auth.service.ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class AuthService {
  isAuthenticated(): boolean {
    return true; // o alguna lògica d'autenticació
  }
}

// auth.service.spec.ts
import { TestBed } from '@angular/core/testing';
import { AuthService } from './auth.service';

describe('AuthService', () => {
  let service: AuthService;

  beforeEach(() => {
    TestBed.configureTestingModule({});
    service = TestBed.inject(AuthService);
  });

  it('hauria de ser creat', () => {
    expect(service).toBeTruthy();
  });

  it('hauria de retornar true per isAuthenticated', () => {
    expect(service.isAuthenticated()).toBeTrue();
  });
});

Conclusió

Les proves unitàries són essencials per garantir la qualitat i la fiabilitat del codi. En aquest mòdul, hem après a configurar l'entorn de proves, escriure i executar proves unitàries per components, serveis i altres unitats de codi en una aplicació Angular. Amb la pràctica, les proves unitàries es convertiran en una part integral del teu flux de treball de desenvolupament.

Curs d'Angular

Mòdul 1: Introducció a Angular

Mòdul 2: Components d'Angular

Mòdul 3: Enllaç de dades i directives

Mòdul 4: Serveis i injecció de dependències

Mòdul 5: Enrutament i navegació

Mòdul 6: Formularis a Angular

Mòdul 7: Client HTTP i observables

Mòdul 8: Gestió d'estat

Mòdul 9: Proves a Angular

Mòdul 10: Conceptes avançats d'Angular

Mòdul 11: Desplegament i millors pràctiques

© Copyright 2024. Tots els drets reservats