# Come usare Playwright: dal primo test ai fixture

Playwright regge una suite grande con tre pezzi: progetti, un fixture per il login e `storageState` rigenerato. Comandi e costi reali.

> Pagina: https://ui.eneawork.it/blog/come-usare-playwright
> Markdown: https://ui.eneawork.it/blog/come-usare-playwright.md

*2026-11-01*

Playwright si usa in tre passi: un file di configurazione con i progetti, un fixture che prepara la pagina e un comando per eseguire la suite. La versione misurata è @playwright/test 1.64.1.

Il pacchetto @playwright/test 1.64.1 ha 104.208.877 download nella settimana chiusa il 1 novembre 2026, letti da api.npmjs.org/downloads/point/last-week/@playwright/test. I browser si scaricano a parte, con npx playwright install --with-deps; il catalogo EneUI conta 1.556 blocchi e 12.808 icone misurati da /api/stats lo stesso giorno.

## Configurazione con progetti

import { defineConfig, devices } from "@playwright/test"; export default defineConfig({ testDir: "./e2e", fullyParallel: true, forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 2 : undefined, reporter: [["html", { open: "never" }], ["github"]], use: { baseURL: "http://localhost:5173", trace: "on-first-retry" }, projects: [ { name: "setup", testMatch: /auth\.setup\.ts/ }, { name: "chromium", use: { ...devices["Desktop Chrome"], storageState: "e2e/.auth/user.json" }, dependencies: ["setup"], }, ], });

Il progetto setup esegue solo auth.setup.ts e salva lo stato di sessione; il progetto chromium dipende da setup e riusa quello stato. dependencies rende l'ordine esplicito, invece di affidarlo al nome dei file.

## Il login una volta sola

import { test as setup, expect } from "@playwright/test"; setup("autentica e salva lo stato", async ({ page }) => { await page.goto("/login"); await page.getByLabel("Email").fill("demo@example.com"); await page.getByLabel("Password").fill("demo1234"); await page.getByRole("button", { name: "Accedi" }).click(); await expect(page.getByRole("heading", { name: "Dashboard" })).toBeVisible(); await page.context().storageState({ path: "e2e/.auth/user.json" }); });

storageState scrive cookie e localStorage su disco. Il file è una credenziale: va in .gitignore, e in CI si rigenera a ogni esecuzione.

## Fixture: setup condiviso senza beforeAll

import { test as base, expect } from "@playwright/test"; import { LoginPage } from "./pages/login"; type Fixtures = { loginPage: LoginPage }; export const test = base.extend({ loginPage: async ({ page }, use) => { const loginPage = new LoginPage(page); await loginPage.goto(); await use(loginPage); }, }); export { expect };

test.extend crea un fixture tipizzato, lo esegue una volta per test e lo chiude quando il test finisce. Sostituisce beforeAll con lo stesso costo, ma senza stato condiviso fra file.

## Comandi che usi ogni giorno

npx playwright test --project=chromium npx playwright test --last-failed npx playwright test --shard=1/4 npx playwright show-report

--last-failed riesegue solo i test falliti nell'ultima run; --shard=1/4 divide la suite in quattro parti per il CI. show-report apre l'HTML con passi, trace e screenshot.

## Debug di un test rosso

npx playwright test --ui npx playwright test --debug npx playwright test -g "login" --repeat-each=10

L'interfaccia --ui fa avanzare il test passo per passo; --repeat-each=10 ripete lo stesso test dieci volte e fa emergere le instabilità che una singola run nasconde.

## Limite dichiarato

Lo stato salvato scade quando scade la sessione dell'app: se il cookie dura un'ora, la suite notturna parte con uno stato vecchio e il primo test fallisce senza un bug. Rigenera lo stato a ogni run invece di committarlo, e ricorda che con lo sharding ogni parte rifà il login.

## Dove continuare

Tre componenti da coprire con un percorso: login-form, otp-input e input; per sfogliare per categoria parti da components/lib e dalle 1.556 anteprime. L'installazione di base è in Playwright: setup e primi test; i test instabili in come trovare un flaky test. Il confronto fra framework è in Vue 3 vs React.

## FAQ

### Devo autenticarmi in ogni test?

No. Un progetto setup esegue il login una volta e salva storageState; gli altri progetti lo riusano. Il costo è che lo stato scade insieme alla sessione, quindi in CI va rigenerato.

### Che differenza c'è fra beforeAll e un fixture?

beforeAll gira una volta per file e condivide lo stato fra i test. Un fixture gira una volta per test e viene chiuso alla fine, quindi non lascia residui.

### Posso dividere la suite su più macchine?

Sì, con --shard=1/4 e valori diversi per ogni macchina. Ogni parte rifà il setup del login, quindi il risparmio cresce con la durata dei test, non con il loro numero.

### Dove finisce la trace dei test falliti?

In test-results, dentro la cartella del test. Si apre con show-report oppure con show-trace e contiene passi, rete e snapshot DOM.

### Serve un server già acceso per lanciare i test?

No, se configuri webServer nel file di configurazione: Playwright avvia il comando, attende la porta e lo spegne alla fine. Con reuseExistingServer riusa quello che hai già aperto in locale.
