SDET interview questions

Question: Can you describe the key components of a well-structured test automation framework?

Answer:

A well-structured test automation framework should be modular, reusable, scalable, maintainable, and easy to integrate with CI/CD tools.

Key Components of a Well-Structured Test Automation Framework:

  • Modularity: The framework should follow a layered architecture such as the Page Object Model (POM) for UI automation. This separates test logic from page locators, making the framework easier to maintain.
  • Reusability: Common functionalities such as login, API requests, database operations, file handling, and utility methods should be implemented as reusable components to minimize code duplication.
  • Scalability: The framework should allow easy addition of new test cases, support multiple browsers, environments, and integrate with third-party tools without significant code changes.
  • Maintainability: Proper project structure, coding standards, logging, reporting (such as Extent Reports or Allure Reports), configuration management, and exception handling should be implemented.
  • CI/CD Integration: The framework should integrate seamlessly with CI/CD tools such as Jenkins, GitHub Actions, Azure DevOps, or GitLab CI for automated execution.

Note: A good automation framework should reduce maintenance effort, improve code reusability, support parallel execution, and generate detailed execution reports.


Question: How do you decide which framework to use for a project? What factors do you consider?

Answer:

The choice of an automation framework depends on the project's technical requirements, team expertise, application architecture, and long-term maintenance goals.

Factors for Selecting a Test Automation Framework:

  • Project Requirements: Determine whether the project requires UI testing, API testing, Mobile testing, or a combination of these.
  • Data Handling: If the application requires testing with multiple datasets, a Data-Driven Framework using Excel, JSON, CSV, or databases is a suitable choice.
  • Maintainability: For applications with frequent UI changes, using the Page Object Model (POM) improves maintainability by separating locators from test logic.
  • Parallel Execution: If execution speed is important, choose frameworks that support parallel execution such as TestNG, Playwright, or WebDriverIO.
  • Technology Stack: The automation framework should align with the application's technology stack and the team's programming expertise. For example :
    • Selenium with Java for Java-based applications.
    • Playwright or WebDriverIO for JavaScript/TypeScript projects.
    • Cypress for modern web applications.
  • CI/CD Integration: The framework should integrate easily with continuous integration tools such as Jenkins, GitHub Actions, Azure DevOps, or GitLab CI.
  • Reporting: It should support reporting tools such as Extent Reports, Allure Reports, or built-in HTML reports for better result analysis.
  • Cross-Browser Support: The framework should support execution across multiple browsers and operating systems based on project requirements.
  • Community & Support: Prefer frameworks that have active community support, regular updates, and comprehensive documentation.

Note: There is no single framework that is ideal for every project. The framework should be selected based on business requirements, application architecture, team expertise, scalability, and long-term maintenance needs.

Question: If an API request is failing with a 500 Internal Server Error, how do you debug the issue?

Answer:

A 500 Internal Server Error indicates that the request reached the server successfully, but the server encountered an unexpected error while processing it. Although the issue is typically on the server side, a tester can perform several checks to help identify the root cause.

1. Validate the API Request

  • Check Request Body: Verify that the JSON or XML payload is correctly formatted and contains all mandatory fields.
  • Check Request Headers: Ensure required headers such as Content-Type, Accept, Authorization, and custom headers are correct.
  • Verify API Endpoint: Confirm that the correct endpoint URL, HTTP method (GET, POST, PUT, DELETE, PATCH), and query/path parameters are being used.

2. Inspect the API Response

  • Check Response Body: Many APIs return detailed error messages or error codes that help identify the failure.
  • Review Server Logs: If log access is available, analyze application logs, server logs, or stack traces for detailed error information.

3. Test with Different Data

  • Execute the request using both valid and invalid payloads.
  • Verify whether the failure occurs only for specific users, roles, environments, or input data.
  • Check boundary values and special characters that might trigger server-side validation failures.

4. Debug Using API Tools

  • Execute the same request using tools like Postman, ReadyAPI, or Swagger to verify whether the issue is reproducible.
  • Compare request headers, payload, and responses with successful requests.
  • Review API monitoring tools such as New Relic, Datadog, Kibana, or Splunk for server-side exceptions.

5. Collaborate with Developers

  • Share the complete request, response, headers, payload, and timestamps with the development team.
  • Verify whether any recent deployments, configuration changes, database updates, or code modifications could have introduced the issue.
  • Provide reproducible test steps and supporting logs to help developers investigate efficiently.

Example : Verify the HTTP status code using Rest Assured.

given()
    .header("Authorization", token)
    .body(requestBody)
.when()
    .post("/users")
.then()
    .statusCode(500);

Note: A 500 Internal Server Error usually indicates a backend issue. However, testers should first verify that the request, headers, endpoint, authentication, and test data are correct before reporting the issue to the development team.

Question: If an API request is failing with a 500 Internal Server Error, how do you debug the issue?

Answer:

A 500 Internal Server Error indicates that the server encountered an unexpected error while processing the request. Although the issue is generally on the server side, a QA engineer should systematically verify the request and collect sufficient evidence before escalating it to the development team.

1. Validate the API Request

  • Verify the Request Body: Ensure the JSON/XML payload is valid and contains all mandatory fields.
  • Check Request Headers: Verify headers such as Content-Type, Accept, Authorization, and any custom headers.
  • Verify the Endpoint: Ensure the correct API endpoint, HTTP method (GET, POST, PUT, DELETE, PATCH), path parameters, and query parameters are being used.
  • Validate Authentication: Confirm that the access token, API key, or other authentication credentials are valid and not expired.

2. Analyze the API Response

  • Review the Response Body: Check whether the API returns an error code, message, or stack trace that helps identify the problem.
  • Review Response Headers: Verify server information, correlation IDs, and other diagnostic headers.
  • Check Server Logs: If log access is available, review application and server logs for detailed exception information.

3. Test with Different Data

  • Execute the request using valid and invalid payloads.
  • Verify whether the issue occurs only for specific users, roles, or environments.
  • Test boundary values and special characters to identify data-related failures.

4. Debug Using API Tools

  • Execute the same request using Postman, ReadyAPI, or Swagger to reproduce the issue.
  • Compare successful and failed requests to identify differences.
  • Review monitoring tools such as New Relic, Datadog, Kibana, or Splunk for backend exceptions.

5. Collaborate with Developers

  • Share the complete request payload, headers, response body, status code, and timestamp.
  • Provide steps to reproduce the issue consistently.
  • Check whether any recent deployments, configuration changes, or database updates could have introduced the failure.

Example : Verify the response status code using Rest Assured.

Response response =
given()
    .header("Authorization", token)
    .contentType(ContentType.JSON)
    .body(requestBody)
.when()
    .post("/users");

response.then()
    .statusCode(500);

System.out.println(response.asPrettyString());

Example : Log request and response details for debugging.

given()
    .log().all()
    .body(requestBody)
.when()
    .post("/users")
.then()
    .log().all();

Note: Before reporting a 500 Internal Server Error, always verify the request payload, endpoint, authentication, headers, and test data. Providing complete request and response logs significantly reduces debugging time for the development team.

Question: How would you handle API test automation failures in a CI/CD pipeline? How do you ensure tests are reliable?

Answer:

API test failures in a CI/CD pipeline can occur due to environmental issues, unstable test data, network problems, or application changes. The objective is to identify the root cause quickly while ensuring that the automation suite remains stable, reliable, and maintainable.

Common Causes of API Test Failures:

  • Environment Issues: API server is unavailable, incorrect base URL, or configuration problems.
  • Data Dependencies: Missing or inconsistent test data.
  • Network Issues: Timeouts, intermittent connectivity, or slow response times.
  • Application Changes: API contract changes, schema modifications, or backend defects.
  • Authentication Issues: Expired tokens or invalid credentials.

Best Practices for Handling API Test Failures:

1. Implement Retry Mechanism

  • Retry tests only for temporary failures such as network issues or timeouts.
  • Avoid retrying genuine application defects.

Example : Configure retries in TestNG.

@Test(retryAnalyzer = RetryAnalyzer.class)
public void verifyUsersAPI() {

    given()
        .when()
        .get("/users")
        .then()
        .statusCode(200);
}

Note: CI/CD tools such as Jenkins can also be configured with retry plugins.

2. Use Mock Servers

  • Use WireMock, MockServer, or Postman Mock Server to simulate API responses.
  • This minimizes dependency on unstable external services.

3. Validate the Response Before Assertions

  • Verify the response status code before validating the response body.
  • This prevents misleading assertion failures.

Example :

Response response =
given()
.when()
.get("/users");

response.then()
.statusCode(200);

response.then()
.body("size()", greaterThan(0));

4. Parameterize Environment Configuration

  • Maintain separate configurations for Development, QA, UAT, and Production.
  • Avoid hardcoding URLs and credentials.

Example :

String baseUrl =
System.getProperty(
"env",
"https://dev.api.com"
);

5. Logging and Reporting

  • Capture request payloads, response bodies, headers, execution time, and stack traces.
  • Generate detailed reports using Allure or Extent Reports.

6. Test Data Management

  • Create independent test data for every execution.
  • Clean up data after test execution whenever possible.

Note: Reliable API automation depends on stable environments, proper logging, test isolation, and minimizing external dependencies.


Question: If a test case is failing intermittently (Flaky Test), how would you debug and fix it?

Answer:

A flaky test is a test that produces inconsistent results without any application changes. It may pass in one execution and fail in another.

1. Verify the Failure Manually

  • Execute the test manually.
  • Determine whether it is an actual application defect or an automation issue.

2. Identify the Root Cause

  • Dynamic element locators.
  • Synchronization issues.
  • Slow API responses.
  • Animations or page transitions.
  • Incorrect or shared test data.
  • Parallel execution conflicts.

3. Stabilize the Test

  • Use stable CSS selectors or Relative XPath.
  • Avoid absolute XPath.
  • Replace Thread.sleep() with Explicit Waits.
  • Use retry only for transient failures.
  • Generate unique test data.
  • Reset application state after execution.

Example : Explicit Wait.

WebDriverWait wait =
new WebDriverWait(driver,
Duration.ofSeconds(10));

wait.until(
ExpectedConditions
.elementToBeClickable(
By.id("login")
));

Note: Fix the root cause instead of relying on retries, as excessive retries can hide genuine defects.


Question: If a parallel test fails intermittently, how would you debug and fix it?

Answer:

Parallel execution failures are usually caused by shared resources, synchronization problems, or improper browser session management.

1. Ensure Test Independence

  • Each test should execute independently.
  • Avoid shared users and shared test data.
  • Generate unique data for every execution.

Example : Generate unique test data.

String username =
"user_"
+ UUID.randomUUID();

2. Isolate Browser Sessions

  • Create a separate browser instance for each thread.
  • Use ThreadLocal WebDriver when executing Selenium tests in parallel.

Example :

private static ThreadLocal
<WebDriver> driver =
new ThreadLocal<>();

3. Replace Fixed Waits

  • Use Explicit Waits instead of Thread.sleep().
  • Wait only for the required condition.

4. Enable Logging and Screenshots

  • Capture screenshots on failures.
  • Store browser logs.
  • Capture API logs.
  • Record execution timestamps.

5. Maintain a Clean Test Environment

  • Reset database changes after execution.
  • Clear cookies, cache, and local storage.
  • Clean up created test data.

Example : Clear browser cookies.

driver.manage()
.deleteAllCookies();

Final Thoughts

  • Ensure tests are completely independent.
  • Use isolated browser sessions.
  • Avoid shared test data.
  • Replace fixed waits with synchronization techniques.
  • Implement proper logging and reporting.
  • Use retries only for temporary failures.
  • Clean up test data after execution.

Note: Stable automation frameworks are built on reliable synchronization, independent test execution, proper environment management, and detailed diagnostics rather than excessive retry mechanisms.



Question: Your UI automation suite has 3,000 tests. It takes 4 hours in CI, while developers expect feedback within 15 minutes. What would you do?
Answer: Scenario
Your team has 3,000 UI regression tests. The application is growing rapidly.

Current situation:
  • Local execution: ~3 hours
  • CI execution: ~4 hours
  • 20% of tests are occasionally flaky
  • Developers wait for the complete suite before merging
  • Management asks you to bring feedback below 15 minutes
How would you approach the problem?

I would not immediately add more CI machines or simply increase parallelism.

First, I would understand where the four hours are being spent.

Step 1 — Measure the suite

I would collect:
  • Test execution time
  • Setup/teardown time
  • Browser startup time
  • Authentication time
  • API/database setup time
  • Slowest tests
  • Slowest test suites
  • Retry frequency
  • Failure rate
  • Flake rate
  • Resource contention

For example :
 Test execution 150 min 
Environment setup 20 min 
Browser startup 15 min 
Authentication 25 min 
Retries 30 min 
Database/data setup 20 min 
Infrastructure wait 20 min 
Without this measurement, parallelization could simply move the bottleneck somewhere else.

Step 2 — Revisit the test pyramid

I would identify tests that are unnecessarily implemented through the UI.

For example :
 UI:
"Create customer"


API:
Create customer
Update customer
Delete customer


Database/service:
Validation/business-rule tests

If 100 tests verify the same business rule through the UI, many of them should probably move to API/component/integration levels.

The UI suite should concentrate on critical user journeys and cross-system behavior rather than testing every business rule through a browser.

Step 3 — Introduce test layers

For example :
 Small number
                UI/E2E

                  ▲

             API/Contract

                  ▲

         Integration tests

                  ▲

             Unit tests

             Large number

Step 4 — Parallelize safely

After removing unnecessary UI coverage, I would parallelize the remaining tests.

But parallel execution requires:
  • Independent test data
  • Independent users/accounts where necessary
  • No shared mutable state
  • Unique resource names/IDs
  • Isolated browser contexts
  • Environment capacity planning
Otherwise:
 Test A ---> modifies customer 123 
Test B ---> expects customer 123 unchanged 
can create race conditions.

Step 5 — Create CI test tiers

I would split execution into stages.

PR:
 Unit 
API/contract 
Critical UI smoke ~10-15 min 
Post-merge:
 Broader regression 
Nightly:
 Full regression 
Cross-browser 
Extended integration 
This gives developers fast feedback without abandoning comprehensive regression coverage.

Step 6 — Optimize the test framework

For UI automation I would investigate:
  • Reusing authenticated state where safe
  • Avoiding unnecessary login flows
  • API-based test-data setup
  • Better fixtures
  • Parallel workers
  • Eliminating hard waits
  • Reducing unnecessary browser navigation
  • Using efficient locators
  • Avoiding unnecessary UI setup
Playwright, for example, recommends isolated tests and user-facing/explicit locators, and its locators provide auto-waiting and retryability.

Senior-level point

The answer is not “increase parallel threads from 10 to 50.”

A senior SDET should first ask:

"Why are we using the browser to verify things that don't require a browser?"

The goal is to reduce feedback time, not simply increase infrastructure.
Question: A test passes 100% locally but fails randomly in CI. How would you investigate it?
Answer: Scenario

A checkout test:
 Local: 100/100 passed 
CI: 92/100 passed 
The failure occurs randomly.

The developer says:

"It's just a flaky test. Add a retry."

What do you do?

I would reject the assumption that it is automatically a flaky test.

A failure that appears nondeterministically may be caused by:
  • Timing
  • Race conditions
  • Shared data
  • Environment differences
  • Network instability
  • Resource exhaustion
  • Browser differences
  • Dependency failures
  • Test-order dependency
  • Application defects
First, I would classify the failure.

Step 1 — Capture evidence

I would collect:
  • CI logs
  • Screenshot
  • Video/trace
  • Browser console
  • Network logs
  • Application logs
  • API responses
  • Database state
  • Test data
  • Environment information
  • Commit/build information
  • Failure timestamp
Step 2 — Re-run repeatedly

I might execute:
 test x 100 
locally and in CI.

If:
 Local: 100/100 
CI: 94/100 
then I investigate environmental differences.

If:
 Local: 96/100 
CI: 93/100 
then the test itself is probably nondeterministic.

Step 3 — Check timing assumptions

Bad:
 await page.click("#submit");

await sleep(3000);

expect(message).toBeVisible();
The problem isn't solved by choosing 5 seconds instead of 3 seconds.

I would wait for a specific condition.

For Playwright, web-first assertions automatically wait and retry until the expected condition is satisfied or the timeout is reached.

Step 4 — Check test-data collision

Suppose parallel workers use:
 customer@test.com 
Every test may update the same customer.

Instead:
 customer-worker1-<unique-id> 
customer-worker2-<unique-id> 
or generate isolated data through APIs.

Step 5 — Check external dependencies

For example :
 
UI 
↓ 
Order Service 
↓ 
Payment Service 
↓ 
External Payment Gateway 
If the external gateway is unstable, the UI test should not necessarily be blamed.

I would determine whether the test is supposed to verify:
  • Our checkout UI
  • Our payment integration
  • The external provider
These may require different test layers.

Step 6 — Only then consider retry

Retry is useful for transient infrastructure failures, but it should not hide genuine product defects.

A retry policy should therefore be observable:
 
Original failure 
↓ 
Retry 
↓ 
Pass 
↓ 
Classify as possible transient failure 
↓ 
Track it 
I would not allow:
 Failure → Retry → Pass → Ignore forever 
Senior-level point

A senior SDET doesn't treat retry as a fix.

The objective is:

Identify why the same test produces different results under apparently identical conditions.

Research on flaky tests also identifies timing/concurrency, infrastructure, environment, and external factors among the important sources of nondeterminism.
Question: Your company has 25 microservices. There are almost no automated tests. You are asked to build the automation strategy from scratch. What is your first 30-day plan?
Answer: I would not start by creating a Selenium/Playwright framework.

The first step is understanding the system.

Week 1 — System discovery

I would identify:
 
Service 
├── API 
├── Database 
├── Events 
├── Dependencies 
├── External systems 
└── Critical business flows 
I would map critical workflows such as:
 
User 
↓ 
Authentication 
↓ 
Order 
↓ 
Inventory 
↓ 
Payment 
↓ 
Notification 
Then classify risk.

Week 2 — Define test layers

For each service:
 
Unit 
Integration 
Contract API Event/message 
End-to-end 
I would avoid making everything an end-to-end test.

For example :
  • Business rule → unit
  • Service API → API/integration
  • Service-to-service compatibility → contract
  • Critical customer journey → E2E

Week 3 — Build the foundation

I would establish:
  • Framework conventions
  • Test-data strategy
  • Environment strategy
  • Authentication strategy
  • Logging
  • Reporting
  • CI integration
  • Parallel execution
  • Failure artifacts
  • Test tagging
  • Ownership
Example :
 @smoke 
@critical 
@api 
@contract 
@e2e 
@nightly 
Week 4 — Automate highest-risk flows

I would select perhaps:
  • Top 10 critical business flows
  • Top 20 high-risk APIs
  • Top service contracts
  • Top production failure scenarios
Then measure:
 Before:

Manual regression = 2 days

After:

Critical automated regression = 20 minutes
Senior-level point

A senior SDET should create a quality strategy, not merely create a test framework.

The framework is an implementation detail of the broader quality architecture.
Question: Two tests pass individually but fail when executed in parallel. How do you diagnose it?
Answer: Scenario

Test A → PASS
Test B → PASS

A + B in parallel → intermittent failures

My first suspicion would be shared mutable state.

I would investigate:

1. Shared database records

 Test A updates user 100 
Test B deletes user 100 
2. Shared accounts

 user@test.com 
being logged in simultaneously by multiple tests.

3. Shared files

 /download/report.csv 
Both tests read/write the same file.

4. Shared environment configuration

For example :
 Test A changes feature flag = ON 
Test B expects feature flag = OFF 
5. Static/global variables

Example :
 static String customerId; 
Parallel tests can overwrite the value.

6. Shared browser context/session

Tests should not unintentionally share:
  • Cookies
  • Local storage
  • Session storage
  • Authentication state

Solution :

I would introduce isolation.

For example :
 Worker 1

customer-101

Worker 2

customer-102

Worker 3

customer-103
Test data should preferably be created specifically for the test and cleaned up safely afterward.

Playwright's current best-practice guidance explicitly emphasizes test isolation, including independent storage/session state, because isolation improves reproducibility and prevents cascading failures.

Senior-level point

Parallelization is not simply:
 workers = 20 
It is:
 Parallelism

Data isolation

State isolation

Resource capacity

Deterministic cleanup

Question: A developer changes the DOM and 200 UI tests fail because of locator changes. How would you design the automation to prevent this?
Answer: Scenario
A frontend team replaces:
<button class="btn btn-primary xyz123">
with:
<button class="primary-action">
Hundreds of tests fail.

Detailed Answer
I would first challenge the locator strategy.

A locator should represent a stable testing contract, not implementation details.

Prefer:
page.getByRole('button', { name: 'Submit' })
or an explicit test identifier:
page.getByTestId('submit-order')
rather than deeply coupled selectors such as:
div:nth-child(2) > div > button.xyz123
Playwright's documentation recommends user-facing attributes and explicit contracts over brittle CSS/XPath chains.

I would establish a locator hierarchy:
  1. Accessible role/name
  2. Label
  3. Explicit test ID
  4. Stable business-facing attribute
  5. CSS
  6. XPath — only when genuinely necessary
I would also establish a frontend/testing agreement:
data-testid="checkout-submit"
should only be changed intentionally.

Important architectural point
I would not create a giant abstraction such as:
findButton("submit")
for everything.

Abstraction should improve maintainability without hiding important test behavior.

Senior-level point
The objective isn't:
"Make locators never fail."

The objective is:
Make locator failures correspond to meaningful changes in user-visible behavior or an intentionally changed test contract.
Question: Your API returns HTTP 200, but customers report that orders are sometimes incorrect. How would you test it?
Answer: I would not treat HTTP 200 as evidence that the API is correct.

I would validate the complete business response.

For an order API:
POST /orders
I would validate:

Transport-level behavior
  • Status code
  • Headers
  • Content type
  • Response time
  • Authentication
  • Correlation ID
  • Schema
{
  "orderId": "...",
  "status": "...",
  "total": 100
}
Validate:
  • Required fields
  • Types
  • Allowed values
  • Nested structures
  • Nullability

Business rules
For example :
quantity = 2
price = $50
discount = $10
expected total = $90
Not merely:
status == 200
Database verification
If appropriate, verify:
API request
   ↓
Order created
   ↓
Database record
   ↓
Inventory reservation
   ↓
Event published
Eventual consistency
If the architecture is asynchronous:
POST /order
    ↓
202 Accepted
    ↓
message queue
    ↓
Order service
    ↓
database
I would not immediately query the database and fail because the record isn't there yet.

Instead I would use a bounded polling strategy based on a meaningful condition.

Idempotency
I would test:
Same request
+
Same idempotency key
=
One logical order
This is particularly important for payment/order systems.

Senior-level point
A senior SDET validates business correctness, not merely HTTP correctness.
Question: Your checkout system uses a third-party payment provider. How would you decide between mocking it and testing against the real provider?
Answer: I would use both approaches at different test levels.

Suppose:
Checkout
   ↓
Payment Service
   ↓
External Payment Provider
Mock/stub tests
Use mocks for deterministic scenarios:
  • Payment success
  • Payment declined
  • Timeout
  • 500 response
  • Invalid response
  • Duplicate callback
These tests are fast and repeatable.

Contract/integration tests
Verify that our integration conforms to the provider's expected API contract.

Real-provider tests
Use a sandbox/test environment for a smaller number of tests.

For example :
PR:
    Mocked payment tests

Post-merge:
    Contract/integration tests

Nightly:
    Sandbox payment flows
Why not always use the real provider?
Because external dependencies introduce:
  • Network instability
  • Rate limits
  • Cost
  • Slow execution
  • Data cleanup problems
  • Availability issues

Why not always mock?
Because mocks can become unrealistic.

For example :
Our mock says response = X
Real provider actually returns Y
The test passes while production integration fails.

Senior-level point
The question isn't:
"Mock or real?"

It is:
Which behavior am I trying to prove, and which test layer is best suited to prove it?
Question: A test fails because the UI hasn't updated after an API call. A junior engineer proposes adding sleep(10). What would you recommend?
Answer: I would avoid fixed sleeps unless there is a very specific reason for one.

Bad:
await page.click('#save');

await page.waitForTimeout(10000);

expect(...);
The test either:
  • Waits too long when the system is fast, or
  • Fails when 10 seconds isn't enough.
Instead, wait for the condition that represents completion.

For example :
await page.getByRole('button', { name: 'Save' }).click();

await expect(
  page.getByText('Saved successfully')
).toBeVisible();
Or wait for a meaningful network/application condition where appropriate.

Playwright's auto-waiting performs actionability checks before actions, while web-first assertions wait for expected conditions rather than immediately evaluating them.

Senior-level point
The principle is:
Wait for state
NOT
Wait for time
Question: Your automation suite reports 95% pass rate, but developers don't trust it. How would you improve confidence?
Answer: A high pass percentage doesn't automatically mean a high-quality test suite.

I would measure:

Reliability
  • Pass rate
  • Failure rate
  • Flake rate
  • Retry rate
Detection effectiveness
  • Production defects detected
  • Escaped defects
  • Defect severity
  • Defect detection layer
Test quality
  • Assertions per test
  • Meaningful business coverage
  • Duplicate coverage
  • Dead tests
  • Obsolete tests
CI health
  • Average runtime
  • P95 runtime
  • Queue time
  • Failure investigation time
Flaky test management
For every test:
test_id
pass_count
fail_count
retry_count
flake_rate
last_failure
root_cause
owner
If a test fails intermittently, I would classify the cause:
  • Timing
  • Data
  • Concurrency
  • Environment
  • Infrastructure
  • Application defect
  • External dependency
I would quarantine genuinely unstable tests where appropriate, but quarantine must not become permanent storage for broken tests.

Senior-level point
The metric shouldn't be:
"We have 10,000 automated tests."

It should be:
"Our automated tests provide trustworthy, fast, actionable feedback."
Question: Your API test passes, but the corresponding UI test fails. How do you determine whether the UI or backend is broken?
Answer: Scenario
API:
POST /customer → 201
UI:
Customer not visible

Detailed Answer
I would build a failure chain rather than immediately blaming either layer.

UI action
   ↓
Browser network request
   ↓
API response
   ↓
Frontend state handling
   ↓
UI rendering
I would inspect the browser network request.

Case 1
UI → API → 500
Likely backend/integration issue.

Case 2
UI → API → 200
    response contains customer
    UI doesn't display it
Likely frontend issue.

Case 3
API → 201
Database record eventually appears
UI immediately checks
Could be eventual consistency.

Case 4
API test uses admin token
UI uses normal-user token
Could be authorization behavior.

Case 5
API creates customer
UI reads from cache/search index
Could be asynchronous propagation.

Senior-level point
I would use:
  • API logs
  • Browser network logs
  • Correlation IDs
  • Service logs
  • Database state
  • Event/message logs
to trace the transaction across layers.

A senior SDET should be able to debug across the system, not only inside the browser.
Question: Your tests create thousands of records and eventually the environment becomes unusable. What would you change?
Answer: Detailed Answer
I would investigate the test-data lifecycle.

Typical problems include:
Create
Create
Create
Create
...
Never cleanup
I would design a test-data strategy.

Option 1 — API-based setup
Instead of:
UI → create customer
for every test:
API → create customer
UI → verify customer behavior
This is faster and reduces UI dependency.

Option 2 — Namespaced data
For example :
test-run-8472-customer-001
Option 3 — Cleanup
Use deterministic cleanup where safe:
Create
Test
Cleanup
Option 4 — Disposable environments
For CI:
Build
  ↓
Create environment
  ↓
Run tests
  ↓
Destroy environment
Option 5 — Database reset/seeding
For controlled environments, use:
Known seed
+
Test-specific data
rather than relying on whatever happens to exist.

Senior-level point
Test data should be treated as an engineering resource, not an afterthought.
Question: A production defect escaped even though you had 500 automated tests. What do you investigate?
Answer: I would perform a failure analysis rather than saying:
"We need more automation."

I would ask:

1. Was the scenario covered?
If not:
Coverage gap

2. Was it covered but incorrectly implemented?
Test exists
Expected result is wrong

3. Did the test execute in CI?
Test exists
But excluded from pipeline

4. Did the test fail but get ignored?
Test failed
Retry passed
Pipeline continued

5. Was test data unrealistic?
Production:
10 million records

Test:
10 records

6. Was the environment different?
Production → distributed architecture
Test → single-node environment

7. Was the scenario fundamentally difficult to reproduce?
For example :
  • Race condition
  • Concurrency
  • Large data volume
  • Network partition
  • Time-zone issue
  • Cache inconsistency
8. Was the requirement itself misunderstood?
Sometimes the failure is not an automation problem.

Senior-level conclusion
The corrective action could be:
  • New test
  • Existing test correction
  • Better test data
  • Better environment
  • Monitoring
  • Observability
  • Architecture improvement
  • Requirement clarification
Not every production defect requires another UI test.
Question: Your team wants 100% automation coverage. How would you respond?
Answer: I would clarify what "100%" means.

If it means:
100% of business requirements have automated verification at an appropriate level,
that can be a useful goal.

If it means:
Every possible scenario must be automated through UI,
I would challenge it.

Some tests are better suited to:
  • Unit
  • API
  • Integration
  • Contract
  • Security
  • Performance
  • Manual exploratory testing
  • Production monitoring
For example, testing 100 invalid combinations through the UI may be inefficient.

Instead:
Business validation
→ API/unit level

5-10 representative workflows
→ UI

Critical production behavior
→ monitoring
Senior-level point
Automation is not the objective.

Risk reduction and fast feedback are the objectives.
Question: Your application uses asynchronous events. The test sends an order and expects a notification. How would you test it reliably?
Answer: Scenario
POST /order
   ↓
Order Service
   ↓
Kafka/message broker
   ↓
Notification Service
   ↓
Email
The test currently does:
Create order
sleep(5)
check email
It fails intermittently.

Detailed Answer
I would first identify the actual synchronization point.

The architecture is asynchronous, so a fixed delay is inherently fragile.

I would use a bounded condition-based wait.

For example :
Create order
    ↓
Obtain correlation/order ID
    ↓
Poll/query notification state
    ↓
Expected event/message appears
    ↓
Validate notification
If the system provides an observable status:
order.status = NOTIFICATION_SENT
that may be preferable to polling an external mailbox.

If event infrastructure is test-accessible, I might consume the relevant event using the order ID/correlation ID.

Important considerations
I would test:
  • Duplicate events
  • Missing events
  • Delayed events
  • Out-of-order events
  • Retry behavior
  • Consumer failure
  • Idempotency
  • Dead-letter behavior
Senior-level point
For asynchronous systems, test synchronization should be based on observable state or events, not arbitrary time.
Question: Your Playwright/Selenium framework has become a 20,000-line "utility framework" that nobody understands. How would you refactor it?
Answer: I would first identify the actual responsibilities.

A healthy framework might separate:
Tests
  ↓
Business/workflow layer
  ↓
Page/API clients
  ↓
Framework utilities
  ↓
Browser/HTTP infrastructure
For example :
test:

    checkout(order)

workflow:

    addProduct()

    applyDiscount()

    completePayment()

page:

    clickCheckout()

    verifyOrder()

api:

    createOrder()

    deleteOrder()

infrastructure:

    browser

    authentication

    logging
I would remove unnecessary abstraction.

Bad abstraction:
clickElement("button", "submit", 10, true, false, ...)
Good abstraction:
checkoutPage.submitOrder()
when that operation has genuine domain meaning.

I would also eliminate:
  • Duplicate wait utilities
  • Duplicate locator wrappers
  • Global mutable state
  • Generic methods with dozens of parameters
  • Unused helpers
  • Hidden retries
  • Framework methods that silently swallow exceptions
Senior-level point
A framework should make correct tests easier to write, not hide the application behind layers of abstraction.
Question: A test fails with a timeout. The screenshot looks correct. What would you investigate next?
Answer: A screenshot is only one piece of evidence.

I would investigate:
Screenshot
+
DOM/state
+
Network
+
Console
+
Application logs
+
Trace
+
Test data
+
Timing
Possible cases:

Case 1 — Element visible but not actionable
It may be:
  • Covered by another element
  • Disabled
  • Animating
  • Moving
  • Not receiving pointer events
Playwright's actionability checks vary by action and can include conditions such as visibility, stability, whether the element can receive events, and whether it is enabled.

Case 2 — Wrong page state
The screenshot may look similar but the application could still be loading.

Case 3 — Network request failed
The UI shell loads but required data never arrives.

Case 4 — Locator matched multiple elements
A locator may not uniquely identify the target.

Case 5 — Test data problem
The expected record doesn't exist.

Case 6 — Application defect
The UI is genuinely stuck.

Senior-level point
I would avoid changing the timeout until I understand which condition was not satisfied and why.
Question: You have 1,000 API tests. They are fast individually but the suite becomes slow when executed in parallel. What could be happening?
Answer: I would investigate resource contention.

Parallelism can expose bottlenecks such as:
  • Database connection pool
  • CPU
  • Memory
  • API rate limits
  • Thread pools
  • Message queues
  • File handles
  • Network
  • Service locks
  • Test-data collisions
For example :
100 workers
   ↓
100 API requests
   ↓
Database pool = 20
The additional 80 workers may simply wait.

More parallelism can therefore make the system slower.

I would measure:
Workers

vs

Throughput

vs

Failure rate

vs

Resource utilization
Example :
10 workers → 100 tests/min

20 workers → 180 tests/min

40 workers → 190 tests/min

80 workers → 170 tests/min
The optimal setting is not necessarily the highest worker count.

Senior-level point
Parallelism should be optimized based on system throughput and reliability, not CPU count alone.
Question: An API occasionally returns duplicate orders when the client retries. How would you test and diagnose this?
Answer: I would suspect an idempotency problem.

Consider:
Client
  ↓
POST /order
  ↓
Server creates order
  ↓
Response lost
  ↓
Client retries POST
  ↓
Second order created
From the client's perspective:
First request = timeout
But the server may already have processed it.

Tests I would create

Same idempotency key
Request 1:
Idempotency-Key = ABC123
Request 2:
Idempotency-Key = ABC123
Expected:
One logical order

Different keys
ABC123
XYZ456
Expected:
Two independent orders

Concurrent duplicate requests
Send the same request simultaneously.

Expected behavior should be defined explicitly.

Timeout/retry scenario
Simulate:
Server processes request
Response delayed/lost
Client retries
Then verify database/business state.

Senior-level point
I would validate business idempotency, not just API response codes.
Question: Your organization has UI, API, mobile, and backend teams. Everyone creates duplicate automation. How would you establish ownership?
Answer: I would create a quality ownership model.

Layer Primary ownership Purpose
Unit Developers Logic
Component Developers/SDET Component behavior
API Service team/SDET Service behavior
Contract Producer + consumer Compatibility
UI E2E SDET + product teams Critical user journeys
Mobile E2E Mobile team/SDET Mobile workflows
Performance Performance/SDET Capacity
Exploratory QA/Product Unknown risks
Then define:
  • Who creates?
  • Who maintains?
  • Who reviews?
  • Who owns failures?
  • Who decides when a test is obsolete?
I would also create a test catalog.

Example :
Requirement
   ↓
Test
   ↓
Layer
   ↓
Owner
   ↓
CI pipeline
Senior-level point
Without ownership, automation eventually becomes:
Everyone's responsibility
=
Nobody's responsibility
Question: You join a company where automation is failing badly. What would you do in your first 90 days?
Answer: Scenario
You inherit:
  • 5,000 UI tests
  • 35% flaky failures
  • 2-hour CI runtime
  • No test ownership
  • Poor reporting
  • Frequent production defects
  • No API automation strategy
  • No test-data strategy
Leadership says:
"Fix automation."

What is your 90-day plan?
I would divide the work into three phases.

Days 1–30: Understand and stabilize
I would not immediately rewrite the framework.

Measure
Collect:
  • Test count
  • Runtime
  • Flake rate
  • Failure rate
  • Retry rate
  • Production escapes
  • Top failing tests
  • Top slow tests
  • Infrastructure failures
Categorize failures
  • Application defect
  • Test defect
  • Data issue
  • Environment issue
  • Infrastructure issue
  • Timing/concurrency
  • External dependency
Establish ownership
Every important test should have an owner.

Stabilize critical tests
Fix the highest-value flaky tests first.

I would avoid mass retries because retries can hide real problems.

Days 31–60: Restructure
I would introduce a layered strategy.
Unit
  ↓
Component
  ↓
API
  ↓
Contract/Integration
  ↓
Small E2E suite
Then move unnecessary UI tests down to lower layers.

Introduce data strategy
Seed
+
API setup
+
Unique test data
+
Controlled cleanup
Improve CI
For example :
PR:
    Unit
    API
    Contract
    Critical smoke

Post-merge:
    Regression

Nightly:
    Full E2E
    Cross-browser
Days 61–90: Scale and measure
I would introduce:
  • Quality dashboard
  • Automation reliability
  • Test duration
  • Flake rate
  • Failure causes
  • Production escapes
  • Coverage by risk
  • Test ownership
  • CI quality gates
For example :
  • Critical smoke failure → block deployment
  • Known flaky test → quarantine + ticket
  • Infrastructure failure → distinguish from product failure
Architecture improvements
I would gradually replace:
UI-only verification
with:
API + contract + integration + targeted E2E
Final outcome
The goal after 90 days should not simply be:
5,000 tests → 5,500 tests
It should be something like:
Before:

5,000 UI tests
2 hours
35% flaky

After:

2,000 meaningful UI/API/integration tests
20-minute PR feedback
<2-3% unexplained flakiness
Clear ownership
Actionable reporting
Better production defect detection
The exact numbers would depend on the product; the important point is the engineering approach and measurable improvement.
Question: What are common follow-up questions interviewers may ask about senior SDET scenarios?
Answer: Follow-up 1
"Why shouldn't we simply add retries to every failing test?"

Expected direction:
Because retries can hide deterministic defects and reduce trust in CI. Retries should be controlled, observable, and used only where transient failure is plausible.

Follow-up 2
"Why not run every test in parallel?"

Expected direction:
Because shared resources, databases, rate limits, test-data collisions, locks, and infrastructure capacity can make excessive parallelism slower or less reliable.

Follow-up 3
"Why not test everything through the UI?"

Expected direction:
UI tests are usually slower and more expensive to maintain. Business logic should generally be verified at lower layers, with UI tests focused on important user-visible workflows.

Follow-up 4
"Why not mock everything?"

Expected direction:
Mocks provide speed and determinism but can diverge from real dependencies. Critical integrations still require contract/integration or controlled real-environment testing.

Follow-up 5
"How do you prove that your automation strategy is successful?"

Expected direction:
Measure feedback time, reliability, flake rate, defect detection, escaped defects, maintenance cost, and coverage of important risks—not merely the number of automated tests.
Question: What separates a Senior SDET answer from a Mid-Level answer?
Answer: A mid-level answer often sounds like:
"I will add explicit waits, Page Object Model, retries, and parallel execution."

A senior answer sounds more like:
"First I will determine whether the failure is caused by the product, test, data, environment, or infrastructure. Then I'll identify the appropriate testing layer, isolate the state, instrument the test for evidence, and choose the least expensive reliable solution. If the same problem affects many tests, I'll fix the underlying framework or architecture rather than patching individual tests."

That distinction is important.

Core topics you should be ready to defend as Senior SDET 
  • Test automation architecture
  • UI automation architecture
  • API automation
  • Contract testing
  • Microservices testing
  • Test pyramid
  • Test-data management
  • Database validation
  • Parallel execution
  • Flaky-test investigation
  • CI/CD strategy
  • Docker/containerized test execution
  • Cloud test execution
  • Authentication and authorization testing
  • Asynchronous/event-driven testing
  • Mocking and service virtualization
  • Performance-testing strategy
  • Observability and debugging
  • Production defect analysis
  • Automation ROI and quality metrics
  • Framework design
  • Code quality and maintainability
  • Risk-based testing
  • Release-quality strategy
  • Technical leadership and mentoring
Question: Production is returning intermittent 503 errors, but all automated tests are green. How would you investigate?
Answer: Scenario
Your production dashboard reports:
POST /checkout

Success: 99.2%
503:     0.8%
But:
  • API automation is green
  • UI automation is green
  • Unit tests are green
  • The problem cannot be reproduced consistently in QA
The engineering manager asks:
"Why didn't our automation catch this?"

Detailed Answer
I would first determine whether the problem is a functional defect, capacity problem, dependency problem, or infrastructure problem.

I would trace the complete request:
Client
  ↓
CDN / Load Balancer
  ↓
API Gateway
  ↓
Checkout Service
  ↓
Payment Service
  ↓
Database
I would correlate failures using:
  • Request/correlation ID
  • Timestamp
  • Host/container/pod
  • Region
  • API version
  • User segment
  • Dependency response
  • CPU/memory
  • Connection pool usage
Then I would look for patterns
For example, 503 occurs only:
  • During peak traffic
  • In one region
  • After 30 minutes
  • With large carts
  • When payment latency increases
That immediately changes the investigation.

Testing gap
The existing automation may only prove:
1 user
+
normal traffic
+
healthy dependencies
Production may experience:
10,000 concurrent users
+
slow dependency
+
connection pool exhaustion
+
autoscaling delay
I would therefore consider:
  • Load testing
  • Stress testing
  • Soak testing
  • Dependency-failure testing
  • Capacity testing
  • Production observability
Senior-level answer
I would not simply add:
"Test that expects 503."

I would ask:
What system condition produces the 503, and do we have a test that deliberately exercises that condition?
Question: A service changes an API response field from customerName to name. Hundreds of tests fail. How would you prevent this kind of problem?
Answer: This is a classic consumer/provider compatibility problem.

I would introduce contract testing.

Suppose:
Customer Service
       ↓
Order Service
       ↓
customerName
The producer should know what consumers depend upon.

A consumer contract could establish:
{
  "id": "123",
  "customerName": "John"
}
If the provider removes customerName, the contract should fail before deployment.

I would also establish API versioning.

For a breaking change:
/v1/customers

/v2/customers
or an equivalent compatibility strategy.

Important point
I would not necessarily say:
"Never change APIs."

Instead:
  • Non-breaking change → backward compatible
  • Breaking change → version/migration/deprecation strategy
Senior-level answer
The goal is to move the failure from:
Production
  ↓
Integration failure
to:
Pull request
  ↓
Contract failure
That is a major quality improvement.
Question: Your team has 100 microservices. End-to-end tests are extremely slow and unreliable. Would you reduce E2E testing?
Answer: I would not make a blanket decision.

I would determine what risks the E2E tests are actually covering.

For example :
Service A
  ↓
Service B
  ↓
Service C
  ↓
Service D
  ↓
Service E
A single E2E test may fail because any of five services or dependencies is unhealthy.

I would shift much of the verification to:
  • Unit
  • Component
  • API
  • Contract
  • Integration
  • Targeted E2E
E2E should focus on business journeys
For example :
  • Customer registration
  • Login
  • Place order
  • Payment
  • Refund
rather than testing every permutation.

Contract testing
Each consumer verifies the provider behavior it actually depends on.

This reduces the need to discover every compatibility problem through giant E2E tests. Contract testing is particularly useful at service boundaries.

Senior-level answer
I would not ask:
"How many E2E tests should we have?"

I would ask:
Which risks can only be proven by E2E testing?

Everything else should be tested at the cheapest reliable layer.
Question: Your company wants to deploy multiple times per day. What should the SDET strategy look like?
Answer: I would design quality around fast feedback and progressive confidence.

A possible pipeline:
Developer PR
   ↓
Unit
   ↓
Static analysis
   ↓
API/component
   ↓
Contract
   ↓
Critical E2E
   ↓
Deploy
   ↓
Smoke
   ↓
Canary
   ↓
Production monitoring
PR tests
Should be:
  • Fast
  • Deterministic
  • Highly relevant
Post-merge
Run broader integration tests.

Deployment
Run smoke tests.

Production
Use:
  • Monitoring
  • Error rates
  • Latency
  • Business metrics
  • Canary analysis
A canary progressively exposes a new version to a subset of servers/users before wider rollout, providing an opportunity to detect unexpected behavior and revert.

Senior-level answer
Quality cannot be entirely delegated to pre-production automation.

For modern continuous delivery:
Testing
+
Observability
+
Progressive delivery
+
Fast rollback
work together.
Question: An authorization bug allows User A to access User B's order by changing /orders/123 to /orders/124. How would you test this systematically?
Answer: Detailed Answer
This is an authorization problem, specifically a classic object-level authorization risk.

I would create at least:
User A → Order A → allowed

User A → Order B → denied

User B → Order B → allowed

Admin → Order A/B → according to policy
Test matrix
User Object Expected
A A Allow
A B Deny
B A Deny
B B Allow
Admin A Allow
Admin B Allow
I would test through:
  • API
  • UI
  • Direct URL
  • Query parameters
  • Request payload
  • Different HTTP methods
Important
I would verify both:
HTTP behavior
+
Data leakage
A response of:
403
is good.

But:
200
{
  "error": "not authorized",
  "otherUserEmail": "..."
}
is still a security defect.

Senior-level answer
Authorization testing must be identity × resource × action, not simply "login works."
Question: Your UI tests are stable on Chrome but fail frequently on Firefox and WebKit. How would you investigate?
Answer: I would not immediately add browser-specific waits.

First I would classify the failure.

Step 1 — Compare behavior
Chrome → PASS
Firefox → FAIL
WebKit → PASS
Is the problem:
  • Locator?
  • Rendering?
  • Timing?
  • JavaScript behavior?
  • CSS?
  • Browser API?
  • Network?
  • Application defect?
Step 2 — Compare artifacts
I would collect:
  • Trace
  • Screenshot
  • Console
  • Network
  • DOM
  • Browser/version
  • OS
Step 3 — Check browser assumptions
Examples:
  • Date parsing
  • Timezone
  • Clipboard
  • File upload/download
  • Permissions
  • Storage
  • Web APIs
  • CSS behavior
Step 4 — Determine responsibility
If the application genuinely behaves differently in Firefox, the test may be exposing a product defect.

If only the locator is browser-sensitive, the automation may be defective.

Senior-level answer
Cross-browser testing should expose real compatibility risk, not become a collection of browser-specific hacks.
Question: Your automation framework uses retries, and the dashboard reports 99.9% pass rate. Management says quality is excellent. Do you agree?
Answer: Not necessarily.

Consider:
1,000 tests

100 failures

100 retries

100 retry passes
The dashboard might report:
1000/1000 PASS
But the system actually experienced:
100 initial failures
That is important.

I would report:
  • Initial pass rate
  • Retry pass rate
  • Final pass rate
  • Flake rate
  • Failure categories
For example :
Initial pass: 90%

Retry pass:   99%

Flake rate:   9%
Why?
Retries can improve resilience against transient infrastructure problems, but they can also hide test instability.

Senior-level answer
I want to know:
"How many tests passed on the first attempt?"

not only:
"How many eventually passed?"
Question: Your database contains 500 million records. A QA environment has only 50,000. Production reports a performance problem. How would you reproduce it?
Answer: Detailed Answer
I would recognize that this is a data-volume problem, not simply a functional testing problem.

I would identify:
Production:
500M records

QA:
50K records
Then determine which properties matter:
  • Row count
  • Data distribution
  • Index cardinality
  • Hot partitions
  • Large values
  • Historical records
  • Query selectivity
  • Concurrent users
I would create production-like data characteristics.

Not necessarily copy production data.

Instead generate synthetic data preserving statistical characteristics.

For example :
Customer:
10M

Orders:
500M

Active orders:
5%

Large customers:
1%

Historical:
70%
Then measure:
  • P50 latency
  • P95 latency
  • P99 latency
  • Throughput
  • CPU
  • Memory
  • DB connections
  • Query execution time
Senior-level answer
"Production-like data" means more than:
"Lots of rows."

It means reproducing the characteristics that influence system behavior.
Question: Your team uses a shared QA environment, but tests constantly interfere with each other. Would you create more environments?
Answer: Maybe—but I would first understand the source of interference.

Problems may be caused by:
  • Shared database
  • Shared users
  • Shared feature flags
  • Shared queues
  • Shared files
  • Shared external accounts
Adding environments may reduce some collisions but can dramatically increase:
  • Infrastructure cost
  • Deployment complexity
  • Data management
  • Maintenance
Alternatives
Test namespaces
run-101
run-102
run-103
Isolated databases
Where practical.

Disposable environments
PR
  ↓
Environment
  ↓
Tests
  ↓
Destroy
Service virtualization
Mock dependencies that don't need to be real.

Senior-level answer
I would ask:
What state must be isolated, and what state can safely be shared?

Isolation should be based on risk, not simply cloning the entire environment.
Question: A production bug occurs only when two requests arrive within milliseconds of each other. How would you automate it?
Answer: Detailed Answer
This is likely a concurrency/race-condition scenario.

A sequential test:
Request A

wait

Request B
may never reproduce it.

I would deliberately synchronize requests.

Conceptually:
          ┌── Request A
Barrier ──┤
          └── Request B
Both are released as close together as possible.

Then repeat:
100

1,000

10,000
depending on risk and environment capacity.

I would also inspect:
  • Database locks
  • Transaction isolation
  • Shared memory
  • Distributed locks
  • Idempotency
  • Queue ordering
  • Cache updates
Important
Concurrency bugs are often probabilistic.

Therefore:
Pass once
doesn't prove correctness.

I would measure:
failure frequency
+
conditions
+
system state
Senior-level answer
The test must reproduce the timing relationship, not merely execute the same two requests.
Question: Your organization wants to introduce AI-generated test cases. How would you use AI without degrading test quality?
Answer: Detailed Answer
I would use AI as an accelerator, not as the authority.

AI can help generate:
  • Boundary scenarios
  • Negative cases
  • Data combinations
  • API test skeletons
  • Test-code refactoring
  • Failure summaries
  • Duplicate-test detection
But every generated test still needs engineering review.

Example
Requirement:
Discount cannot exceed 50%.

AI may generate:
49%
50%
51%
I would additionally consider:
  • -1%
  • 0%
  • null
  • decimal
  • very large number
  • multiple discounts
  • currency conversion
  • expired coupon
  • concurrent application
Main risk
AI can generate large quantities of low-value tests.

For example :
1 requirement
→ 500 tests
→ 450 duplicates
Governance
I would establish:
  • Review standards
  • Security/privacy restrictions
  • No production secrets
  • No sensitive data in prompts
  • Test ownership
  • Quality metrics
  • Duplicate detection
Senior-level answer
The metric should not be:
"AI generated 10,000 tests."

It should be:
"AI helped us discover meaningful risks faster while maintaining test quality and review standards."
Question: A third-party API suddenly starts returning unexpected JSON fields. Your application doesn't fail, but downstream processing becomes incorrect. How would you test this?
Answer: Detailed Answer
I would treat external API responses as untrusted input.

I would test:
  • Expected response
  • Additional fields
  • Missing fields
  • Null fields
  • Wrong types
  • Unexpected enum
  • Malformed data
  • Huge payload
  • Unexpected redirect
  • Slow response
  • 5xx
Example :
Expected:

{
  "status": "PAID"
}
Unexpected:
{
  "status": "UNKNOWN"
}
The application should have defined behavior for that case.

Contract validation
I would validate the external provider's expected contract where feasible.

Resilience
I would also test:
  • Timeout
  • Retry
  • Circuit breaker
  • Fallback
Senior-level answer
Third-party systems should not be treated as inherently trustworthy simply because they are external or reputable.
Question: Your team says code coverage is 90%, but production defects remain high. What would you investigate?
Answer: I would explain that code coverage is not the same as risk coverage.

For example :
Line executed = yes

Correct behavior verified = no
A test could execute:
calculateDiscount();
without asserting the correct business outcome.

I would inspect:
  • Branch coverage
  • Condition coverage
  • Mutation testing where valuable
  • Requirement coverage
  • Risk coverage
  • Negative scenarios
  • Boundary cases
  • Integration behavior
  • Production-like data
  • Failure modes
Example :
if customer.isPremium:
    discount = 20
else:
    discount = 5
90% line coverage doesn't necessarily prove:
  • Premium + expired coupon
  • Premium + invalid currency
  • Non-premium + coupon
  • Concurrent update
Senior-level answer
I would move the conversation from:
"How much code executed?"

to:
"How much important behavior and risk was actually verified?"
Question: Your test suite takes 30 minutes even after parallelization. Management demands 5 minutes. What would you optimize first?
Answer: Detailed Answer
I would establish the actual critical path.

I would measure:
  • Test execution
  • Queue time
  • Environment provisioning
  • Data setup
  • Browser startup
  • Authentication
  • Network latency
  • Cleanup
  • Reporting
Then determine whether the 30 minutes is:
  • CPU-bound
  • I/O-bound
  • Environment-bound
  • Dependency-bound
  • Serialization-bound
I would investigate test distribution.

Suppose:
Worker 1 → 2 minutes

Worker 2 → 3 minutes

Worker 3 → 28 minutes
The total runtime may be determined by one poorly distributed shard.

I would rebalance tests.

But I would also challenge the requirement.

If the 30-minute suite contains:
500 UI tests
I may move tests to lower layers rather than forcing five-minute UI execution.

Senior-level answer
The fastest test is often the test that doesn't need to run at that layer.
Question: Your company has a critical payment system. Product wants to release despite several automation failures. How do you decide whether to block release?
Answer: Detailed Answer
I would not make the decision based only on:
"10 tests failed."

I would classify the failures.

For example :
8 failures → environment issue

1 failure → known flaky test

1 failure → payment authorization failure
The final one may be release-blocking.

I would assess:
  • Business impact
  • Customer impact
  • Security risk
  • Financial risk
  • Probability
  • Severity
  • Known workaround
  • Test confidence
  • Production monitoring
  • Rollback capability
Example risk matrix
Payment authorization failure

+

No workaround

+

Production path affected

=

Block
Whereas:
Visual regression on internal admin page

+

Low business impact

+

Known issue

=

Possibly release
Senior-level answer
A senior SDET should be able to say:
"I recommend blocking because of this specific risk."

or:
"I recommend proceeding because these failures do not affect the release risk, and here is the mitigation."

Not simply:
"Tests are red, therefore stop."
Question: A service works correctly in isolation but fails when deployed with the latest versions of four other services. How would you identify the breaking change?
Answer: Detailed Answer
I would model the dependency graph.
A
├── B
├── C
└── D
    └── E
Then identify version combinations.

For example :
A v5

B v8

C v12

D v4

E v9
Then perform controlled comparison.

Techniques
  • Contract tests: Verify each service boundary.
  • Binary/version matrix: Test combinations such as A-old + B-new and A-new + B-old where practical.
  • Git bisect/change correlation: Identify which deployment introduced the incompatibility.
  • Distributed tracing: Follow the failing transaction.
Senior-level answer
Microservice testing needs compatibility testing, not merely isolated service testing.
Question: Your UI test passes, but users complain that the page feels slow. What is wrong with your automation strategy?
Answer: Detailed Answer
A functional UI test might only verify:
Element visible = PASS
But users care about:
  • Time to usable page
  • Interaction latency
  • API latency
  • Rendering
  • Core user journey performance
I would introduce performance measurements.

For critical flows:
  • Login
  • Search
  • Checkout
  • Payment
  • Dashboard
I would measure:
  • Response latency
  • P95/P99
  • Page load characteristics
  • API latency
  • Resource size
  • Error rate
  • Concurrent-user behavior
Important
I would avoid turning every functional test into a performance test.

Instead:
Functional tests
→ correctness

Performance tests
→ latency/capacity

Real-user monitoring
→ production experience
Senior-level answer
Functional correctness and performance are different dimensions of quality.
Question: Your test occasionally passes after a retry, but the second execution modifies production-like data differently from the first. Is retry still safe?
Answer: Not automatically.

This is a test side-effect/idempotency problem.

Suppose:
Test:

Create payment

First attempt:

Payment created
Response lost

Retry:

Second payment created
The test may eventually report:
PASS
while leaving incorrect state.

Before enabling retries I would ask:
  • Is the operation idempotent?
  • Does retry mutate data?
  • Does retry send notifications?
  • Does retry charge money?
  • Does retry create orders?
  • Does retry publish events?
For destructive or state-changing workflows, retry needs special handling.

Solutions
  • Unique test data
  • Idempotency keys
  • Cleanup
  • State verification
  • Retry only safe portions
  • Isolated environment
Senior-level answer
A retry mechanism must be designed with side effects in mind.

"Retry everything" is dangerous in stateful systems.
Question: Your team has no reliable way to determine whether a failed automation test is caused by the application or infrastructure. What would you redesign?
Answer: Detailed Answer
I would improve observability of the test system.

Every test execution should ideally have:
  • Test ID
  • Build ID
  • Commit
  • Environment
  • Browser
  • Worker
  • Test data ID
  • Correlation ID
  • Timestamp
And artifacts such as:
  • Application logs
  • Network logs
  • Browser console
  • Trace
  • Screenshot
  • Video where useful
  • API request/response
  • Infrastructure metrics
Failure classification
I would build categories such as:
PRODUCT_DEFECT
TEST_DEFECT
TEST_DATA
ENVIRONMENT
INFRASTRUCTURE
EXTERNAL_DEPENDENCY
TIMEOUT
UNKNOWN
Then measure them.

Senior-level answer
A test framework should be observable enough to debug itself.
Question: You are appointed SDET Architect. Engineering asks you to define the organization's automation strategy for the next two years. What would you propose?
Answer: Detailed Answer
I would start with a quality architecture rather than choosing a tool.

1. Define quality principles
For example :
  • Fast feedback
  • Risk-based testing
  • Test isolation
  • Production-like validation
  • Automation at the right layer
  • Observable tests
  • Security by design
  • Continuous improvement
2. Define the testing architecture
                Production
                    ▲
             Monitoring/RUM
                    ▲
             Canary/Smoke
                    ▲
                E2E tests
                    ▲
             Integration tests
                    ▲
              Contract/API tests
                    ▲
            Component/unit tests
3. Standardize frameworks carefully
For example :
  • UI → Playwright
  • API → organization-approved API framework
  • Performance → organization-approved load-testing tool
  • Security → SAST/DAST/API security tooling
The tool is secondary to the architecture.

4. Define CI strategy
PR
├── Unit
├── Component
├── Contract
├── API
└── Critical E2E

Post-merge
└── Regression

Nightly
├── Full E2E
├── Cross-browser
├── Performance subsets
└── Extended integration

Production
├── Smoke
├── Canary
└── Monitoring
5. Define test-data architecture
Synthetic data
+
API setup
+
Isolation
+
Cleanup
+
Disposable environments
6. Define reliability standards
For example :
  • Flake rate target
  • Maximum retry policy
  • Maximum PR runtime
  • Failure triage SLA
  • Test ownership
  • Quarantine policy
7. Define security testing
API security should include areas such as:
  • Authentication
  • Object-level authorization
  • Function-level authorization
  • Resource consumption
  • SSRF
  • Security misconfiguration
  • API inventory
  • Unsafe third-party API consumption
8. Define quality metrics
I would avoid vanity metrics such as:
Number of automated tests
Instead:
  • Escaped defects
  • Critical-risk coverage
  • Initial pass rate
  • Flake rate
  • PR feedback time
  • Regression duration
  • Failure diagnosis time
  • Automation maintenance cost
  • Production incident correlation
9. Define engineering ownership
Quality should be shared:
Developer
    ↓
Unit/component quality

Service team
    ↓
API/contract quality

SDET
    ↓
Automation architecture/system-level quality

DevOps/SRE
    ↓
Environment/reliability/observability

Security
    ↓
Security assurance
10. Define the two-year roadmap
Phase 1
  • Stabilize
  • Measure
  • Remove flaky tests
  • Establish ownership
Phase 2
  • Move testing down the pyramid
  • Introduce contracts
  • Improve CI
  • Improve test data
Phase 3
  • Scale parallel execution
  • Disposable environments
  • Production validation
  • Advanced observability
Phase 4
  • Continuous quality engineering
  • Risk-based release decisions
  • Automated quality intelligence
  • Performance/security integrated into delivery
Senior-level answer
The strongest answer is not:
"I will build a better Selenium framework."

It is:
"I will build an engineering quality system where defects are prevented, detected at the cheapest appropriate layer, diagnosed quickly, and monitored after deployment."
Question: What should a 10+ year SDET demonstrate in an interview?
Answer: For this experience level, the candidate should demonstrate more than framework knowledge.

Strong candidate
A strong candidate naturally talks about:
  • Architecture
  • Risk
  • Distributed systems
  • Failure modes
  • Observability
  • Data isolation
  • Contract testing
  • Security
  • Performance
  • CI/CD
  • Production behavior
  • Reliability
  • Metrics
  • Cost
  • Maintainability
  • Engineering trade-offs
Warning signs
Be cautious if the candidate's answer to every scenario is:
  • "Use Page Object Model."
  • "Add explicit wait."
  • "Increase timeout."
  • "Add retry."
  • "Run it in parallel."
Those are implementation techniques, not senior-level problem-solving strategies.

Excellent 10+ year answer pattern
A very strong candidate usually follows something like:
1. Clarify the business risk
        ↓
2. Understand architecture
        ↓
3. Reproduce the problem
        ↓
4. Collect evidence
        ↓
5. Identify root cause
        ↓
6. Select the correct testing layer
        ↓
7. Design deterministic automation
        ↓
8. Integrate into CI/CD
        ↓
9. Add observability/metrics
        ↓
10. Prevent recurrence
Question: Your automation framework has grown from 500 to 8,000 tests. Every team is adding its own utilities, and now the framework has multiple implementations of login, API clients, waits, database utilities, and reporting. How would you redesign it?
Answer: What the interviewer is testing
  • Framework architecture
  • Technical-debt management
  • Reusability
  • Governance
  • Scalability
  • Ability to distinguish abstraction from unnecessary complexity
Strong answer
I would not immediately rewrite the framework.

First, I would perform an architecture assessment.

I would identify:
Test Layer
   ↓
Business/Domain Layer
   ↓
UI/API Abstraction
   ↓
Infrastructure Utilities
   ↓
Configuration
   ↓
Reporting/Observability
Then I would identify duplicated responsibilities.

For example :
Team A → LoginUtility

Team B → LoginHelper

Team C → AuthenticationService

Team D → LoginPage.login()
I would establish a single responsibility for authentication while keeping the domain-specific behavior at the appropriate layer.

I would also define framework standards:
  • Naming conventions
  • Package structure
  • Dependency rules
  • Logging standards
  • Error handling
  • Configuration
  • Test-data strategy
  • Reporting
  • Ownership
  • Versioning
I would avoid creating a giant CommonUtils class containing everything.

Architecture I would aim for
                    Test Cases
                        |
                Business/Domain APIs
                        |
        +---------------+---------------+
        |               |               |
       UI              API             DB
        |               |               |
   UI Adapter       API Client       DB Client
        |               |               |
        +---------------+---------------+
                        |
               Common Infrastructure
                        |
        Config | Logging | Reporting
                        |
                  CI / Execution
The key principle is:
Centralize common infrastructure, but don't centralize unrelated business behavior.
Question: Your organization has 30 SDETs and five product teams. Everyone uses the same automation framework, but one team's change frequently breaks another team's tests. How would you architect ownership?
Answer: Strong answer
I would move toward a shared platform + team-owned tests model.

          Automation Platform
                    |
        +-----------+-----------+
        |           |           |
      Team A      Team B      Team C
       Tests       Tests       Tests
The platform team owns:
  • Core framework
  • Execution engine
  • Reporting
  • Common fixtures
  • Authentication infrastructure
  • CI integration
  • Versioning
  • Observability
  • Common libraries
Product teams own:
  • Their test scenarios
  • Domain-specific fixtures
  • Test data
  • Business assertions
  • Test maintenance
I would introduce:
Pull Request
    ↓
Contract/API validation
    ↓
Framework compatibility tests
    ↓
Consumer test validation
I would also version shared framework components instead of allowing uncontrolled changes.

Important
A shared framework should behave like an internal product.

It needs:
  • Documentation
  • Release notes
  • Versioning
  • Backward compatibility
  • Deprecation policy
  • Ownership
  • Support model
Question: Your framework takes 45 minutes to execute 6,000 tests. Management asks you to reduce it to 10 minutes. What would you change?
Answer: Strong answer
I would not immediately increase the number of parallel workers.

First I would profile the execution pipeline.
45 minutes

   |
   +-- Queue time
   +-- Environment setup
   +-- Browser startup
   +-- Authentication
   +-- Test execution
   +-- Database setup
   +-- Cleanup
   +-- Reporting
Suppose I discover:
Test execution       25 min

Environment setup    8 min

Data creation        6 min

Browser startup      3 min

Reporting            3 min
Increasing workers may only improve the 25-minute component.

I would optimize at multiple levels.

1. Move tests down the pyramid
If 2,000 UI tests are actually API validations, move them to API/component tests.

2. Parallelize safely
Use multiple workers/shards.

3. Improve test-data creation
Avoid repeatedly creating expensive data through the UI.

4. Remove unnecessary setup
Use API/database setup where appropriate.

5. Optimize infrastructure
6,000 tests
      ↓
20 shards
      ↓
multiple workers
But I would validate that the environment and database can actually support that concurrency.

Senior-level point
The goal is not:
"Run more tests simultaneously."

The goal is:
"Reduce the critical path without introducing test interference or hiding defects."
Question: Your team wants every test to use Page Object Model. After three years, the framework contains 400-page classes with hundreds of methods. What would you do?
Answer: Strong answer
I would challenge the assumption that Page Object = automation architecture.

A page object should represent meaningful interaction with a UI, not become a dumping ground.

Bad:
CheckoutPage

├── clickButton()
├── clickButton2()
├── clickButton3()
├── getText1()
├── getText2()
├── helper1()
├── helper2()
├── API call
├── database call
└── test assertion
I would separate responsibilities.
Test
  ↓
Business/Domain Flow
  ↓
Page Components
  ↓
Locators / UI interaction
For example :
Checkout
├── AddressComponent
├── PaymentComponent
├── OrderSummaryComponent
└── ConfirmationComponent
This is particularly useful for modern applications where the same UI component appears on many pages.

Key principle
Use abstractions to reduce change impact, not simply because a design pattern exists.
Question: Your automation framework has 200 helper methods such as clickElement(), waitForElement(), enterText(), and isElementDisplayed(). Would you keep this abstraction layer?
Answer: Strong answer
Not automatically.

I would determine whether these helpers provide meaningful value.

For example :
clickElement(button);
may simply wrap:
button.click();
If the wrapper adds no:
  • Logging
  • Error context
  • Domain behavior
  • Diagnostics
  • Consistency
  • Cross-tool abstraction
then it may just increase indirection.

With modern Playwright, locators already provide auto-waiting and retryability for many interactions.

Therefore, blindly creating:
waitForElement()
waitForElementVisible()
waitForElementClickable()
waitUntilDisplayed()
can actually make the framework worse.

I would keep an abstraction only when it provides real value.

For example :
authenticateAsAdmin()
createCustomer()
createOrder()
approveRefund()
These are meaningful domain operations.
Question: Your framework supports Selenium, Playwright, REST Assured, database testing, and Kafka testing. Developers complain that the framework is becoming too large. How would you architect it?
Answer: Strong answer
I would avoid creating one giant framework.

Instead, I would create a modular automation platform.
automation-platform/

├── core/
│   ├── config
│   ├── logging
│   ├── reporting
│   └── test lifecycle

├── ui/
│   ├── selenium
│   └── playwright

├── api/

├── database/

├── messaging/
│   └── kafka/

└── integrations/
Teams should consume only what they need.

For example :
UI Team
→ core + playwright

API Team
→ core + api

Messaging Team
→ core + kafka
This avoids forcing every project to download or maintain unrelated dependencies.

Architectural principle
Shared platform does not mean shared everything.
Question: Your Selenium Grid has 100 browser nodes, but tests are waiting several minutes for sessions. How would you investigate?
Answer: Strong answer
I would inspect the Grid architecture rather than simply adding more nodes.

I would investigate:
Test requests
      ↓
Router
      ↓
Session Queue
      ↓
Distributor
      ↓
Available slots
      ↓
Node
      ↓
Browser
I would check:
  • Session queue depth
  • Available slots
  • Browser startup time
  • Node health
  • CPU/memory
  • Browser crashes
  • Session cleanup
  • Capability matching
  • Uneven node utilization
For example :
Chrome:
80% utilization

Firefox:
20% utilization

Safari:
100% utilization
The problem may be capability-specific rather than overall capacity.

Senior-level answer
I would measure queue time vs execution time before deciding that more nodes are required.
Question: Your tests are independent when executed individually but fail when executed in parallel. How would you determine whether the framework or application is responsible?
Answer: Strong answer
I would create a controlled experiment.
Sequential
→ PASS

Parallel
→ FAIL
Then vary one dimension at a time.

Test 1

Same tests

1 worker


Test 2

Same tests

2 workers


Test 3

Different test data

2 workers


Test 4

Same data

2 workers
Then inspect:
  • Database records
  • Browser state
  • Cookies
  • Local storage
  • Authentication
  • Files
  • Environment variables
  • Queues
  • API calls
If the failure disappears when unique test data is used:
Likely shared-data collision.

If it remains:
Possible application concurrency issue.

Senior-level principle
Don't automatically label parallel failures as "flaky tests."

Parallel execution can expose real product race conditions.
Question: Your framework has a global static WebDriver object. Tests pass sequentially but fail in parallel. Would you change it?
Answer: Strong answer
Yes.

A global mutable WebDriver is dangerous in parallel execution because multiple tests can potentially interact with the same browser/session.

Instead, driver ownership should be scoped appropriately.

For Selenium:
Test
  ↓
Driver instance
  ↓
Browser session
Potentially:
Worker
  ↓
Driver lifecycle
depending on the framework architecture.

I would avoid:
public static WebDriver driver;
as a shared mutable resource.

I would also separate:
Configuration
≠
Driver state
≠
Test data
≠
Business state
Question: Your company wants one test to create data that 50 other tests reuse. It makes the suite faster, but occasionally one test modifies the data and breaks everyone else. Would you keep this design?
Answer: Generally, no.

This creates a dependency graph:
Test A
  ↓
Creates data
  ↓
Test B
Test C
Test D
Test E
Now Test B isn't actually independent.

A better architecture is:
Test B → Own data
Test C → Own data
Test D → Own data
Data creation can be optimized through:
  • API setup
  • Database fixtures
  • Worker-scoped fixtures where appropriate
  • Data factories
  • Synthetic data
  • Reusable immutable reference data
But mutable business data should generally be isolated.

Exception
Immutable reference data can be safely shared.

For example :
  • Countries
  • Currencies
  • Static product catalog
provided the application does not mutate it during tests.
Question: Your organization has 50,000 tests and developers complain that automation failures are impossible to debug. How would you redesign observability?
Answer: Strong answer
I would treat test execution as an observable distributed system.

Every test should have metadata such as:
  • Test ID
  • Build ID
  • Commit SHA
  • Environment
  • Browser
  • Worker
  • Shard
  • Test-data ID
  • Correlation ID
  • Timestamp
For a failure, I want:
Test
  ↓
Browser trace
  ↓
Network
  ↓
API request
  ↓
Correlation ID
  ↓
Application logs
  ↓
Database / service logs
The framework should automatically capture the right artifacts for failures.

For UI automation:
  • Screenshot
  • Trace
  • Console
  • Network
  • Video where justified
For API:
  • Request
  • Response
  • Headers where safe
  • Correlation ID
For infrastructure:
  • Container/pod
  • CPU
  • Memory
  • Restart information
Important
Don't capture everything for every test if the cost becomes excessive.

Use policies such as:
PASS → minimal artifacts

FAIL → detailed artifacts

RETRY → detailed artifacts
Question: Your automation framework has 30 different configuration files for environments, browsers, credentials, timeouts, and test execution. How would you redesign configuration management?
Answer: Strong answer
I would establish configuration layers.
Default configuration
        ↓
Environment configuration
        ↓
Execution configuration
        ↓
Test-specific override
For example :
config/
 ├── default
 ├── qa
 ├── staging
 └── production-like
Then:
Environment variables
        ↓
Secrets manager
        ↓
Runtime configuration
Secrets should never be committed to the repository.

I would also separate:
Configuration
≠
Secrets
≠
Test data
For example :
  • BASE_URL → configuration
  • API_TIMEOUT → configuration
  • API_TOKEN → secret
  • CUSTOMER_ID → test data
Senior-level principle
Configuration should be centralized enough to govern but flexible enough to support independent execution.
Question: Your framework has hardcoded URLs, usernames, browser names, timeout values, and database connection strings throughout the codebase. How would you migrate it without stopping feature development?
Answer: Strong answer
I would treat this as a gradual refactoring problem, not a rewrite.

Phase 1 — Inventory
Search the repository for:
http://
https://
username
password
jdbc:
chromium
firefox
timeout
Phase 2 — Introduce configuration abstraction
config.getBaseUrl()

config.getBrowser()

config.getTimeout()
Phase 3 — Migrate incrementally
New tests must use the new approach.

Existing tests are migrated when modified.

Phase 4 — Add static checks
Prevent new hardcoded configuration.

Phase 5 — Remove old implementation
Once usage reaches zero.

Senior-level principle
Don't create a six-month refactoring project when you can make the codebase progressively healthier with every change.
Question: Your framework has a retry mechanism that reruns every failed test three times. It reduced pipeline failures by 70%. Would you consider this a success?
Answer: Strong answer
Not necessarily.

I would separate:
  • Initial failure
  • Retry success
  • Final result
Suppose:
10,000 tests

Initial failures = 500

Retry passes     = 350

Final failures   = 150
The final pipeline might look healthy:
98.5% PASS
But:
Flake/initial failure rate = 5%
is still concerning.

Retries can also be dangerous when tests have side effects:
Create order

Charge card

Send email

Publish event
A retry may duplicate the operation.

I would use retries as:
Diagnostic signal
+
Temporary resilience mechanism
not as:
Permanent solution for flaky tests
Question: Your team wants to create a reusable BaseTest class containing 2,000 lines of setup and utility logic. Would you approve it?
Answer: Strong answer
I would probably reject the design.

A huge BaseTest creates hidden dependencies.
Test
  ↓
BaseTest
  ↓
BaseBaseTest
  ↓
Utility
  ↓
AnotherUtility
Eventually developers don't know:
"What exactly does this test depend on?"

I would use composition instead.
Test
 ├── AuthFixture
 ├── TestDataFixture
 ├── APIClient
 ├── DBClient
 └── BrowserFixture
This makes dependencies explicit.

Principle
Prefer explicit dependencies and composition over inheritance-heavy test frameworks.
Question: Your framework is used by 15 teams, but each team needs slightly different behavior for authentication, reporting, test data, and environments. How would you support customization without creating forks?
Answer: I would introduce extension points rather than allowing teams to modify the framework source.

For example :
Core Framework
      |
      +-- Authentication interface
      |
      +-- Reporting interface
      |
      +-- Data provider interface
      |
      +-- Environment provider
Then:
Team A → AuthProviderA

Team B → AuthProviderB

Team C → AuthProviderC
The core framework remains stable.

Avoid
framework-teamA
framework-teamB
framework-teamC
because eventually:
15 teams
×
different versions
=
maintenance nightmare
Architecture principle
Stable core + controlled extension points > uncontrolled customization.
Question: Your automation framework is tightly coupled to Selenium, and management wants to migrate some applications to Playwright. How would you design the migration?
Answer: I would not attempt a "big bang" migration.

I would first identify:
  • What Selenium provides
  • What the framework provides
  • What tests actually depend upon
Then introduce an abstraction only where it provides value.

For example :
Test / Domain Layer
        ↓
Browser Interaction Interface
        ↓
+--------------------+
| Selenium Adapter   |
| Playwright Adapter |
+--------------------+
But I would not abstract every browser API just to make Selenium and Playwright look identical.

That often produces a lowest-common-denominator abstraction.

Migration strategy
  • Phase 1: New tests → Playwright
  • Phase 2: High-maintenance Selenium tests → migrate
  • Phase 3: Stable low-value Selenium tests → evaluate
  • Phase 4: Remove unnecessary Selenium infrastructure
Senior-level principle
Migrate based on business value and maintenance cost, not technology fashion.