jpesewang.work
HomeProjectsBlogContact
Back to Blog
From Zero to Scalable: Building a Test Automation Framework with Playwright
Leif Le
January 19, 2026
15 min read

From Zero to Scalable: Building a Test Automation Framework with Playwright

TestingPlaywrightSDET

When people talk about automation testing, they often think about “writing some scripts with Playwright or Cypress”. But in real projects, automation is not just about scripts. It’s about building a testing framework that is scalable, maintainable, and reliable. Playwright is the engine. The framework is how you design everything around it. In this blog, I’ll share how I use Playwright to build a testing framework from scratch, and why concepts like Page Object Model and Data-Driven Testing are essential.

1. Why Playwright?

I chose Playwright because:

  1. It supports modern web apps (React, NextJS, SPA)
  2. Built-in TypeScript support
  3. Can test:

-UI (E2E)

-API

-Multiple browsers

  1. Strong reporting (screenshots, videos, HTML reports)
  2. Fast and stable compared to older tools

Playwright fits perfectly for a Full-stack Test Engineer / SDET role where we need both UI and API testing in one place.



2. Automation Tool vs Testing Framework

This is a big misunderstanding:

  1. Playwright = automation tool
  2. Testing framework = architecture + structure + standards

Without a framework:

  1. Tests are hard to maintain
  2. UI change breaks many files
  3. Team cannot scale automation

With a framework:

  1. Code is clean
  2. Tests are reusable
  3. Easy for multiple people to work together



3. Project Structure

A simple but professional structure:


tests/
├── e2e/
│ └── login.spec.ts
├── api/
│ └── auth.api.spec.ts
├── pages/
│ └── LoginPage.ts
├── data/
│ └── loginData.ts
├── utils/
│ └── helpers.ts
playwright.config.ts

Each folder has a clear responsibility:

  1. pages → Page Object Model
  2. data → Test data
  3. e2e → UI test scenarios
  4. api → API tests

This already looks like a real test framework, not just scripts.



4. Page Object Model (POM)

POM is the backbone of any good automation framework.

Instead of writing selectors directly in tests:


await page.fill('#email', 'test@mail.com');

We encapsulate UI inside a page class:


// pages/LoginPage.ts
export class LoginPage {
constructor(private page) {}

emailInput = this.page.locator('#email');
passwordInput = this.page.locator('#password');
loginButton = this.page.locator('#login');

async login(email: string, password: string) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.loginButton.click();
}
}

Test case becomes:


test('login success', async ({ page }) => {
const loginPage = new LoginPage(page);
await page.goto('/login');
await loginPage.login('test@mail.com', '123456');
});

Benefits:

  1. Clean code
  2. Easy to read
  3. UI changes → fix one file
  4. Highly reusable



5. Data-Driven Testing

Instead of hard-coding data, we separate data from logic.


// data/loginData.ts
export const loginData = [
{ email: 'user@test.com', password: '123456', expected: 'success' },
{ email: 'user@test.com', password: 'wrong', expected: 'fail' },
{ email: '', password: '123456', expected: 'validation error' }
];

In test:


for (const data of loginData) {
test(`login case: ${data.expected}`, async ({ page }) => {
const loginPage = new LoginPage(page);
await page.goto('/login');
await loginPage.login(data.email, data.password);
});
}

Benefits:

  1. One test logic → many test cases
  2. Easy to add new cases
  3. Higher coverage with less code



6. E2E + API in One Framework

With Playwright, we can test UI and API together.

Example API test:


test('login API returns token', async ({ request }) => {
const res = await request.post('/api/login', {
data: { email: 'test@mail.com', password: '123456' }
});
expect(res.status()).toBe(200);
});

This makes the framework truly full-stack:

  1. UI tests protect user experience
  2. API tests protect backend logic



7. Regression and Smoke Suites

In real projects:

  1. Smoke tests → check system is alive
  2. Regression tests → protect existing features

Example:


tests/
smoke/
regression/

Before every release:


npx playwright test regression

This becomes your safety net.



8. Reporting & Debugging

Playwright gives:

  1. Screenshot on failure
  2. Video recording
  3. HTML report

This is crucial in professional environments.



9. What “Building a Framework from Scratch” Really Means

It does NOT mean:

Rewriting Playwright

It means:

  1. Designing folder structure
  2. Applying POM
  3. Using Data Driven approach
  4. Writing reusable helpers
  5. Supporting API + UI tests
  6. Making it maintainable and scalable

In interviews, I usually explain it as:

“Playwright is my engine. The framework is how I design architecture, patterns, and structure so automation becomes a long-term asset, not just a set of scripts.”



10. Conclusion

A real automation engineer is not judged by how many scripts they write, but by:

  1. How maintainable their tests are
  2. How easy it is to extend
  3. How well they protect product quality

Playwright + a well-designed testing framework is a perfect foundation for a Full-stack Test Engineer / SDET role.

If you come from a development background, building your own testing framework is the best way to prove that you truly understand both engineering and quality.

Related Articles

TypeScript Best Practices for Large Applications

Essential TypeScript patterns and practices that will help you build maintainable applications.

Jan 5, 202410 min read

React Performance Optimization Techniques

Learn advanced techniques to optimize your React applications for better performance.

Dec 28, 202315 min read

Enjoyed this article?

Subscribe to get notified about new articles and updates.