Ryz Labs/Interview questions/QA automation engineer
Interview questions

QA automation interview questions for senior engineers (2026)

QA automation questions on Playwright, flaky tests, API and contract testing and CI pipelines, with guidance on what a senior answer looks like.

These 28 QA automation interview questions are for engineers who build and own automated test suites: Playwright end-to-end tests, API and contract tests, CI integration and, above all, keeping a suite fast and trustworthy as the product grows. The examples use Playwright with TypeScript, which most new web projects choose today, but the reasoning applies to any framework. Ryz vets QA automation engineers along the same lines: recruiters source people with real suite ownership, structured NTRVSTA AI interviews test how they reason about scenarios like these, and recruiters review each candidate. The AI scores are advisory and people decide.

How to use these questions

Match the questions to the job. A QA automation engineer joining a team with no tests needs strategy and framework design; one joining a mature suite needs flakiness and CI skills. Mid-level candidates should handle the fundamentals and intermediate sections; senior candidates should own the strategy questions and explain what they would not automate.

Fundamentals

How do you decide what to test at the unit, integration, API and end-to-end levels?

Push each check to the lowest level that can catch the bug. Business rules belong in fast unit tests, service boundaries and database behavior in integration and API tests, and only critical user journeys (sign-up, checkout, permissions) in end-to-end tests. Whether you draw it as a pyramid or a trophy, the point is the same: end-to-end tests are expensive, slow and the most likely to flake.

What a strong answer shows: they ask what has broken in production before, and design coverage around real risk.

Why does Playwright recommend role-based locators and web-first assertions?

Role and label locators match what users and assistive technology see, so they survive markup changes and double as a light accessibility check. Locators auto-wait for elements to be actionable, and assertions like toHaveText retry until they pass or time out, which removes most manual waits.

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

test("applying a discount updates the total", async ({ page }) => {
await page.goto("/cart");
await page.getByLabel("Discount code").fill("FALL25");
await page.getByRole("button", { name: "Apply" }).click();
await expect(page.getByRole("status")).toHaveText("Discount applied");
await expect(page.getByTestId("order-total")).toHaveText("$75.00");
});

What a strong answer shows: they know expect(await locator.textContent()) doesn't retry, and avoid it.

What makes an automated test good?

It is deterministic, independent of other tests and their order, fast enough to run on every change, and it fails with a message that points at the cause. It checks one behavior, sets up its own data and cleans up or isolates it.

What a strong answer shows: they value a clear failure message as much as coverage, because someone else will debug it.

Page objects or fixtures: how do you organize a Playwright suite?

Page objects or component helpers hold locators and multi-step actions for one area of the UI. Playwright fixtures inject those helpers, authenticated pages and test data into tests with setup and teardown handled for you. Keep assertions in tests, not page objects, and avoid deep inheritance.

What a strong answer shows: they keep abstractions thin so a failing test is still readable without opening five files.

How should end-to-end tests get their data?

Each test creates what it needs through the API or a seeding helper, with unique identifiers, rather than relying on shared records that other tests mutate. Reference data can be seeded once per environment. UI steps are reserved for the behavior under test.

What a strong answer shows: they recognize shared mutable test data as a top source of order-dependent failures.

What should you not automate?

One-off checks, rapidly changing prototypes, exploratory testing, subjective visual judgment and flows that are cheaper to cover lower in the stack. Automating everything through the UI produces a slow suite nobody trusts.

What a strong answer shows: they weigh the maintenance cost of a test against the risk it covers.

When do you use soft assertions?

expect.soft records a failure and continues, which helps when checking several independent fields on one page so a single run reports all mismatches. Use hard assertions when later steps depend on the earlier state, otherwise failures cascade into noise.

What a strong answer shows: they use soft assertions deliberately, not to hide unstable checks.

Intermediate

Every test logs in through the UI, which makes the suite slow. How do you fix it?

Authenticate once in a setup project, save the browser storage state, and have test projects depend on it. Use separate state files per role, and log in through an API when one exists.

// playwright.config.ts
import { defineConfig } from "@playwright/test";

export default defineConfig({
projects: [
{ name: "setup", testMatch: /auth\.setup\.ts/ },
{
name: "chromium",
use: { storageState: "playwright/.auth/user.json" },
dependencies: ["setup"],
},
],
});

What a strong answer shows: they keep the auth files out of version control and still keep one real login test.

How do you write API tests, and when do you prefer them to UI tests?

Prefer API tests for validation rules, permissions, error codes and edge cases, since they are faster and more precise. Playwright's request fixture shares config and auth with the UI suite; schema validation catches unexpected fields.

test("creating an order returns the new order", async ({ request }) => {
const res = await request.post("/api/orders", {
data: { sku: "SKU-123", quantity: 2 },
});
expect(res.status()).toBe(201);
expect(await res.json()).toMatchObject({ sku: "SKU-123", status: "pending" });
});

What a strong answer shows: they test negative paths (403, 409, 422) as carefully as the happy path.

When do you mock network calls in UI tests?

Mock third-party services and hard-to-reproduce states such as outages, slow responses and empty lists. Keep a smaller set of tests against the real backend so mocks don't drift from reality.

await page.route("**/api/recommendations", (route) =>
route.fulfill({ status: 503, json: { error: "unavailable" } })
);
await page.goto("/home");
await expect(page.getByText("Recommendations are unavailable")).toBeVisible();

What a strong answer shows: they pair mocks with contract tests so the faked responses stay accurate.

What is consumer-driven contract testing and when is it worth it?

With a tool like Pact, the consumer's tests record the requests it makes and the responses it relies on as a contract. The provider's pipeline verifies it can satisfy every published contract, and a broker answers whether a version can be deployed safely. It pays off when many services and teams release independently.

What a strong answer shows: they explain how contracts replace many slow cross-service end-to-end tests.

How do you run a large Playwright suite in CI?

Shard across parallel jobs, emit blob reports, and merge them into one HTML report. Capture traces, screenshots and video only on failure or first retry to keep artifacts small.

strategy:
matrix:
shard: [1, 2, 3, 4]
steps:
- run: npx playwright install --with-deps chromium
- run: npx playwright test --shard=${{ matrix.shard }}/4 --reporter=blob
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: blob-report-${{ matrix.shard }}
path: blob-report
# a later job downloads all blobs and runs:
# npx playwright merge-reports --reporter html ./all-blob-reports

What a strong answer shows: they make failures easy to debug from CI artifacts without rerunning locally.

Is visual regression testing worth it?

For design systems, charts and layout-heavy pages, yes. toHaveScreenshot compares against stored baselines; run it in a pinned container so fonts and rendering match, mask dynamic regions, and keep the number of screenshots small and intentional.

What a strong answer shows: they have a clear process for reviewing and updating baselines.

How do you test a feature that depends on time, like a trial expiring at midnight?

Control the clock instead of waiting. Playwright's clock API installs fake timers and lets you jump forward.

await page.clock.install({ time: new Date("2026-03-31T23:59:00Z") });
await page.goto("/billing");
await page.clock.fastForward("02:00");
await expect(page.getByText("Your trial has ended")).toBeVisible();

What a strong answer shows: they also cover time zones and the server-side clock, which the browser clock doesn't control.

How do you add accessibility checks to an automated suite?

Run axe on key pages and states with @axe-core/playwright and fail on new violations at the agreed WCAG level. Automated scans catch a subset of issues, so keyboard navigation tests and manual review still matter.

import AxeBuilder from "@axe-core/playwright";

const results = await new AxeBuilder({ page })
.withTags(["wcag2a", "wcag2aa"])
.analyze();
expect(results.violations).toEqual([]);

What a strong answer shows: they scan states like open modals and error messages, not only initial page loads.

Flakiness and test reliability

A test fails about once in 20 runs, only in CI. How do you find the cause?

Open the trace from a failing run to see the DOM, network and console at the moment of failure. Reproduce locally with --repeat-each and the same worker count, or CPU throttling. Then classify: timing, data collision with parallel tests, environment dependency or a real race condition in the product.

What a strong answer shows: they treat some flaky tests as real bugs, since races in the app look exactly like test flakiness.

What is your policy on retries and quarantining flaky tests?

Retries in CI are acceptable as a safety net if flaky passes are tracked and reported, not hidden. A test that flakes repeatedly is quarantined with an owner and a deadline, and the team fixes or deletes it. Unlimited retries teach everyone to ignore red builds.

What a strong answer shows: they make flakiness visible with data rather than relying on memory.

What are the most common causes of flaky UI tests?

Fixed sleeps, assertions that don't retry, non-unique test data, tests that depend on order, animations and transitions, uncontrolled third-party scripts, and shared accounts across parallel workers. Each has a specific fix: web-first assertions, unique data, isolation, disabled animations and mocks.

What a strong answer shows: they give a fix for every cause instead of a generic "add waits".

Tests pass one at a time but fail when run in parallel. What do you do?

Find the shared state: the same user, cart or database row used by multiple workers. Give each worker its own account through a worker-scoped fixture, or generate unique data per test using testInfo.workerIndex or random suffixes.

What a strong answer shows: they design for parallelism from the start instead of forcing serial mode.

The shared staging environment breaks tests several times a week. How do you get stable runs?

Run end-to-end tests against ephemeral, per-branch environments with seeded databases where possible. Virtualize unstable third-party dependencies, and separate "the environment is down" from "the test failed" with a health check before the run.

What a strong answer shows: they treat environment reliability as part of test reliability.

The full suite takes 90 minutes. How do you bring it under 15?

Measure the slowest tests and remove duplicated coverage. Move edge cases to API tests, replace UI setup with API calls, shard across machines, and run a smoke subset on every pull request with the full suite on merge or nightly. Delete tests that no longer guard real risk.

What a strong answer shows: they reduce work first and add hardware second.

Senior and architecture

You join a product team with no automated tests. What is your plan for the first 90 days?

Talk to engineers, product and support to list critical journeys and recent escaped bugs. Set up the framework and CI integration early, cover a handful of critical paths end to end, and help developers add unit and API tests to new work. Report progress as risk covered, not test count.

What a strong answer shows: they make developers part of testing from the start rather than becoming a separate gate.

How does the QA automation role work when developers own quality?

The QA engineer builds the tooling, frameworks and test data that make testing cheap, reviews test plans and pull requests for risk, and coaches developers. They still own exploratory testing and cross-cutting suites.

What a strong answer shows: they measure their impact by the team's quality, not by tests they wrote personally.

How would you test a system made of 20 microservices?

Unit and integration tests per service, contract tests at every service boundary, a thin end-to-end layer for critical journeys, and synthetic monitoring in production. Feature flags and canary releases cover what pre-production tests can't.

What a strong answer shows: they refuse to build a giant end-to-end suite that requires all 20 services to be healthy at once.

How would you plan a migration from Selenium or Cypress to Playwright?

Start with a pilot covering one area, write shared fixtures and helpers, and run both suites in parallel during the transition. Migrate by value (most critical and most flaky tests first) and delete old tests as replacements prove stable. Don't port bad tests one for one.

What a strong answer shows: they treat migration as a chance to cut redundant coverage.

Which metrics tell you whether a test suite is healthy?

Time from push to feedback, flaky-test rate, how often failures are real bugs, defects that escape to production by area, and how long red builds stay red. Code coverage helps find gaps but is a poor target.

What a strong answer shows: they connect suite metrics to developer behavior and release confidence.

How do you test a feature that uses an LLM, where output is not deterministic?

Test the deterministic parts normally: prompts assembled correctly, tools called with valid arguments, guardrails applied. For model output, assert properties (valid JSON, required fields, no banned content) and run an evaluation set with scored criteria in CI, tracking results over time rather than expecting exact strings.

What a strong answer shows: they separate functional tests from quality evaluations and mock the model in fast tests.

How do you bring load testing into the delivery pipeline?

Script realistic user flows with a tool like k6, set thresholds that fail the run, and execute a short smoke load test on every release candidate, with longer tests before major launches.

import http from "k6/http";
import { check } from "k6";

export const options = {
vus: 50,
duration: "5m",
thresholds: {
http_req_failed: ["rate<0.01"],
http_req_duration: ["p(95)<400"],
},
};

export default function () {
const res = http.get(`${__ENV.BASE_URL}/api/products`);
check(res, { "status is 200": (r) => r.status === 200 });
}

What a strong answer shows: they base thresholds on SLOs and run load tests against production-like data volumes.

Red flags to watch for

A practical exercise

As a take-home of about three hours, give the candidate a small web app (a to-do or booking app with login and an API) plus a starter Playwright suite of five tests: two flaky, one using fixed sleeps, one with brittle selectors and one that depends on another test's data. Ask them to fix the suite, add three meaningful tests (one API, one end to end, one for an error state with a mocked response), and wire it into a CI workflow. Include a short README explaining their choices.

Hire senior QA automation engineers vetted with these questions

Ryz introduces senior QA automation engineers who build Playwright, API and contract test suites that teams trust. They are the top 1% of the candidates we interview, they join your team and work in your repos and CI, and they keep within ±1h of US time zones. See how our vetting process works, or start from our QA automation engineer job description.

FAQ

Should a QA automation interview include live coding?

Yes, but keep it close to the job: writing or fixing one end-to-end test, or debugging a failing one from a trace, says more than algorithm puzzles. Thirty to forty-five minutes is enough.

Does it matter which framework the candidate used before?

Less than you might think. Engineers who understand isolation, waiting, test data and CI move between Selenium, Cypress and Playwright quickly. Test the concepts and let them use the framework they know in the interview.

How is a senior QA automation engineer different from a mid-level one?

Mid-level engineers write solid tests within an existing framework. Senior engineers decide what to test at which level, design the framework, fix flakiness at its source and change how the whole team approaches quality.

Questions we didn't answer? Email info@ryzlabs.com.

Explore Ryz Labs

Staff augmentationDedicated development teamsAI pod teamsForward deployed engineersNearshore software developmentAI engineering teamsHire engineers by roleRyz Labs vs competitorsAlternatives guidesBuyer guidesCase studiesHow we vet engineers
Ryz Labs

Senior engineers in your time zone. AI pod teams that ship.

Tell us who you need. You'll get a scoped plan, a price and the names of the people who would do the work.

Start a conversation →