Skip to main content
/tayyab/portfolio — zsh
tayyab
TA
// dispatch.read --classified=false --access-level: public

Top 50 QA Automation Interview Questions (Playwright, Selenium, 2026)

March 10, 2026 EST. READ: 22 MIN #Quality Assurance

You're preparing for a QA automation engineer interview.

You've studied the frameworks. You can write Playwright tests. You understand Page Object Model. But then the interviewer asks something unexpected, and you freeze.

I've conducted 20+ QA automation interviews in 2026. I've heard the best answers and the worst. This guide covers the 50 questions we actually ask—and exactly how to answer them.

Section 1: Foundational Concepts (Q1-10)

1. What is test automation and what are its benefits?

Best Answer:

Test automation is the practice of using software tools to execute predefined test cases on an application. Key benefits include:

  • Speed: Run hundreds of tests in minutes vs hours of manual testing
  • Reliability: Same test runs identically every time (no human error)
  • Cost: High upfront investment, but saves money at scale (1000+ tests)
  • Coverage: Test edge cases humans would miss (boundary conditions, load scenarios)
  • CI/CD Integration: Tests run on every commit, catch regressions immediately

Common mistakes: Saying \"automation is faster\" without context. (Slower upfront, faster long-term.)

2. When should you automate tests vs manual testing?

Best Answer:

Automate when:

  • Test will run 10+ times (ROI breakeven)
  • Requirements are stable (automated tests break with requirement changes)
  • Scenarios are repeatable (same inputs → same outputs)
  • High-risk features (payment processing, authentication)

Manual test when:

  • One-time exploratory testing (new feature, edge case hunting)
  • Requirements changing frequently
  • Visual/UX testing (humans detect design issues better)
  • Accessibility testing (screen readers, keyboard navigation)

3. What's the difference between unit tests, integration tests, and end-to-end tests?

Best Answer (with real examples):

  • Unit Tests: Test a single function in isolation
    • Example: Test `calculateDiscount(100, 0.2)` returns 80
    • Speed: Milliseconds
    • Coverage: 60-80%
  • Integration Tests: Test multiple components together
    • Example: Test API endpoint receives request → queries database → returns JSON
    • Speed: Seconds
    • Coverage: 20-30%
  • E2E Tests: Test entire workflow from user perspective
    • Example: Login → Browse products → Add to cart → Checkout (Playwright)
    • Speed: Minutes
    • Coverage: 10-20%

4. What is the test pyramid and why does it matter?

Best Answer:

        E2E Tests
       /        \
      /    UI    \
     /____________\
   /              \
  /  Integration   \
 /________________\
/                  \
   Unit Tests

Why it matters:

  • Unit tests are cheap to write/maintain (write 100s)
  • E2E tests are expensive but catch real bugs (write 10s-20s)
  • Inverted pyramid = broken tests, slow CI/CD, high maintenance
  • Proper pyramid = fast feedback, low cost, high confidence

5. What is a test case and what should it contain?

Best Answer:

A test case is a set of steps to verify a feature works correctly.

Good test case template:

Title: Should reject login with empty email
Preconditions: User is on login page
Steps:
  1. Leave email field empty
  2. Enter valid password
  3. Click login
Expected Result: Error message shows \"Email is required\"
Actual Result: [To be filled]
Status: Pass/Fail

6. What is flaky testing and how do you prevent it?

Best Answer:

Flaky test = test that passes sometimes and fails sometimes (same code, same input).

Common causes:

  • Race conditions: Element loads in 100ms usually, 5s on slow network
  • Timing: `wait 2 seconds then click` fails if app is slow
  • External dependencies: API timeout, database delay
  • Random data: Tests using random numbers without seeding

How to prevent:

  • Use explicit waits (Playwright's auto-wait does this)
  • Wait for specific conditions: `await expect(button).toBeEnabled()`
  • Avoid sleep/hardcoded waits
  • Mock external APIs in tests
  • Use test data that doesn't change between runs

7. What is test maintenance and why is it important?

Best Answer:

Test maintenance = updating tests when application changes.

Reality: Most QA engineers spend 60% of time maintaining tests, 40% writing new ones.

Why it matters:

  • UI changes break selectors (CSS class renamed: `btn-primary` → `btn-submit`)
  • Feature changes require test updates
  • Bad test design = high maintenance cost
  • Good test design (Page Object Model) = low maintenance cost

8. What is the difference between assertions and test steps?

Best Answer:

  • Test Step: Action taken (click, type, navigate)
    • `await page.click('button')`
  • Assertion: Check that something is true
    • `expect(page).toHaveURL('/dashboard')`

Common mistake: Writing tests without assertions. Tests run but don't verify anything.

9. What's the difference between positive and negative test cases?

Best Answer:

  • Positive tests: \"Happy path\" - application works correctly
    • Login with valid credentials → succeeds
  • Negative tests: Error handling - application rejects invalid input
    • Login with invalid credentials → shows error

Ratio: 80% positive tests, 20% negative tests (focus on critical errors)

10. What is code coverage and what's a good coverage percentage?

Best Answer:

Code coverage types:

  • Line coverage: % of lines executed
  • Branch coverage: % of if/else branches tested
  • Function coverage: % of functions called

Good coverage targets:

  • 70-80%: Good (covers most code)
  • 80-90%: Very good (only edge cases untested)
  • 90%+: Overkill (diminishing returns, hard to maintain)

Trap: 100% coverage doesn't mean zero bugs. Coverage = did we test it, not did we test it well.

Section 2: Playwright Specific (Q11-25)

11. What is Playwright and how is it different from Selenium?

Key Differences (2026):

Feature Playwright Selenium
Speed Fast (modern architecture) Slow (WebDriver overhead)
Auto-waiting ✅ Yes (tests wait automatically) ❌ No (need explicit waits)
Browsers Chrome, Firefox, Safari Chrome, Firefox, Safari, Edge
Ecosystem Smaller, newer Massive (20+ years old)
Learning curve Easy (modern syntax) Moderate (verbose)

12. What is auto-waiting in Playwright and why does it matter?

Best Answer:

Auto-waiting = Playwright automatically waits for elements to be ready before interacting.

// Playwright (no wait needed)
await page.click('button');

// Selenium (explicit wait required)
wait.until(EC.element_to_be_clickable((By.TAG_NAME, 'button')))
button.click()

Why it matters: Eliminates 80% of flaky tests caused by timing issues.

13. How do you select elements in Playwright?

Best Answer (in order of preference):

  1. data-testid: Most stable
    • `page.locator('[data-testid=\"submit-btn\"]')`
  2. Role selectors: Accessible
    • `page.locator('button[type=\"submit\"]')`
  3. CSS selectors: Fragile but common
    • `page.locator('.btn-primary')`
  4. XPath: Last resort (slowest, hardest to maintain)
    • `page.locator('//button[@type=\"submit\"]')`

14. What is Page Object Model and why should you use it?

Best Answer:

POM = Pattern that separates UI interactions from test logic.

// Without POM (bad - test depends on selectors)
test('login', async ({ page }) => {
  await page.fill('input[name=\"email\"]', 'user@example.com');
  await page.click('button');
});

// With POM (good - test is clean, selectors in one place)
test('login', async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.login('user@example.com', 'password');
});

Benefits: One selector change updates all 50 tests.

15. How do you handle waits in Playwright?

Best Answer:

  • Auto-wait (default): Playwright waits automatically ✅
    • `await page.click('button')` waits for button to be clickable
  • Explicit wait (when needed):
    • `await expect(page.locator('.success')).toBeVisible()`
  • Navigation wait:
    • `await page.goto('/dashboard')` waits for page load

Never use: `await new Promise(resolve => setTimeout(resolve, 2000))` (hardcoded wait)

16. How do you test API endpoints with Playwright?

Best Answer:

// Playwright can test APIs directly
test('API test', async ({ request }) => {
  const response = await request.post('https://api.example.com/users', {
    data: { name: 'John', email: 'john@example.com' }
  });
  expect(response.status()).toBe(201);
  const user = await response.json();
  expect(user.id).toBeDefined();
});

Advantage: Test API + UI in same framework, same language.

17. How do you mock API responses in Playwright?

Best Answer:

test('handle API error', async ({ page }) => {
  // Mock API to return error
  await page.route('**/api/users/**', route => {
    route.abort('failed');
  });
  
  await page.goto('/users');
  await expect(page.locator('[role=\"alert\"]')).toContainText('Failed to load');
});

18. What is a fixture in Playwright?

Best Answer:

Fixture = reusable setup/teardown for tests.

// Define fixture
const test = base.extend({
  authenticatedPage: async ({ page }, use) => {
    await page.goto('/login');
    await page.fill('input[name=\"email\"]', 'user@test.com');
    await page.fill('input[name=\"password\"]', 'password');
    await page.click('button[type=\"submit\"]');
    await page.waitForURL('/dashboard');
    await use(page);
  },
});

// Use fixture
test('access dashboard', async ({ authenticatedPage }) => {
  // Already logged in
  await expect(authenticatedPage).toHaveURL('/dashboard');
});

19. How do you handle multiple browsers in Playwright?

Best Answer:

// playwright.config.ts
const config = {
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit', use: { ...devices['Desktop Safari'] } },
  ],
};

// Run tests: npx playwright test --project=chromium
// Or run all: npx playwright test

20. What's the difference between page.click() and locator.click()?

Best Answer:

  • page.click(): Click anywhere on page (deprecated in newer versions)
    • `await page.click('button')`
  • locator.click(): Recommended (more reliable)
    • `await page.locator('button').click()`

Trend 2026: Use locator API exclusively.

21. How do you handle dynamic content that loads asynchronously?

Best Answer:

// Wait for element to appear
await expect(page.locator('.loading')).toBeHidden();

// Or wait for specific condition
await page.locator('.item-list').waitFor({ state: 'visible' });

// Or use promise.all for multiple waits
await Promise.all([
  page.waitForURL('/dashboard'),
  page.locator('button').click()
]);

22. How do you take screenshots in Playwright?

Best Answer:

// Full page screenshot
await page.screenshot({ path: 'screenshot.png' });

// Specific element
await page.locator('button').screenshot({ path: 'button.png' });

// For debugging/reports
test.afterEach(async ({ page }, testInfo) => {
  if (testInfo.status !== 'passed') {
    await page.screenshot({ path: `failure-${Date.now()}.png` });
  }
});

23. How do you debug tests in Playwright?

Best Answer:

// Option 1: Playwright Inspector
npx playwright test --debug

// Option 2: Headed mode (see browser)
npx playwright test --headed

// Option 3: Slow motion
npx playwright test --headed --headed-sleep-ms=1000

// Option 4: Trace (record test execution)
test('my test', async ({ page }) => {
  await page.context().tracing.start({ screenshots: true });
  // test steps
  await page.context().tracing.stop({ path: 'trace.zip' });
});

24. How do you run tests in parallel vs serial?

Best Answer:

// playwright.config.ts
const config = {
  fullyParallel: true, // Default: run all tests in parallel
  workers: 4, // Number of workers (default: auto)
};

// Run specific test serial
test.describe.serial('critical path', () => {
  test('step 1', async ({ page }) => { /* ... */ });
  test('step 2', async ({ page }) => { /* ... */ });
  // Step 2 waits for Step 1 to finish
});

25. What's the difference between @playwright/test and playwright library?

Best Answer:

  • @playwright/test: Test runner (what you use for testing)
    • Includes fixtures, reporters, parallel execution
  • playwright: Browser automation library (lower-level)
    • Use when writing scripts, not tests

Section 3: API Testing & CI/CD (Q26-40)

26. How do you test REST APIs?

Best Answer:

test('GET /users/:id', async ({ request }) => {
  const response = await request.get('/api/users/1');
  
  // Check status
  expect(response.status()).toBe(200);
  
  // Check response body
  const user = await response.json();
  expect(user).toHaveProperty('id');
  expect(user.id).toBe(1);
  expect(user.email).toBeDefined();
});

27. How do you handle authentication tokens in API testing?

Best Answer:

test('authenticated API request', async ({ request }) => {
  // Get token
  const loginResponse = await request.post('/api/auth/login', {
    data: { email: 'user@test.com', password: 'password' }
  });
  const { token } = await loginResponse.json();
  
  // Use token in subsequent requests
  const response = await request.get('/api/users/profile', {
    headers: { 'Authorization': `Bearer ${token}` }
  });
  
  expect(response.status()).toBe(200);
});

28. What is CI/CD and why is it important for QA?

Best Answer:

  • CI (Continuous Integration): Code changes tested automatically on every commit
  • CD (Continuous Deployment): Tested code deployed automatically to production

Why it matters for QA:

  • Catch bugs immediately (within minutes of code change)
  • Prevent broken code from reaching production
  • Reduce manual testing work

29. How do you integrate Playwright tests into GitHub Actions?

Best Answer (workflow file):

name: Playwright Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npx playwright test
      - uses: actions/upload-artifact@v3
        if: always()
        with:
          name: playwright-report
          path: playwright-report/

30. How do you handle test failures in CI/CD?

Best Answer:

  • Build fails if any test fails
  • Pull request blocked from merging
  • Developers must fix test before deployment
  • Generate report and upload artifacts for debugging

Section 4: Advanced Scenarios (Q31-40)

31. How do you test a feature that depends on external APIs?

Best Answer:

test('payment processing', async ({ page }) => {
  // Mock payment API
  await page.route('**/api/payment/**', route => {
    route.fulfill({
      status: 200,
      body: JSON.stringify({ transactionId: '12345', status: 'success' })
    });
  });
  
  await page.goto('/checkout');
  await page.locator('button[name=\"pay\"]').click();
  await expect(page).toHaveURL('/success');
});


32. How do you test file uploads?

Best Answer:

test('upload file', async ({ page }) => {
  await page.locator('input[type=\"file\"]').setInputFiles('path/to/test-file.csv');
  await page.locator('button[name=\"upload\"]').click();
  await expect(page.locator('.success-message')).toBeVisible();
});

33. How do you test form validation?

Best Answer:

test('form validation - email required', async ({ page }) => {
  await page.goto('/signup');
  // Leave email empty
  await page.locator('input[name=\"password\"]').fill('password');
  await page.locator('button[type=\"submit\"]').click();
  
  const error = page.locator('[role=\"alert\"]');
  await expect(error).toContainText('Email is required');
});

34. How do you test dropdown menus and select elements?

Best Answer:

test('select dropdown', async ({ page }) => {
  // Option 1: Using selectOption (for