
Testing Best Practices
- 55 installs
- 18 repo stars
- Updated June 8, 2026
- andrelandgraf/fullstackrecipes
Testing-best-practices is a Claude skill that helps developers choose between Playwright, integration, and unit tests and run them against isolated Neon database branches.
About
Testing-best-practices helps a developer choose the right test type and write it correctly. It ranks Playwright browser tests over integration tests over unit tests, and runs everything against an isolated Neon database branch that auto-deletes. A developer uses it when adding, running, or debugging tests for a feature.
- Ranks test types Playwright > integration > unit by 'how would a user verify this'
- Runs all tests against a disposable, schema-only Neon branch that auto-deletes after 1 hour
- Enforces per-suite test data isolation with unique users
Testing Best Practices by the numbers
- 55 all-time installs (skills.sh)
- Ranked #1,191 of 2,153 Testing & QA skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
testing-best-practices capabilities & compatibility
- Capabilities
- testing · debugging
- Works with
- playwright · postgres
- Use cases
- testing
What testing-best-practices says it does
All tests run against an isolated, schema-only Neon branch that auto-deletes after 1 hour.
Ask "how would a user verify this works?" and pick the highest applicable tier:
npx skills add https://github.com/andrelandgraf/fullstackrecipes --skill testing-best-practicesAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 55 |
|---|---|
| repo stars | ★ 18 |
| Last updated | June 8, 2026 |
| Repository | andrelandgraf/fullstackrecipes ↗ |
What it does
Helps a developer pick the right test tier and write tests that run against an isolated Neon branch.
Who is it for?
Developers on a Next.js/Bun stack deciding which test tier to write and how to isolate test data.
Skip if: Projects not using Playwright, Bun, or Neon branching.
When should I use this skill?
Adding, running, or debugging tests for a feature.
What you get
- Playwright, integration, or unit test files
- Isolated per-suite test data
By the numbers
- 3 test tiers (Playwright, integration, unit)
- Neon branch auto-deletes after 1 hour
Files
Testing Best Practices
Choose the right test type, isolate data per suite, and run against a disposable Neon branch.
Prerequisites
Complete these setup recipes first:
- Browser Tests with Playwright
- Integration Tests
- Unit Tests with Bun
Choosing a Test Type
Ask "how would a user verify this works?" and pick the highest applicable tier:
1. Playwright (default) — UI interactions, visual feedback, form validation, multi-step flows, protected routes, accessibility. 2. Integration — API responses (status, JSON shape), DB state after operations, server logic without UI, or when Playwright is too slow/complex. 3. Unit — pure functions with complex logic, many edge cases, or type narrowing/assertions with no external dependencies.
Running
All tests run against an isolated, schema-only Neon branch that auto-deletes after 1 hour.
bun run test # all tests
bun run test:playwright # browser only
bun run test:integration # integration only
bun run test:unit # unit onlyFolder Structure
Unit tests are co-located; Playwright and integration tests live under tests/.
src/lib/<domain>/<file>.test.ts # unit (co-located)
tests/integration/<feature>.test.ts
tests/playwright/<feature>.spec.ts
tests/playwright/lib/ # Playwright helpersWriting Tests
Playwright spec:
import { test, expect } from "@playwright/test";
test.describe("Feature Name", () => {
test("should do expected behavior", async ({ page }) => {
await page.goto("/feature");
});
});Integration — import the route handler directly instead of going over HTTP:
import { describe, it, expect } from "bun:test";
import { GET } from "@/app/api/feature/route";
describe("GET /api/feature", () => {
it("returns expected response", async () => {
const response = await GET();
expect(response.status).toBe(200);
const data = await response.json();
expect(data.value).toBeDefined();
});
});Unit (co-located):
import { describe, it, expect } from "bun:test";
import { myFunction } from "./my-file";
describe("myFunction", () => {
it("returns expected value", () => {
expect(myFunction()).toBe("expected");
});
});Test Data Isolation
Tests run in parallel against the shared branch, so each suite must own its data. Generate unique users per spec (e.g. auth-test-${uuid}@example.com), avoid shared resources, and rely on the branch TTL for cleanup — never assume data from another test exists.
const testUser = await createTestUser({
email: `auth-test-${uuid}@example.com`,
});Common Patterns
// Protected route (Playwright)
test("redirects unauthenticated user", async ({ page }) => {
await page.goto("/protected-page");
await expect(page).toHaveURL(/sign-in/);
});
// Error state (Playwright)
test("shows error for invalid input", async ({ page }) => {
await page.goto("/form");
await page.getByRole("button", { name: /submit/i }).click();
await expect(page.getByText(/error|required/i)).toBeVisible({
timeout: 5000,
});
});Debugging
bunx playwright test --headed # watch the browser
bunx playwright test --debug # step through
bunx playwright show-report # HTML report
bun test --only "test name" # run a single test
bun test --watch # re-run on changeFailed Playwright runs save screenshots and traces to test-results/ — check there when CI fails.
Related skills
FAQ
Which test type is the default?
Playwright browser tests are the default; drop to integration or unit only when the higher tier does not apply.
How is test data isolated?
Each suite generates unique users (e.g. auth-test-<uuid>@example.com) and relies on the Neon branch TTL for cleanup.