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
-
Crear una nova aplicació Angular:
ng new my-app cd my-app
-
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 aapp.component.ts
.
- Els fitxers de proves es troben al mateix directori que els fitxers de codi, amb l'extensió
-
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:
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
- Crea un component
UserComponent
que tingui una propietatname
i un mètodegetName()
. - 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
- Crea un servei
AuthService
que tingui un mètodeisAuthenticated()
que retornitrue
ofalse
. - 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
- Què és Angular?
- Configuració de l'entorn de desenvolupament
- Arquitectura d'Angular
- Primera aplicació Angular
Mòdul 2: Components d'Angular
- Comprendre els components
- Crear components
- Plantilles de components
- Estils de components
- Interacció de components
Mòdul 3: Enllaç de dades i directives
- Interpolació i enllaç de propietats
- Enllaç d'esdeveniments
- Enllaç de dades bidireccional
- Directives integrades
- Directives personalitzades
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
- Introducció al client HTTP
- Fer sol·licituds HTTP
- Gestionar respostes HTTP
- Utilitzar observables
- Gestió d'errors
Mòdul 8: Gestió d'estat
- Introducció a la gestió d'estat
- Utilitzar serveis per a la gestió d'estat
- NgRx Store
- NgRx Effects
- NgRx Entity
Mòdul 9: Proves a Angular
- Proves unitàries
- Proves de components
- Proves de serveis
- Proves de cap a cap
- Simulació de dependències
Mòdul 10: Conceptes avançats d'Angular
- Angular Universal
- Optimització del rendiment
- Internacionalització (i18n)
- Tubs personalitzats
- Animacions d'Angular