Testing
Policy dei test in FireFeed — naming convention, env-gated skip, comandi.
FireFeed ha tre tipi di test, distinti dal naming del file. La policy è centrata su una regola: pnpm test su una shell pulita senza Postgres deve essere verde.
Tipi di test
| Tipo | Naming | Dipendenze esterne | Quando girare |
|---|---|---|---|
| Unit | *.unit.test.ts o *.test.ts | Nessuna | Sempre, in CI ad ogni PR |
| Integration | *.int.test.ts + pipeline-integration.test.ts | DATABASE_URL (Postgres) | Locale con docker compose up -d db; in CI con servizio Postgres |
| Stress / Perf | *.stress.test.ts, *.perf.test.ts | Postgres + carico CPU/memoria | On-demand prima di major release |
Stress/perf sono esclusi dai default via vitest.config.ts (exclude: ["**/*.stress.test.ts", "**/*.perf.test.ts"]).
Pattern env-gated skip
Gli integration test usano describe.skip quando manca l'ambiente. Pattern canonico:
import { describe, beforeAll, ... } from "vitest";
// Integration test: skipped if DATABASE_URL is not configured.
const describeDb = process.env.DATABASE_URL ? describe : describe.skip;
describeDb("MergeService merge-by-key", () => {
let pool: pg.Pool;
beforeAll(() => {
pool = new pg.Pool({ connectionString: process.env.DATABASE_URL });
});
// ...
});Niente throw new Error("DATABASE_URL required"): un test che throw fa fallire la suite, uno con describe.skip la lascia verde con un marker ↓ esplicito nell'output.
createPrismaClient lazy
createPrismaClient() in packages/shared/src/db.ts ritorna un Proxy<PrismaClient> che istanzia la connection al primo property access, non al constructor. Significa che import { processRulesJob } from "../jobs/rules.job.js" (che a sua volta fa const prisma = createPrismaClient() a module-load) non throw se DATABASE_URL manca — solo la prima query lo fa. Questo è ciò che permette al describe.skip di essere efficace anche su file che importano job worker.
Comandi
# Suite default — gira unit + integration (gli integration auto-skip se manca DB)
pnpm test
# Solo unit, verbose ridotto
pnpm test:unit
# Integration con reporter verbose (per debug)
DATABASE_URL=postgresql://... pnpm test:integration
# Watch mode (sviluppo)
pnpm test:watch
# Coverage (per package)
pnpm test:coverage
# Stress test on-demand (NON in CI di default)
pnpm -F @firefeed/worker exec vitest run **/*.stress.test.tsCI
In CI deve essere settato DATABASE_URL puntando a un Postgres ephemeral (services.postgres nel workflow). Con DB presente, lo skip non scatta più e gli integration girano davvero. Senza DB → silently skipped (pnpm test:unit resta verde, ma non si copre il path multi-tenant).
Regola operativa: il workflow CI deve verificare che
DATABASE_URLsia settato. Se manca, è un misconfiguration, non uno skip legittimo.
Aggiungere un nuovo test integration
- Naming:
<feature>.int.test.tsinpackages/<package>/src/__tests__/. - Importa
describedavitest, creaconst describeDb = process.env.DATABASE_URL ? describe : describe.skip;. - Tutto il
describe(e i suoibeforeAll/afterAll) deve stare sottodescribeDb, non a livello modulo — altrimenti i setup hook girano anche quando il describe è skipped. - Usa
process.env.DATABASE_URLdirettamente dentro i hook, non variabili top-level.
File coperti dal pattern (oggi)
packages/worker/src/__tests__/import-provenance.int.test.tspackages/worker/src/__tests__/merge-by-key.int.test.tspackages/worker/src/__tests__/multi-tenancy-isolation.int.test.tspackages/worker/src/__tests__/pipeline-integration.test.tspackages/worker/src/__tests__/rules-per-export-scope.int.test.tspackages/worker/src/__tests__/rules-streaming.int.test.tspackages/worker/src/__tests__/rules-to-export-boundary.int.test.tspackages/shared/src/__tests__/schema-service.test.ts
Cosa NON è coperto
- E2E browser: Playwright non ancora in setup. La pipeline di product UI è validata manualmente (audit WS6).
- Load testing: solo gli stress test (
rules-stress,rules-1m.stress) eseguono carichi sintetici. Niente test su SLA latency end-to-end della pipeline produzione.