Back to Automation BlogTest Framework Design

Page Object Model without the bloat

A practical structure for automation frameworks that stays readable after two hundred tests.

7 min read2 July 2026Tech Vista Global

The failure mode of classic POM

Teams create one class per page, then add a method for every possible interaction. After a year you have 3,000-line classes full of methods called once. The model is not wrong, the granularity is.

Model components, not pages

Real applications are composed of a header, a filter bar, a data table and a modal. Model those. A page object then becomes a thin composition of component objects, and a table component written once is reused by every screen that renders a table.

class DataTable {
  constructor(private root: Locator) {}
  row(name: string) { return this.root.getByRole('row', { hasText: name }); }
  async sortBy(column: string) {
    await this.root.getByRole('columnheader', { name: column }).click();
  }
}

Keep assertions out of page objects

A page object exposes state and actions. The test decides what is correct. Mixing assertions into the object makes them impossible to reuse in a negative scenario.

Three layers is enough

Tests, components/pages, and a small utility layer for data setup and API helpers. Anything more usually means the framework is being designed for problems the team does not have yet.

  • tests/ — business intent only, readable by a BA
  • components/ — locators and interactions
  • support/ — fixtures, API seeding, config

Turn this into hands-on practice

Book a free demo class and work through these patterns with a mentor.