All jobs / Full-stack developer

Testing interview questions

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

  1. You built a feature that touches a React screen and two API endpoints. Which tests do you write, and where?

    The strongest answer: Most of it in fast unit tests on both halves, a smaller layer of integration tests around the API and the database, and one or two end-to-end tests for the journey that must never break

    Why it works: Right — many cheap tests, few slow ones, and the slow ones reserved for the journeys you cannot afford to break.

    • Many fast tests, few slow ones.
    • Unit-test the logic on both halves.
    • Integrate where API meets database.
    • End-to-end only the critical journey.
  2. You are writing your first tests for a POST endpoint. What do you actually assert?

    The strongest answer: The status code, the shape and key fields of the response, that the record really changed in the database, and that bad input comes back as a validation error rather than a 500

    Why it works: Exactly — status, body contract, persisted effect, and the unhappy path. Those four are what a consumer depends on.

    • Assert the contract, not the code path.
    • Status code and body shape.
    • Check the data really changed.
    • Test the invalid input too.
  3. How do you keep the real API out of a component test without the test drifting from the real thing?

    The strongest answer: Intercept at the network boundary — a request mock such as MSW returns realistic responses, the component runs its own fetching code, and the same handlers cover empty and error responses

    Why it works: Right — mocking the network keeps the component’s real data layer under test, and one set of handlers covers success, empty and failure.

    • Mock the network, not your own code.
    • Keep the real fetching path under test.
    • Share handlers across tests.
    • Cover empty and error responses.
  4. Your service runs a query with a join and a couple of filters, and the team is arguing about how to test it.

    Do you test this against a real database or against a mocked repository?

    The strongest answer: Against a real instance of the same engine, started for the test run and thrown away — a mocked repository only proves your own assumptions, never that the query returns the right rows

    Why it works: Right — same engine, disposable instance. Joins, constraints, types and migrations are exactly what this test should exercise.

    • Test queries against the real engine.
    • Start it per run; throw it away.
    • Substitutes hide dialect bugs.
    • Never point tests at shared data.
  5. How do you test the parts that are not a request — an incoming webhook and a nightly job?

    The strongest answer: Call the handler directly with a recorded payload, signature check included, and replay it to prove it is idempotent; run the job’s function against a seeded database and assert the rows it changed

    Why it works: Exactly — the schedule and the delivery are infrastructure; the logic behind them is ordinary code you can call with real payloads.

    • Separate the trigger from the logic.
    • Call handlers with recorded payloads.
    • Replay one to prove idempotency.
    • Assert the rows, not the schedule.
  6. Someone deleted a required field and merged because the unit tests still passed.

    What should CI do?

    The strongest answer: Fail the build on a breaking OpenAPI diff unless the PR labels an intentional version bump — additive changes pass

    Why it works: Exactly. The spec is a contract test. Breaking should be loud and opt-in, not a surprise in the iOS build next week.

    • Breaking OpenAPI = red CI.
    • Additive = green.
    • Intentional breaks bump a version on purpose.
    • Docs generation is not a compatibility check.
  7. The suite is green on one worker and red across three shards; every spec signs in as the same demo user.

    The end-to-end suite passes alone and fails when it runs in parallel. What is wrong with the test data, and how do you fix it?

    The strongest answer: Each test creates the data it needs through the API under unique identifiers, and its own account where it can, so nothing is shared; whatever is left behind is namespaced per run and cleaned up

    Why it works: Exactly — isolated data per test is what makes parallel runs safe, and a unique prefix makes leftovers easy to find and delete.

    • Every test owns its data.
    • Create it through the API, uniquely named.
    • Its own account where possible.
    • Namespace per run; clean up after.
  8. Backend unit tests are green. The SPA is red on the next deploy because a field went optional to required.

    How do you stop the API from breaking the UI in CI?

    The strongest answer: Consumer-driven contract tests (Pact or a generated-client build) so an API PR fails if it would break a real caller — not only if its own unit tests pass

    Why it works: Exactly. The join needs an automated consumer. Pact, OpenAPI-generated clients, or a tiny real request suite — something the API CI runs.

    • A consumer test in the API pipeline.
    • The UI (or mobile) owns the expectations.
    • Breaking the expectation fails the PR.
    • Chat is not CI.
  9. Every pull request wants the browser suite, and staging is also where the product team demos.

    Where should the end-to-end suite run in CI — against shared staging, or against a stack built for the run?

    The strongest answer: An ephemeral stack per pull request — the build under test, its own database, its own seed — and a smaller suite against staging on a schedule to catch environment and data drift

    Why it works: Right — per-run isolation makes results trustworthy and parallel, and the scheduled staging run still catches what an isolated stack cannot.

    • Isolate the stack per run.
    • Build under test, own database.
    • Keep a scheduled staging run.
    • Never run write suites on production.
  10. Every dashboard is green, and a customer emails to say sign-up has been broken since the morning.

    What would you run against production itself, and what must such a check never do?

    The strongest answer: A scripted journey — sign in, load the dashboard, complete the key action — run every few minutes from outside and alerting on failure or latency, on a dedicated test tenant, never real customers or payments

    Why it works: Exactly — dashboards say the parts are alive; a synthetic journey says the product works, and the test tenant is what makes it safe.

    • Watch the journey, not the process.
    • Run it from outside, on a schedule.
    • Alert on failure and on latency.
    • Dedicated tenant; never real money.
  11. A web client and an API, a forty-minute suite that fails often, and a team that re-runs it until it is green.

    You inherit a slow, flaky suite the team has learned to ignore. What is your strategy for the next quarter?

    The strongest answer: Quarantine the flaky tests on a deadline to fix or delete, move coverage down into fast unit and contract tests, and keep a short end-to-end set for the journeys that earn money

    Why it works: Right — a suite people trust is the goal, and speed plus honesty about what each layer buys you is how you get there.

    • Trust first, coverage second.
    • Quarantine flakes with a deadline.
    • Push tests down the pyramid.
    • Keep end-to-end short and meaningful.