Skip to main content

Testing and Verification

(Verifying the risks that matter)

Senior rule:

Testing is not about count. Testing is about risk placement.

Atlas has dashboard filters, billing settings, permissions, charts, and export flows. A senior test strategy asks which failures are expensive and which layer catches them with the least brittleness.

Conceptual Model

LayerBest forAvoid
Unitpure logic, formatting, reducerstesting framework internals
ComponentUI behavior in isolationmocking away the risk
Integrationmodule and data collaborationgiant unclear fixtures
ContractAPI assumptionsonly testing happy paths
E2Ecritical journeyscovering every detail
Visuallayout regressionsunstable screenshots
Accessibilitysemantics and interactionassuming automation is enough
Performancebudget regressionslab-only confidence

Unit Test Example

type Money = { cents: number; currency: "USD" };

export function formatMoney(value: Money) {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: value.currency,
}).format(value.cents / 100);
}

Unit tests are strongest when logic is deterministic and isolated.

Playwright E2E Example

import { test, expect } from "@playwright/test";

test("filters reports by region", async ({ page }) => {
await page.goto("/dashboard/reports");

await page.getByLabel("Region").selectOption("Europe");
await page.getByRole("button", { name: "Apply filters" }).click();

await expect(page.getByRole("status")).toHaveText("Report updated");
await expect(page.getByRole("table", { name: "Revenue report" })).toContainText(
"Europe"
);
});

Prefer user-facing locators. They make tests more stable and improve accessibility pressure.

Cross-Browser Projects

import { defineConfig, devices } from "@playwright/test";

export default defineConfig({
projects: [
{ name: "chromium", use: { ...devices["Desktop Chrome"] } },
{ name: "firefox", use: { ...devices["Desktop Firefox"] } },
{ name: "webkit", use: { ...devices["Desktop Safari"] } },
{ name: "mobile", use: { ...devices["Pixel 7"] } },
],
use: {
trace: "on-first-retry",
},
});

Run all browsers for flows where browser differences are a real product risk. Use a smaller smoke set if full coverage is too expensive.

Avoiding Flakiness

Bad:

await page.waitForTimeout(2000);
await expect(page.locator(".status")).toHaveText("Done");

Better:

await expect(page.getByRole("status")).toHaveText("Done");

Web-first assertions retry until the condition is met or times out.

Contract Test Shape

import { z } from "zod";

const ReportResponse = z.object({
rows: z.array(
z.object({
id: z.string(),
revenueCents: z.number(),
})
),
});

export async function parseReport(response: unknown) {
return ReportResponse.parse(response);
}

This guards frontend assumptions about backend shape. It does not replace backend tests.

Accessibility Verification

Automated checks are useful, but critical flows need manual review:

  • keyboard only
  • screen reader path
  • visible focus
  • reduced motion
  • zoom and reflow
  • form errors

Mini Case Study: Flaky Filter Test

Atlas had a flaky e2e test for report filtering. It used CSS selectors, arbitrary waits, and shared test data.

Fix:

  • use role and label locators
  • seed data per test
  • assert the status message instead of sleeping
  • keep each test isolated
  • collect traces on retry

Flakiness revealed unclear loading and uncontrolled state.

Common Failure Modes

  • E2E tests for logic that belongs in unit tests.
  • Unit tests that mirror implementation.
  • Tests depending on execution order.
  • Arbitrary sleeps.
  • Mocking away auth, latency, and error states.
  • No accessibility or performance verification.

Review Checklist

  • Is the highest product risk tested somewhere?
  • Are e2e tests user-visible and resilient?
  • Are tests isolated?
  • Are API assumptions validated?
  • Are error and empty states tested?
  • Are accessibility checks included for critical flows?
  • Are performance budgets verified?

Senior Deep Dive: Risk-Based Verification

Senior engineers do not ask "do we have enough tests?" They ask "which important failures can still escape, and what is the cheapest reliable place to catch them?"

Risk placement matrix

RiskBest verification layerWhy
pure formatting or calculationunitdeterministic and cheap
component keyboard behaviorcomponent plus accessibility checksfast and behavior-focused
API shape assumptioncontract/integrationcatches client/server drift
permission boundaryintegration plus E2E negative pathneeds real auth behavior
critical purchase/export journeyE2Eproves cross-system user outcome
visual layout of stable componentvisual regressioncatches CSS/design drift
performance budgetCI budget plus RUMlab catches obvious regressions, field proves reality
browser compatibilitytargeted cross-browser E2Eavoids false confidence from Chromium only

The weakness this corrects: teams often overuse E2E tests for everything or unit tests for risks that only appear at integration boundaries.

Test design quality

A good test has a clear behavior name, realistic setup, minimum mocking necessary, user-facing interaction where UI is involved, failure messages that point toward the cause, stable selectors based on roles/names where possible, and one meaningful reason to fail.

A weak test snapshots large unstable output, asserts implementation details, mocks away the contract being tested, depends on timing guesses, passes even when the user journey is broken, or fails with no diagnostic signal.

Contract testing for frontend seniors

Frontend contract tests should prove assumptions such as required fields exist, optional fields can be missing, enum values can evolve, error shapes are understood, pagination and sorting semantics match UI expectations, permissions are enforced when UI is wrong, and stale client versions fail safely.

This is where wider software-engineering material matters: good code makes contracts hard to misuse, and architecture makes important contracts explicit.

Flake triage protocol

Do not normalize flakiness. Classify it:

Flake sourceFix
waiting for wrong thingwait for user-visible state or network contract
shared test dataisolate data or reset state
animation/timingdisable motion in test or assert final state
race in product codefix product state machine, not the test
environment dependencymock at boundary or improve test environment
over-broad E2Emove behavior to lower-level test

Every ignored flaky test teaches the team that red builds are negotiable.

Verification strategy document

For a major feature, write a short verification strategy: highest-risk journeys, unit/component/integration/E2E coverage choices, what is intentionally not tested and why, accessibility checks, performance budget checks, security and permission checks, production signals after release, and rollback trigger. This makes testing an engineering decision, not a scramble at the end.

Exercises

Exercise 1 - Risk Matrix

Pick one feature and map each risk to a test layer.

Exercise 2 - Rewrite A Flaky Test

Replace CSS selectors and waits with locators and web-first assertions.

Exercise 3 - Critical Flow Verification

For one critical flow, define unit, integration, e2e, accessibility, and performance checks.

Further Reading