Playwright Component Testing: perché e come iniziare
Playwright per il component testing rappresenta uno dei modi più efficienti per validare componenti singoli in isolamento, prima ancora di integrarli nell'applicazione completa. A differenza dei test di integrazione o end-to-end, il component testing si focalizza su un singolo componente UI, interagisce con esso direttamente e verifica che il comportamento sia corretto. Questo articolo fornisce un setup completo per iniziare subito.
💡 Cosa imparerai
- Come installare e configurare Playwright per il component testing
- Setup del file playwright.config.ts
- Scrivere il primo test di componente
- Utilizzo di fixture e helper per semplificare i test
- Best practice per component testing su larga scala
Differenza tra Component Testing e E2E Testing
Component testing valida un singolo componente in isolamento. Il componente è renderizzato in una pagina di test dedicata, e si interagisce direttamente via DOM senza l'intera applicazione dietro. Questo rende i test più veloce, deterministici e facili da debuggare.
E2E testing, al contrario, avvia l'applicazione completa e simula il percorso reale dell'utente attraverso intere pagine. E2E è più "realista" ma anche più lento e fragile.
Prerequisiti
Per seguire questo tutorial hai bisogno di:
- Node.js 16+ e npm/yarn
- Un progetto Angular (oppure React/Vue, Playwright supporta tutti)
- Familiarità di base con TypeScript e il testing
- Editor di codice (VS Code consigliato)
Installazione di Playwright CT (Component Testing)
Playwright mette a disposizione un package dedicato al component testing: @playwright/experimental-ct-angular
(o per React/Vue). Installa via npm:
npm install --save-dev @playwright/experimental-ct-angular @playwright/test
Questo installerà il test runner, le utilità di mounting componenti, e tutti gli strumenti necessari. Non c'è bisogno di browserify, webpack, o ulteriori configurazioni — Playwright gestisce tutto internamente.
Configurazione del File playwright.config.ts
Crea (o aggiorna) il file playwright.config.ts nella root del progetto:
import {{ '{' }} defineConfig, devices {{ '}' }} from '@playwright/experimental-ct-angular';
export default defineConfig({{ '{' }}
testDir: 'src/**/*.spec.ts',
testMatch: '**/*.spec.ts',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {{ '{' }}
trace: 'on-first-retry',
screenshot: 'only-on-failure',
{{ '}' }},
webServer: {{ '{' }}
command: 'npm run ng serve',
port: 4200,
reuseExistingServer: !process.env.CI,
{{ '}' }},
projects: [
{{ '{' }}
name: 'chromium',
use: {{ '{' }} ...devices['chromium'] {{ '}' }},
{{ '}' }},
{{ '{' }}
name: 'firefox',
use: {{ '{' }} ...devices['firefox'] {{ '}' }},
{{ '}' }},
{{ '{' }}
name: 'webkit',
use: {{ '{' }} ...devices['webkit'] {{ '}' }},
{{ '}' }},
],
{{ '}' }});
La configurazione abilita:
- testDir: Individua tutti i test nelle cartelle src
- fullyParallel: Esegue i test in parallelo per velocità
- reporter: Genera report HTML interattivi
- trace e screenshot: Registra tracce e screenshot su fallimento
- projects: Testa su Chromium, Firefox, WebKit
Scrivere il Primo Test di Componente
Crea un componente di esempio (ad esempio src/app/button.component.ts):
import {{ '{' }} Component, Input, Output, EventEmitter {{ '}' }} from '@angular/core';
@Component({{ '{' }}
selector: 'app-button',
standalone: true,
template: `
<button
(click)="onClick()"
[disabled]="isDisabled"
class="btn"
>
{{ '{{' }} label {{ '}}' }}
</button>
`,
styles: [`
.btn {{ '{' }}
padding: 8px 16px;
cursor: pointer;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
{{ '}' }}
.btn:disabled {{ '{' }}
opacity: 0.5;
cursor: not-allowed;
{{ '}' }}
`],
{{ '}' }})
export class ButtonComponent {{ '{' }}
@Input() label: string = 'Click me';
@Input() isDisabled: boolean = false;
@Output() clicked = new EventEmitter<void>();
onClick() {{ '{' }}
this.clicked.emit();
{{ '}' }}
{{ '}' }}
Ora crea il test accanto (stessa cartella):
import {{ '{' }} test, expect {{ '}' }} from '@playwright/experimental-ct-angular';
import {{ '{' }} ButtonComponent {{ '}' }} from './button.component';
test.describe('ButtonComponent', () => {{ '{' }}
test('rendezza il label correttamente', async ({{ '{' }} mount {{ '}' }}) => {{ '{' }}
const component = await mount(ButtonComponent, {{ '{' }}
props: {{ '{' }} label: 'Submit' {{ '}' }},
{{ '}' }});
await expect(component).toContainText('Submit');
{{ '}' }});
test('emette evento al click', async ({{ '{' }} mount {{ '}' }}) => {{ '{' }}
const component = await mount(ButtonComponent, {{ '{' }}
props: {{ '{' }} label: 'Click' {{ '}' }},
{{ '}' }});
let eventCount = 0;
component.on('clicked', () => {{ '{' }} eventCount++; {{ '}' }});
await component.locator('button').click();
expect(eventCount).toBe(1);
{{ '}' }});
test('disabilita il pulsante quando isDisabled è true', async ({{ '{' }} mount {{ '}' }}) => {{ '{' }}
const component = await mount(ButtonComponent, {{ '{' }}
props: {{ '{' }} isDisabled: true {{ '}' }},
{{ '}' }});
const button = component.locator('button');
await expect(button).toBeDisabled();
{{ '}' }});
{{ '}' }});
Esegui i test con:
npm run test:ct
# o
npx playwright test
Fixture Personalizzate e Helper
Per ridurre la duplicazione di codice, crea fixture personalizzate. Ad esempio, un file
src/fixtures.ts:
import {{ '{' }} test as base {{ '}' }} from '@playwright/experimental-ct-angular';
export const test = base.extend({{ '{' }}
customMount: async ({{ '{' }} mount, page {{ '}' }}, use) => {{ '{' }}
// Helper per verificare accessibilità
const mountWithA11y = async (component: any, options = {{ '}' }}) => {{ '{' }}
const mounted = await mount(component, options);
// Controlla ARIA attributes
const axeResults = await page.evaluate(() => {{ '{' }}
return (window as any).axe?.run();
{{ '}' }});
return mounted;
{{ '}' }};
await use(mountWithA11y);
{{ '}' }},
{{ '}' }});
export const expect = base.expect;
Best Practice per Component Testing su Scala
Quando i test crescono, seguire queste best practice evita problemi:
1. Organizzazione Modulare
Mantieni i test vicino ai componenti:
src/
├── app/
│ ├── button/
│ │ ├── button.component.ts
│ │ └── button.component.spec.ts
│ ├── form/
│ │ ├── form.component.ts
│ │ └── form.component.spec.ts
2. Usa Data Attribute per Selezione
Evita di legare i test a classi CSS che cambiano frequentemente. Usa data-testid:
// Template
<button data-testid="submit-btn">Submit</button>
// Test
const submitBtn = component.locator('[data-testid="submit-btn"]');
await submitBtn.click();
3. Test l'Interfaccia, Non l'Implementazione
Testa i comportamenti pubblici e i risultati visibili, non i dettagli interni.
4. Mantieni i Test Isolati
Ogni test deve essere indipendente. Non fare affidamento su stato di test precedenti.
Aggiunta ai Script di package.json
Aggiungi questi script al tuo package.json per facilitare l'esecuzione:
"test:ct": "playwright test --config=playwright.config.ts",
"test:ct:ui": "playwright test --config=playwright.config.ts --ui",
"test:ct:debug": "playwright test --config=playwright.config.ts --debug",
"test:ct:report": "playwright show-report"
Integrazione con CI/CD
Per integrare in GitHub Actions:
name: Playwright Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install
- run: npm run test:ct
Troubleshooting Comune
Problema: "mount non è definito"
Soluzione: Assicurati di importare test e expect da
@playwright/experimental-ct-angular, non da @playwright/test direttamente.
Problema: Componente non renderizza
Soluzione: Accertati che il server dev sia attivo. Verifica la porta nel webServer config.
Problema: Test flaky (intermittente)
Soluzione: Usa waitFor espliciti e avoid timeouts troppo brevi.
Disabilita esecuzione parallela se ci sono effetti collaterali.
FAQ
È necessario usare mock in component testing?
No sempre. Se il componente dipende da servizi, puoi passare mock via dependency injection. Playwright CT supporta direttamente la configurazione di provider Angular.
Posso testare componenti con Reactive Forms?
Sì. Testa form come faresti normalmente. Playwright supporta completamente Reactive Forms e tutte le validazioni.
Quale è il tempo medio per eseguire suite di component test?
Dipende dal numero di test e dalla parallelizzazione. Tipicamente 100-200 component test girano in 30-60 secondi su hardware moderno.
Posso usare Playwright CT per e2e test?
Sì, ma non è il suo scopo primario. Per e2e test completi, usa @playwright/test
standard che fornisce più controllo sul browser.
Come incorporo Playwright CT nel mio CI/CD?
Aggiungi i comandi npm run test:ct nei tuoi workflow GitHub Actions, GitLab CI,
o altro. Assicurati che il server dev sia disponibile durante l'esecuzione.

Commenti
Caricamento commenti...
Accedi per commentare