Back to SDET
Looking for JavaScript fundamentals (variables, promises, classes…)? They live in the JavaScript path.Go to JavaScript →Testing Concepts & Exercises
What are the types of test doubles?
A test double is any stand-in for a real component. Dummy: passed but never used. Stub: returns fixed canned values. Fake: a working but simplified implementation (e.g. an
in-memory DB). Spy: records how it was called without changing behavior. Mock: a stub plus assertions on how it was called (e.g. sendEmail was called once).Why and when do you mock — and when should you not?
Mock to isolate the unit under test from slow or unstable external dependencies (DB, third-party APIs, email), to simulate hard-to-reproduce errors like a
500, and to keep tests fast and deterministic. Don't mock when you specifically want to verify real integration, when a mock would diverge so far from reality it loses value, or when the real dependency is already local and fast.How do you mock network requests in Playwright?
Use
page.route to intercept a URL pattern and fulfill it with a canned response: page.route('**/api/products', r => r.fulfill({ status: 200, body: JSON.stringify(data) })). You can return a 500 to test error UI, or add a delay before route.continue() to test loading states — all without touching the real backend.How do you structure a CRUD integration test for a REST API?
Cover the full lifecycle and the auth/validation edges: create (
POST -> 201), read it back (GET -> 200), update partially (PATCH -> 200, unchanged fields stay), delete (DELETE -> 204), then confirm it's gone (GET -> 404). Add negative cases: no token -> 401, wrong role -> 403, missing required field -> 422, duplicate -> 409. Each test should set up its own data so it stays independent.What is TTL and where does it matter in testing?
TTL (time to live) is how long something stays valid: auth tokens/sessions (JWT expiry), cache entries (Redis, CDN,
HTTP Cache-Control), and rate-limit windows (X-RateLimit-Reset). As an SDET you test that an expired token is rejected, a cache entry is a miss after its TTL, and that requests beyond the limit are throttled and reset correctly.Why avoid fixed sleeps, and what do you use instead?
A fixed sleep (
waitForTimeout(3000)) is either too short (flaky) or too long (slow), because real timing varies. Use condition-based waits instead: waitForSelector for an element, expect(...).toBeVisible(), waitForResponse for an API call, or a generic polling helper that re-checks a condition until a timeout. This makes tests both faster and more reliable.How do retries with exponential backoff work, and when should you not retry?
Retry re-runs a failing operation up to N attempts, waiting longer between each try (
delay * 2^attempt) so a struggling service can recover without being hammered. Only retry transient failures (network blips, 5xx, timeouts). Don't retry deterministic client errors like a 404 or 422 — a shouldRetry predicate lets you skip those, since retrying will never succeed.