All jobs / Frontend / web developer

Testing interview questions

Testing questions a Frontend / web developer can be asked, from first job to senior. Open one to see the strongest answer and why it works.

  1. What is the difference between a unit test, a component test and an end-to-end test on the frontend, and which do you write most of?

    The strongest answer: Unit: one function in isolation. Component: render a piece of UI and use it like a user. End-to-end: the real app in a browser. Many of the first two, a few end-to-end on critical paths

    Why it works: Right — each level trades speed for realism. Fast tests carry most of the load; a thin end-to-end layer proves the pieces work together.

    • Each level buys different confidence.
    • Unit: logic in isolation.
    • Component: UI as the user sees it.
    • End-to-end: few, critical paths.
  2. How do you assert a login button in React Testing Library?

    The strongest answer: Find by role and name — getByRole('button', { name: /log in/i }) — not test-id-first or snapshot-everything

    Why it works: RTL's point is the user tree: roles and names catch a11y holes and survive refactors.

    • Query the way a user finds it.
    • Prefer role + accessible name.
    • test-id only when there is no name.
    • Avoid class-name and snapshot-only tests.
  3. How do you test a search box that debounces input by 300 ms, in Jest or Vitest, without slowing the suite down?

    The strongest answer: Switch on fake timers, type, advance the clock by 300 ms, assert one call with the last term, then restore real timers afterwards so other tests are not affected

    Why it works: Exactly — the test controls time, runs in milliseconds, and can also assert that nothing fired at 299 ms.

    • Control the clock, don’t wait for it.
    • Enable fake timers.
    • Advance time, then assert.
    • Restore real timers after each test.
  4. A test passes when run alone and fails when the whole file runs, and the failing test changes when you reorder them.

    What do you look for?

    The strongest answer: Shared state leaking between tests: a module-level variable, a mock never reset, storage or timers left over. Reset in beforeEach or afterEach and build fresh data per test so order cannot matter

    Why it works: Right — order dependence means tests share something. Isolation is the rule: each test sets up and tears down its own world.

    • Order-dependent means shared state.
    • Hunt for leftovers between tests.
    • Reset mocks, storage and timers.
    • Fresh data for every test.
  5. A Playwright or Cypress suite fails about one run in five on CI, in different places. The tests are full of fixed two-second waits and long CSS selectors.

    How do you make it trustworthy?

    The strongest answer: Remove fixed sleeps in favour of the tool’s auto-waiting assertions, locate by role or test id, give each test its own seeded data, and use traces from failed runs to find the rest

    Why it works: Exactly — flakiness has causes: timing guesses, brittle selectors, shared data. Web-first assertions wait for the condition, not the clock.

    • Wait for conditions, not for time.
    • Replace sleeps with auto-waiting assertions.
    • Stable locators; isolated test data.
    • Read traces; fix root causes.
  6. After a bad release, management asks you to enforce 90% code coverage on the frontend repository as a merge gate.

    How do you respond?

    The strongest answer: Agree on the goal, fewer escaped bugs, then offer better levers: tests for changed behaviour, coverage on new code as a signal, critical flows end to end, escaped defects tracked. A hard global number invites empty tests

    Why it works: Right — coverage shows what is untested, never what is well tested. Tie the practice to the failure that actually happened.

    • Measure outcomes, not just lines.
    • Name the goal behind the request.
    • Coverage as a signal on new code.
    • Track escaped defects.
  7. How do you catch layout breakage before you translate into German and Hebrew?

    The strongest answer: Pseudo-localization plus string-length budgets — no concatenated sentences, every UI string extracted

    Why it works: Pseudo-loc expands, wraps, and injects accents/RTL markers so layout fails in CI instead of in market.

    • Break layout in a fake locale first.
    • Extract every string.
    • Run pseudo-loc in CI.
    • Forbid concatenated sentences.