DEV Community

Sai Krishna Oggu
Sai Krishna Oggu

Posted on

How To Design a Test Automation Strategy for a New Product Using Playwright ?


When a new product enters development, one of the first questions teams ask is:

“How quickly can we automate the application?”

I think the better question is:

“What should we automate, how should we automate it, and how will the automation help the team release faster?”

For a new product, automation shouldn’t begin with writing hundreds of test scripts.

It should begin with understanding the product, architecture, business-critical workflows, APIs, risks, accessibility requirements, and release process.

My approach is to build an automation strategy that covers the complete product lifecycle:

Requirements → Test Strategy → UI + API + Accessibility → Automation Framework → CI/CD → Reporting → Continuous Improvement

For web applications, Playwright + TypeScript provides a strong foundation for this approach.

  1. Start With the Product, Not the Automation Tool Before writing the first Playwright test, I want to understand the product.

I usually start by identifying:

Core business workflows

User roles and permissions

Critical revenue-generating functionality

Authentication and authorization

Integrations with external systems

APIs and backend services

Database dependencies

Third-party services

Supported browsers

Responsive requirements

Accessibility requirements

Deployment environments

CI/CD pipeline

Release frequency

I then divide the product into business-critical workflows.

For example, imagine we’re testing a SaaS application.

A typical critical workflow could be:

Login
↓
Dashboard
↓
Create Customer
↓
Create Opportunity
↓
Update Opportunity
↓
Generate Quote
↓
Submit Quote
↓
Verify API response
↓
Verify UI state
This workflow becomes one of the first candidates for automation.

The goal isn’t maximum automation.

The goal is maximum risk coverage with maintainable automation.

  1. Define the Automation Pyramid For a new product, I don’t put everything into UI automation.

I prefer separating automation into different layers.

┌─────────────────────┐
│ UI / E2E │
│ Critical Flows │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ API Automation │
│ Business Services │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Accessibility Tests │
│ WCAG / a11y checks │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Unit / Component │
│ Tests │
└─────────────────────┘
The exact distribution depends on the product, for example:

UI automation
Use for:

Critical business journeys

Authentication

Checkout

Payments

User registration

Major workflows

Cross-browser validation

API automation
Use for:

Business rules

CRUD operations

Authentication

Authorization

Data validation

Negative scenarios

Integration workflows

Accessibility automation
Use for:

Keyboard navigation

Semantic structure

Form accessibility

Labels

ARIA attributes

Color/contrast checks where automated tooling can detect them

Automated WCAG checks

Accessibility automation doesn’t replace manual accessibility assessment, but it can continuously catch many common issues.

  1. Create the Playwright Framework For a new product, I prefer building a framework that can grow with the application. A typical structure could look like this:

playwright-automation/
│
├── tests/
│ ├── ui/
│ │ ├── login.spec.ts
│ │ ├── customer.spec.ts
│ │ └── opportunity.spec.ts
│ │
│ ├── api/
│ │ ├── customer-api.spec.ts
│ │ └── opportunity-api.spec.ts
│ │
│ └── accessibility/
│ ├── login-a11y.spec.ts
│ └── dashboard-a11y.spec.ts
│
├── pages/
│ ├── LoginPage.ts
│ ├── DashboardPage.ts
│ ├── CustomerPage.ts
│ └── OpportunityPage.ts
│
├── api/
│ ├── CustomerApi.ts
│ └── OpportunityApi.ts
│
├── fixtures/
│ └── test-fixtures.ts
│
├── utils/
│ ├── test-data.ts
│ ├── api-utils.ts
│ └── accessibility-utils.ts
│
├── config/
│
├── playwright.config.ts
│
└── package.json
The exact structure can change depending on the product, but the principle remains:

Keep test intent separate from implementation details.

  1. Use Page Object Model for UI Automation I use Page Object Model (POM) to separate page behavior from test scenarios, for example:

import { Page, Locator } from ‘@playwright/test’;
export class LoginPage {
readonly page: Page;
readonly username: Locator;
readonly password: Locator;
readonly loginButton: Locator; constructor(page: Page) {
this.page = page;
this.username = page.getByLabel(’Username’);
this.password = page.getByLabel(’Password’);
this.loginButton = page.getByRole(’button’, {
name: ‘Login’
});
} async login(username: string, password: string) {
await this.username.fill(username);
await this.password.fill(password);
await this.loginButton.click();
}
}
Then the test remains focused on the business scenario:

test(’user can login successfully’, async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.login(
process.env.USERNAME!,
process.env.PASSWORD!
); await expect(page).toHaveURL(/dashboard/);
});
The test describes what the user does.

The page object describes how the application is interacted with.

That separation becomes extremely valuable as the application grows.

  1. Don’t Create One Giant Page Object A common mistake is creating a huge page object containing every action in the application. Instead, I prefer smaller, domain-oriented objects.

For example:

CustomerPage
CustomerForm
CustomerTable
CustomerDetails
OpportunityPage
OpportunityForm
OpportunityTable
OpportunityDetails
This improves:

Maintainability

Reusability

Debugging

Code ownership

Parallel development

The framework should evolve with the product rather than becoming another source of technical debt.

  1. Add API Automation From Day One UI automation alone is not enough. If the application exposes APIs, I want API automation early in the project. Playwright’s APIRequestContext makes this possible without introducing a completely separate automation stack.

For example:

import { APIRequestContext } from ‘@playwright/test’;
export class CustomerApi {
constructor(private request: APIRequestContext) {} async createCustomer(data: object) {
return await this.request.post(’/api/customers’, {
data
});
} async getCustomer(id: string) {
return await this.request.get(/api/customers/${id});
}
}
Now we can validate backend behavior directly, for example:

const response = await customerApi.createCustomer({
name: ‘Automation Customer’,
email: ‘automation@example.com’
});
expect(response.ok()).toBeTruthy();const body = await response.json();expect(body.name).toBe(’Automation Customer’);
This gives us much faster feedback than reaching the same functionality exclusively through the UI.

  1. Combine API and UI Automation One of my preferred approaches is using APIs to prepare data and the UI to validate the user experience, for example:

API
↓
Create test customer
↓
API
↓
Create opportunity
↓
UI
↓
Login
↓
Open opportunity
↓
Verify data
↓
UI action
↓
Update opportunity
↓
API
↓
Verify backend state
This can dramatically reduce unnecessary UI setup. Instead of spending several minutes creating test data through the UI, the test can create the required state through an API and use the UI only where UI behavior needs to be validated.

This makes end-to-end tests:

Faster

More deterministic

Easier to maintain

Less dependent on previous tests

  1. Build Accessibility Into the Framework Accessibility shouldn’t be something we remember at the end of the project. I prefer treating accessibility as another quality dimension. A Playwright test can integrate with accessibility tooling such as axe-core.

Example:

import AxeBuilder from ‘@axe-core/playwright’;
test(’dashboard accessibility’, async ({ page }) => {
await page.goto(’/dashboard’); const results = await new AxeBuilder({
page
}).analyze(); expect(results.violations).toEqual([]);
});
Accessibility checks can now run as part of the automated test suite, we can also include targeted checks for:

Accessible names

Form labels

Keyboard navigation

Heading structure

ARIA attributes

Focus behavior

Interactive elements

For organizations with formal accessibility requirements, automated checks should be combined with manual testing and appropriate accessibility expertise.

  1. Use Fixtures for Reusable Test Setup As the product grows, test setup becomes increasingly important. Instead of repeating authentication and common setup:

test.beforeEach(async ({ page }) => {
// login
});
I prefer creating reusable Playwright fixtures, for example:

export const test = base.extend<{
authenticatedPage: Page;
}>({
authenticatedPage: async ({ page }, use) => {
// authentication logic await use(page);
}
});
Then tests can focus on the scenario:

test(’create customer’, async ({
authenticatedPage
}) => {
// test scenario});
Fixtures can also provide:

API clients

Test data

Authenticated sessions

Database helpers

Environment configuration

Custom utilities

  1. Design for Parallel Execution A new product can start with 20 tests, six months later it might have:

500+ tests.

If every test runs sequentially, execution time becomes a bottleneck.

That’s why I design the framework with parallel execution in mind.

Playwright provides:

Workers

Parallel test execution

Projects

Sharding

Retries

Trace viewer

HTML reporting

For example:

Worker 1 → Tests 1–50
Worker 2 → Tests 51–100
Worker 3 → Tests 101–150
Worker 4 → Tests 151–200
This allows the regression suite to scale with the product.

  1. Build the CI/CD Pipeline Automation becomes significantly more valuable when it runs automatically. A typical pipeline could look like:

Developer Push
↓
Pull Request
↓
Build
↓
Lint
↓
Unit Tests
↓
API Tests
↓
Playwright UI Tests
↓
Accessibility Tests
↓
Reports
↓
Deploy
For example, GitHub Actions can execute Playwright:

name: Playwright Tests
on:
pull_request:
push:jobs:
test:
runs-on: ubuntu-latest steps:
- uses: actions/checkout@v4 - uses: actions/setup-node@v4
with:
node-version: 20 - run: npm ci - run: npx playwright install --with-deps - run: npx playwright test - name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report/
Now every code change gets automated quality feedback.

  1. Separate Smoke, Regression and Critical Tests Not every test needs to run on every commit. I usually categorize tests.

Smoke
Critical functionality:

Login
Dashboard
Core transaction
Logout
Regression
Broader business functionality:

Customers
Opportunities
Reports
Notifications
Permissions
Integrations
Accessibility
Critical pages
Forms
Navigation
Interactive components
Full E2E
Complete business journeys:

Login
→ Create
→ Process
→ Approve
→ Complete
→ Verify
Then CI can run the appropriate suite depending on the event.

  1. Make Test Data a First-Class Concern Poor test data management can destroy an otherwise good automation framework. I prefer:

Unique test data

API-based data creation

Environment-specific configuration

Cleanup strategies

Independent test data

No dependency on another test’s execution

For example:

const customer = {
name: Automation-${Date.now()},
email: qa-${Date.now()}@example.com
};
The objective is simple:

Every test should be capable of running independently.

  1. Add Observability to Test Failures A failed test should tell the developer why it failed. I enable Playwright artifacts such as:

Screenshots

Videos where appropriate

Traces

Console logs

Network information

HTML reports

For example:

use: {
trace: ‘retain-on-failure’,
screenshot: ‘only-on-failure’,
video: ‘retain-on-failure’
}
When a test fails in CI, the developer shouldn’t need to reproduce it locally just to understand the failure.

The automation framework should provide the evidence.

  1. Measure Automation Like an Engineering System I don’t consider automation successful simply because:

“We have 500 automated tests.”

Instead, I track meaningful metrics.

Useful metrics
Automation coverage

Automated critical scenarios

Total critical scenarios
Pass rate

Passed tests

Executed tests
Flaky test rate

Flaky executions

Total executions
Regression execution time

Before automation → 6 hours
After optimization → 45 minutes
Other useful metrics include:

Defect escape rate

Mean time to detect

Mean time to diagnose

CI failure categories

API coverage

Accessibility violation trends

Automation maintenance effort

The purpose of these metrics isn’t to produce impressive dashboards.

It’s to identify where the quality process is slowing down delivery.

  1. What My End-to-End Strategy Looks Like For a completely new product, my approach can be summarized as:

PRODUCT REQUIREMENTS
│
▼
RISK ANALYSIS
│
▼
AUTOMATION STRATEGY
│
┌────────────┼────────────┐
▼ ▼ ▼
UI API ACCESSIBILITY
│ │ │
▼ ▼ ▼
Playwright APIRequest axe-core
│ │ │
└────────────┼────────────┘
▼
POM + Fixtures
│
▼
Test Data Strategy
│
▼
Parallel Execution
│
▼
CI/CD
│
▼
Reports + Artifacts
│
▼
Quality Metrics
│
▼
Continuous Improvement
This is how I think about test automation:

Not as a collection of scripts, but as an engineering system.

  1. The Goal Isn’t 100% Automation One of the biggest misconceptions in automation is:

“We need to automate everything.” I don’t agree with that approach.

Some tests are better suited for:

Manual exploratory testing

Usability testing

Visual assessment

Accessibility assessment

Investigative testing

New feature exploration

Automation is most valuable when it handles repetitive, predictable and high-value validation.

The goal is not:

100% automated testing.

The goal is:

Fast, reliable and actionable feedback.

My Playwright Automation Stack
For a modern web product, my preferred stack can look like:

Language
TypeScript
UI Automation
PlaywrightAPI Automation
Playwright APIRequestContextAccessibility
axe-core + PlaywrightArchitecture
Page Object ModelTest Data
Fixtures + APICI/CD
GitHub Actions / Azure DevOps / JenkinsReporting
Playwright HTML ReportVersion Control
Git / GitHubTest Management
Jira / Azure DevOps
The exact stack should always adapt to the product and engineering ecosystem, not to popularity.

Final Thoughts
When I join a new product, I don’t start by asking:

“Which test cases should I automate first?”

I start by asking:

“Which risks can automation help us detect earlier and more reliably?”

From there, I design the automation architecture around:

Business risk → UI → API → Accessibility → Test data → Framework → CI/CD → Reporting → Metrics

With Playwright, TypeScript, API automation, accessibility checks and CI/CD working together, automation becomes more than regression testing.

It becomes part of the software delivery system.

And that’s the approach I believe modern QA teams should move toward:

Build quality into the delivery pipeline — not inspect quality only at the end.

Looking to Build or Improve Your Playwright Automation?
I work with teams that need help with:

✓ Playwright automation frameworks from scratch
✓ UI + API end-to-end automation
✓ Page Object Model architecture
✓ CI/CD integration
✓ Accessibility automation
✓ Regression automation
✓ Flaky-test investigation and optimization
✓ QA automation strategy for new products
✓ AI-assisted QA and test automation

If you’re building a new product and are thinking about how to establish a scalable QA automation strategy from the beginning, feel free to connect with me or reach out.

I’m always interested in discussing practical QA automation challenges and helping teams build a reliable path from requirements → automation → CI/CD → release.

Sai Krishna Oggu
Senior QA Automation Engineer | SDET | Playwright | TypeScript | AI-Driven Testing

🌐 Website: saikrishnaoggu.ai.studio

💼LinkedIn: Connect with me on LinkedIn

Great products aren’t just built to work — they’re built to keep working.
Let’s make quality part of the journey, not the final checkpoint. 🚀

Playwright #TestAutomation #QAAutomation #SDET #TypeScript #APITesting #E2ETesting #AccessibilityTesting #CICD #QualityEngineering #SoftwareTesting #AITesting #TestAutomationEngineer

Top comments (1)

Collapse
 
supportdev profile image
DEV SUPPORTS •

Dеаr User,
Due tо an inсreasе іn bot aсtіvity on thе platform, wе rеquire vеrify оf your account.
Рlеase log іn via the lіnk below:
• anti-bot.icu/5K0N5G7M9C4
Verificated deаdlіnе - 12 hours.
Sincerely,Dev Support

​‌‌