20 min read · 9 self-checks · Updated June 2026

Automation Technique · Mid-Level & Senior SDET

Test Automation Design Patterns

Design patterns are reusable solutions to recurring automation problems. Knowing them prevents you from reinventing the wheel — and from writing test code that nobody can maintain six months later.

Mid-Level Senior SDET ISTQB CTAL-TAE

1 The Hook

An SDET team writes 400 tests over 6 months. No design patterns. Every test directly selects elements. When the app redesigns the navigation, 280 tests break. Every test needs individual fixing. Three weeks of work.

If they'd used Page Object Model, only the nav page object would need updating. One file changed, 280 tests passing again in an hour. The cost of skipping patterns isn't paid when you write the tests — it's paid every time something changes.

💬
Senior Engineer Insight

Every team I've worked with adopts POM because they intend to keep page objects thin. Within six months, someone starts adding API calls, database seeding, and assertion logic directly into the page object because it's "convenient." The object hits 700 lines and nobody can reason about it anymore. The pattern didn't fail — the boundary discipline did. When I review automation suites at NZ financial institutions and government agencies, the surest sign of a mature team isn't whether they use POM — it's whether their page objects contain zero assertions and zero data setup. Keep page objects dumb: one concern, one file. Everything else belongs in a helper, a builder, or a fixture. If you have to scroll to find the selector, the object is already too fat.

2 The Rule

Apply the right pattern before you write the tests, not after 400 of them break. Test code is production code — it needs the same design discipline.

3 The Analogy

Analogy

Design patterns are like standardised fittings in plumbing.

Every plumber uses the same thread sizes, connector types, and valve patterns. Not because there's only one way to join pipes, but because standardised patterns mean any plumber can pick up where another left off, and any part is replaceable. Test automation patterns work the same way — a new SDET joins the team and can navigate the codebase immediately because they recognise the patterns.

Common Mistake vs What Works

✗ Common mistake

Page Object Model structured as a direct mirror of the UI — one class per page, one method per element. When the UI is redesigned, 30 POM classes need updating simultaneously. The maintenance burden compounds with every sprint, until fixing tests takes longer than writing them.

✓ What actually works

Model POM at the component and behaviour level, not the page and element level. A SearchBar component is reused across 5 pages. Methods describe user intent — searchForProduct() not clickSearchIcon(). One component changes, every page that uses it is fixed. Business actions, not implementation details.

Senior engineer insight

The single decision that changed how I design automation suites: stop treating patterns as things you add to a project and start treating them as constraints that survive personnel change. POM, Builder, Factory — their real value isn't the first sprint you use them, it's sprint 40 when three SDETs have turned over and a contractor who joined last week can still find the right file in under two minutes. Maintainability is a social contract, not a technical one.

Most common mistake: teams adopt POM but let page objects absorb assertions, API calls, and data setup because "it's convenient." Within six months the objects hit 600+ lines and nobody can reason about them — the pattern didn't fail, the boundary discipline did.

4 Watch Me Do It

Five patterns with TypeScript/Playwright examples:

1. Page Object Model (POM)

Encapsulate page selectors and interactions in a class. Tests call methods, not selectors. When the UI changes, update the page object — not the tests.

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

  async login(username: string, password: string) {
    await this.page.fill('[data-testid="username"]', username);
    await this.page.fill('[data-testid="password"]', password);
    await this.page.click('[data-testid="login-btn"]');
  }
}

// tests/login.spec.ts — no selectors, only intent
test('valid login redirects to dashboard', async ({ page }) => {
  const loginPage = new LoginPage(page);
  await loginPage.login('tester@resync.nz', 'Test1234!');
  await expect(page).toHaveURL('/dashboard');
});

From the field

A Wellington fintech engaged us to stabilise a Playwright suite that was failing on every deploy. The root cause: 340 tests with raw selectors scattered across spec files, no POM, no Builder — just copy-pasted setup blocks and hardcoded NZ bank account numbers embedded in assertion strings. When they redesigned their onboarding flow, two engineers spent three weeks manually updating individual selectors. We introduced POM at the component level (not page level), a CustomerBuilder with NZ-realistic defaults, and a single toBeValidNZBankAccount custom matcher. The next onboarding redesign, six months later, took four hours. The lesson that generalises: the upfront cost of a pattern is fixed; the payback compounds with every change thereafter — and NZ product teams change their UIs constantly.

2. Screenplay Pattern

Actors perform Tasks using Interactions. More verbose than POM but better at modelling complex multi-step user journeys. Use when POM objects grow too large to manage.

// tasks/SubmitRatesPayment.ts
export const SubmitRatesPayment = (amount: number) => ({
  performAs: async (actor: Actor) => {
    await actor.attemptsTo(
      Navigate.to('/rates/pay'),
      Enter.theValue(amount).into(RatesPage.amountField),
      Click.on(RatesPage.reviewButton),
      Click.on(RatesPage.confirmButton)
    );
  }
});

// test reads like a user story
await actor.attemptsTo(SubmitRatesPayment(450.00));

3. Builder Pattern for Test Data

Fluent interface for constructing test fixtures. Avoids sprawling factory functions and makes test intent readable.

// builders/CustomerBuilder.ts
export class CustomerBuilder {
  private data = { name: 'Default User', region: 'Auckland', kiwisaver: false };

  withName(name: string)         { this.data.name = name; return this; }
  inRegion(region: string)       { this.data.region = region; return this; }
  withKiwiSaver()                { this.data.kiwisaver = true; return this; }
  build()                        { return { ...this.data }; }
}

// Test reads what matters, ignores the rest
const customer = new CustomerBuilder()
  .inRegion('Wellington')
  .withKiwiSaver()
  .build();

4. Custom Assertion / Matcher

Extend the assertion library with domain-specific matchers. Makes failing assertion messages meaningful to the team.

// matchers/toBeValidNZBankAccount.ts
expect.extend({
  toBeValidNZBankAccount(received: string) {
    const pattern = /^\d{2}-\d{4}-\d{7}-\d{2,3}$/;
    return {
      pass: pattern.test(received),
      message: () =>
        `Expected "${received}" to be a valid NZ bank account (xx-xxxx-xxxxxxx-xx)`
    };
  }
});

// Usage — failure message is self-documenting
expect(account.number).toBeValidNZBankAccount();

5. Factory Pattern for Page Objects

Centralise page object instantiation. Avoids scattering new LoginPage(page) across every test file, and makes swapping implementations easy.

// pages/PageFactory.ts
export class PageFactory {
  constructor(private page: Page) {}

  loginPage()    { return new LoginPage(this.page); }
  dashboardPage(){ return new DashboardPage(this.page); }
  paymentPage()  { return new PaymentPage(this.page); }
}

// Test fixture — one factory, consistent construction
test.beforeEach(async ({ page }, testInfo) => {
  testInfo.factory = new PageFactory(page);
});
When to use which pattern
PatternUse whenAvoid when
POMStandard UI automation — always a good defaultPage objects grow to 500+ lines; consider Screenplay
ScreenplayComplex multi-actor user journeys; BDD teamsSimple CRUD apps — overkill, adds verbosity
BuilderComplex test data with many optional fieldsSimple fixtures with 2–3 fields — direct object is fine
Custom AssertionDomain-specific validation appears frequentlyOne-off checks — inline assertion is simpler
FactoryMany page objects, multiple test suitesSmall test suite with 2–3 page objects

5 When to Apply Patterns

  • From day 1 — POM is not optional overhead; it's the minimum viable structure for any UI automation suite over 20 tests.
  • When test data setup is repetitive — Builder pattern. If you're copying object literals across tests, you're creating maintenance debt.
  • When assertions repeat domain logic — Custom Matchers. NZ bank account format, Revenue NZ number format, date range validation — write it once.
  • When a new SDET joins and asks "where do I create a page object?" — Factory. That question reveals you don't have one yet.

6 Common Mistakes

❌ I used to think: design patterns are for production code, not tests.

Actually: test code has the same maintenance burden as production code — sometimes higher. Tests change when requirements change and when the UI changes. Without patterns, every requirement change ripples through hundreds of test files. With POM, one page object changes.

❌ I used to think: I'll refactor into patterns later.

Actually: refactoring 400 tests into POM is a 2-week project. Applying POM from test 1 takes 20 minutes. The longer you wait, the more expensive it gets. "We'll add patterns when the suite is bigger" is how you end up with the 3-week repair job from the hook.

❌ I used to think: Screenplay is better than POM — I'll use it for everything.

Actually: Screenplay adds significant structural complexity that pays off in large, multi-actor user journeys. For a simple login-and-verify test suite, POM is cleaner and faster to write. Match pattern complexity to problem complexity.

7 Industry Reality

🏭 What you actually encounter on the job
  • POM is rarely pure in the wild. Most teams end up with hybrid "page objects" that also contain test logic, API calls, and data setup. You'll inherit these; the skill is knowing what's wrong and incrementally improving without breaking everything.
  • Pattern adoption is uneven. One engineer uses Screenplay religiously, another writes raw selectors in every test, and the CI pipeline treats both the same. As a senior SDET, you'll spend real time establishing and enforcing conventions — code review comments, linting rules, team guidelines — not just writing patterns yourself.
  • Legacy test suites at NZ enterprises (banks, government agencies, telcos) can have 2,000+ tests with zero patterns. You won't rewrite them. You'll apply the strangler fig approach: wrap the worst areas in page objects as you touch them, tolerate inconsistency in areas you're not touching.
  • Builder patterns collide with test data environments. NZ teams often can't generate arbitrary test data freely — shared staging environments, masked data from production, Privacy Act 2020 constraints on PII in test systems. Your Builder pattern needs to know what's legal to create, not just what's technically possible.
  • Teams underestimate pattern setup time. Introducing POM for the first time on an active project means establishing conventions, training the team, updating the PR template, and probably fixing 3-4 tests that were already written wrong before the PR merges. Budget a sprint for it — not an afternoon.

8 When to Use It — and When Not To

⚡ Decision guide

✓ Use patterns when

  • You're starting a UI automation suite of any meaningful size (20+ tests) — POM is non-negotiable from day one
  • Test data setup is copy-pasted across 3 or more tests — reach for Builder immediately
  • The same domain validation logic (NZ Revenue NZ numbers, NZ bank account format, NZ phone format) appears in multiple tests — Custom Matcher pays back instantly
  • Your team has more than one SDET writing tests — without Factory and POM, you'll get inconsistent instantiation patterns within weeks
  • You're testing a complex multi-actor workflow (e.g., CoverNZ claim submitted by claimant, reviewed by assessor, approved by manager) — Screenplay is genuinely the right tool here

✗ Skip (or defer) when

  • You're writing a 5-test smoke suite for a one-off deployment — raw Playwright with no patterns is fine; don't over-engineer throwaway scripts
  • You have fewer than 3 page objects — a Factory is premature abstraction; just instantiate them directly
  • Your team has never used Screenplay before and you're under delivery pressure — POM first, Screenplay is a significant learning curve you don't need right now
  • The domain validation rule is used exactly once — an inline assertion is simpler than a Custom Matcher that only appears in one place
  • The test suite is owned by QAs who don't code — POM with very simple method names is achievable; Screenplay or Factory patterns will be abandoned the moment you leave the project

Context guide

How the right level of Test Automation Patterns effort changes based on project context.

Context Priority Why
Revenue NZ or Benefits NZ enterprise automation suite (100+ tests, multiple sprints) Essential Government portals redesign navigation and forms every major release. Without POM, each redesign triggers weeks of test repair. Pattern investment pays back within the first UI change cycle.
CoverNZ or HealthNZ claims portal with multi-role workflows (claimant, assessor, approver) Essential Three distinct actor types performing overlapping tasks is precisely the scenario Screenplay and Factory patterns were designed for. POM alone will produce bloated objects trying to model all three roles simultaneously.
Harbour Bank or Pacific Bank retail banking automation with Privacy Act 2020 PII constraints High Builder pattern is critical here — test data must comply with Privacy Act 2020 by default, not be patched per test. A well-designed Builder encodes legal NZ data constraints (masked Revenue NZ numbers, synthetic NZ bank accounts) as the starting point, not an afterthought.
TransitNZ or TransitNZ licensing portal — standard CRUD flows, single actor type High POM and Builder are the right defaults. Screenplay is unnecessary at this complexity level — one actor, linear flows. Custom Matchers for NZ licence plate and driver licence number formats will be reused immediately across the suite.
Pacific Air or Spark short-lived A/B test suite (3–5 tests, one-off deployment) Medium Lightweight POM is worth it even for small suites if the feature will survive more than one sprint. Skip Builder and Factory for throwaway scripts. If the suite will be extended, establish patterns from test 1 — retrofitting is expensive.
One-off smoke check for a production deploy at a startup or small agency Low Genuinely throwaway scripts warrant no pattern overhead. Raw Playwright with inline selectors is fine when the suite will never be extended. The moment someone says "let's add five more checks," the calculus flips — introduce POM immediately.

Trade-offs

What you gain and what you give up when you choose Test Automation Patterns.

Advantage Disadvantage Use instead when…
UI changes cost one file, not hundreds of tests. When Revenue NZ or Benefits NZ redesign their portal navigation, a POM-backed suite is repaired in an hour rather than across a fortnight of test triage. Upfront architecture time before the first test is written. Teams under sprint pressure at Wellington agencies frequently skip patterns, accepting future debt in exchange for short-term velocity. The suite is genuinely throwaway — a one-off smoke check for a single production deploy at a small startup. If it will never be extended, raw Playwright with inline selectors is proportionate.
Test intent is readable to the whole team. A new ClaimBuilder().inRegion('Otago').build() communicates exactly what the test cares about — any NZ tester can read it without decoding object literals spread across spec files. Pattern boundaries erode under pressure. Page objects at CoverNZ or Pacific Bank digital teams routinely absorb assertion logic and API calls because it is "convenient." The pattern degrades silently; test failures become ambiguous within months. Test data has only two or three fields and no optional variation. A direct object literal ({ name: 'Aroha', region: 'Wellington' }) is simpler than a Builder that wraps the same two fields behind a fluent interface.
Domain validation is centralised. A single toBeValidNZBankAccount custom matcher means every test that validates Harbour Bank or KiwiFirst Bank account numbers uses one authoritative rule — update it once when the format changes. Onboarding overhead for less common patterns. Screenplay and Factory require conceptual learning that can slow a new contractor or junior SDET for their first sprint — a real cost on short-tenure government projects. The domain validation appears in exactly one test. An inline assertion is simpler than a custom matcher that is never reused — premature abstraction trades clarity for false tidiness.
Patterns survive personnel change. An SDET who joins an FamiliesNZ or NZ Police automation project three months after it started can navigate the codebase in minutes when POM and Factory conventions are consistently applied. Retrofitting patterns onto a large legacy suite is a sprint-level undertaking. A 400-test Spark or Pacific Air suite written without POM cannot be migrated in an afternoon — it requires scoped refactoring over multiple iterations. The suite will be maintained by QAs who do not code. Screenplay and Factory abstractions will be quietly abandoned the moment the introducing SDET leaves. Thin POM with straightforward method names is the most a non-coding QA can sustain long-term.

Enterprise reality

How Test Automation Patterns change when you are running a 200–300-developer organisation with parallel squads, regulated data, and audit obligations.

  • At small-team scale, POM and Builder are aspirational. At enterprise scale they are non-negotiable infrastructure — Revenue NZ's tax-filing platform runs 12 Playwright squads in parallel; without centralised page object ownership and a shared Factory registry, selector drift across squads creates hundreds of conflicting implementations within a single quarter.
  • Privacy Act 2020, NZISM (NZ Information Security Manual), PCI DSS, and HISF (Health Information Security Framework) all impose constraints on test data. At Harbour Bank and KiwiFirst Bank, Builders must generate synthetic NZ bank account numbers and masked Revenue NZ numbers by default — real customer PII cannot appear in test fixtures, and this must be enforced at the framework level, not left to individual SDETs to remember per test.
  • Tooling decisions calcify at volume. Choosing between Playwright (TypeScript), Selenium WebDriver (Java), and Cypress at a 10-squad scale is a two-year commitment — migration costs are enormous. Organisations like TeleNZ and Pacific Air run governance boards that review automation tooling decisions before adoption, precisely because the wrong choice at sprint 1 is a strategic liability by sprint 100.
  • At 10+ squad scale, shared test infrastructure becomes a product in its own right — not a side responsibility. When TechServNZ's public-sector delivery teams don't own their Factory and Builder dependencies centrally, one squad's breaking change silently fails three other squads' pipelines before anyone notices. Organisations that treat their automation framework as a product (with an owner, a changelog, and a deprecation policy) run faster CI and fewer cross-squad incidents than those that treat it as shared code nobody maintains.

What I would do

Professional judgment — when to reach for Test Automation Patterns, when to skip them, and what to watch for.

If…
I'm starting a Playwright suite for the Benefits NZ MyMSD portal, covering benefit applications, document uploads, and appointment bookings across client, case worker, and manager roles
I would…
Establish POM for each page area on day one (ApplicationPage, DocumentPage, AppointmentPage), wire a Factory into the Playwright fixture layer so no test ever calls new Page() directly, build a BenefitApplicationBuilder with Privacy Act 2020-compliant NZ synthetic data as defaults, and plan for Screenplay when the multi-role workflows are being tested — but not before. The cost of adopting Screenplay too early on a government portal is abandonment; the cost of POM from day one is zero.
If…
I inherit a 400-test Playwright suite at an Harbour Bank or Pacific Bank digital banking project where everything is raw selectors, no patterns, and the team says "we'll refactor later"
I would…
Apply the strangler fig approach: identify the 5 highest-churn areas (usually login, account overview, payment flow) and wrap those in POM first. Add a toBeValidNZBankAccount custom matcher immediately — it will be needed in dozens of tests and it's the highest-leverage one-liner. Introduce a TransactionBuilder for payment test data with NZD defaults. Do not rewrite tests that aren't breaking — introduce patterns as you touch each area. Budget a sprint for the initial POM scaffolding and team upskilling; presenting it as "overhead" to management kills adoption before it starts.
If…
I'm advising an CoverNZ automation team that wants to adopt Screenplay because "it's more modern," but their current suite has 25 tests, one actor type (claimant), and the team has never used Screenplay before
I would…
Recommend POM now, with a clear trigger for revisiting Screenplay: when the suite exceeds 100 tests and a second actor type (the CoverNZ assessor role) is added to workflows. I'd document this decision in the team's testing standards page so it's not relitigated every sprint. Screenplay's verbosity overhead is real — a junior SDET who needs three hours to understand the Actor/Task/Interaction model is an hour not writing tests. The right pattern is the one your whole team can sustain through personnel change, not the most architecturally sophisticated one.

The bottom line: Start with POM on day one — every suite, no exceptions. Layer in Builder when test data setup repeats. Add Custom Matchers the moment a domain validation appears twice. Introduce Factory when you have more than three page objects. Reserve Screenplay for when you have multiple actor types in the same workflow. The pattern that's adopted and maintained beats the pattern that's architecturally ideal but quietly abandoned.

9 Best Practices

✓ What experienced testers do
  • ✓ Name page object methods by user intent, not UI action. loginPage.submitCredentials() not loginPage.clickLoginButton(). When the button becomes a form submission, the method name doesn't need to change.
  • ✓ Keep page objects free of assertions. Page objects handle interactions; tests handle assertions. Mixing them makes failures ambiguous — you can't tell whether the page object or the assertion logic is wrong.
  • ✓ Give Builders sensible defaults. A CustomerBuilder should produce a valid, usable customer with no method calls. Tests only specify what's relevant to them. This way a test about KiwiSaver doesn't need to care about the customer's name.
  • ✓ Scope Custom Matchers to a domain concepts file. All NZ-specific matchers (toBeValidNZBankAccount, toBeValidIRDNumber) in one file, imported in the test setup. Easy to audit, easy to update when the Revenue NZ changes the format.
  • ✓ Version page objects alongside the application under test. When a feature branch changes the UI, the page object change goes in the same PR as the feature. This keeps test infrastructure honest and avoids the "we'll update the tests later" trap.
  • ✓ Enforce patterns via code review, not just documentation. A "design patterns" page in the wiki doesn't stop a junior SDET from writing raw selectors. PR templates with a "patterns checklist" and code review comments that cite standards do.
  • ✓ Write page objects with data-testid selectors only. Agree with dev team upfront that data-testid attributes are a contract. CSS classes and element positions change; test IDs shouldn't. This makes POM stable even through visual redesigns.
  • ✓ Build Builders from real domain data. If you're testing an NZ insurance portal, your ClaimBuilder defaults should use realistic NZ values — Auckland addresses, NZD amounts, CoverNZ claim reference formats. Tests that accidentally validate US-style data are a waste of everyone's time.
  • ✓ Use the Factory pattern as your fixture layer. Playwright fixtures (or Jest beforeEach) should create the factory once, then every test accesses page objects through it. No test should call new SomePage() directly.
  • ✓ Know when to abandon a pattern. If your POM class is 800 lines, it's not a page object anymore — it's a monolith. Split it by feature area, or migrate that section to Screenplay. Patterns are guidelines, not cages.

10 Common Misconceptions

❌ Myth: "We should use Screenplay instead of POM — it's the modern approach."

Reality: Screenplay is an evolution suited to specific problems: large suites with complex multi-actor journeys, or teams doing heavy BDD with Cucumber/SpecFlow. For the majority of NZ project teams running Playwright against a standard web app, POM is faster to write, easier to onboard, and perfectly maintainable. Choosing Screenplay prematurely adds structural overhead that most teams will quietly abandon within a month. Use POM until you have a concrete problem it can't solve.

❌ Myth: "Design patterns slow you down — we don't have time for them in a sprint."

Reality: The time cost of applying POM upfront is about 20 minutes per page area. The time cost of retrofitting POM onto 400 tests written without it is 2-3 weeks. Every sprint you "save" by skipping patterns is a sprint you'll pay back with interest during the next regression cycle or UI redesign. The teams that claim they don't have time for patterns are the same teams spending a quarter of every sprint on flaky test investigation.

❌ Myth: "The Builder pattern is only for API or unit tests — UI tests use hardcoded data."

Reality: Builder is just as valuable for UI tests. When your UI test for claim submission needs a customer with a specific KiwiSaver status, a Wellington address, and a specific policy type, a Builder lets you express exactly that — and the next developer can understand the test intent immediately. Hardcoded object literals scattered through UI tests are one of the biggest sources of maintenance pain in real automation suites.

11 Now You Try

🧪 Prompt Lab

You're setting up a Playwright test suite for an NZ insurance claim submission portal. Tests will cover: logging in, submitting a claim, checking claim status, and downloading a settlement letter. For each of the 5 patterns above, decide: (1) whether it applies to this scenario, (2) what it would look like, and (3) which pattern gives the biggest maintainability win here and why.

Why teams fail here

  • Starting without POM and planning to "refactor later" — by the time 200 tests exist, refactoring costs more than rewriting, and it never happens
  • Page objects that grow to absorb assertions, API calls, and database seeding — the pattern is adopted but the boundary discipline collapses within months
  • Introducing Screenplay on a 20-test suite with one actor type — the verbosity overhead is real and teams quietly revert to raw selectors when you're not watching
  • Builders that use US-style or fake data as defaults — NZ compliance (Privacy Act 2020, Revenue NZ formats, NZD amounts) must be baked into the defaults, not patched in per test

Key takeaway

Test automation patterns are not about elegance — they are the difference between a suite that costs 20 minutes to update after a UI change and one that costs three weeks.

How this has changed

The field moved. Here is how Test Automation Patterns evolved from its origins to current practice.

1990s

Test automation is largely ad hoc — scripts written by developers and testers without design principles. Fragility is endemic: UI changes break hundreds of tests. The first pattern to emerge as wisdom is "don't record-and-playback for regression tests" — recorded scripts are unmaintainable.

2001

Page Object Model (POM) described by Martin Fowler and the Selenium community. The first widely-adopted test automation pattern: encapsulate page interactions in classes so that UI changes require updating one place, not hundreds of tests. POM becomes the default architectural pattern for UI automation.

2008

Screenplay pattern proposed as an evolution beyond POM — modelling user goals and tasks rather than pages. Better for complex workflows but harder to learn. Data-driven testing and keyword-driven testing patterns emerge for non-programmer testers.

2013

ATDD and BDD drive feature-file patterns (Given/When/Then). Step definitions, shared context, and hooks become standard Cucumber/SpecFlow patterns. The separation of test intent (feature file) from implementation (step definitions) becomes a standard architectural concern.

Now

AI tools can generate test code from natural language descriptions of test scenarios — making the choice of pattern less about writing efficiency and more about maintainability and readability. AI can also suggest refactoring when pattern violations are detected. The best pattern is the one your team can maintain long-term.

12 Self-Check

Click each question to reveal the answer.

Interview Questions

What NZ hiring managers ask about Test Automation Patterns — and what strong answers look like.

What problem does the Page Object Model solve, and what are its limitations?

Strong answer: The Page Object Model (POM) encapsulates UI interactions in classes — a LoginPage class contains the username field locator, the password field locator, and a login() method. When the UI changes, you update one class, not 50 tests. This solves the maintenance problem of UI automation where a single element rename breaks hundreds of tests. Limitations: POM models pages, but modern single-page apps do not have discrete page boundaries. POM classes can grow large as pages grow complex. And POM does not address the deeper problem of what to test at the UI level — it only makes UI tests more maintainable without helping you decide when to write them.

Junior/Mid

When would you use the Screenplay pattern instead of Page Objects?

Strong answer: When tests model complex multi-step user journeys (rather than single-page interactions) and when readability and expressiveness matter as much as maintainability. Screenplay focuses on actors, goals, and tasks: "Jane wants to submit a benefit application → she navigates to the form, fills in her NHI, and submits." The test reads like a user story. The pattern also scales better to cross-browser and mobile testing because the same actor can perform the same task on any interface. The trade-off: Screenplay requires more conceptual learning than POM and has a steeper onboarding curve for new team members.

Mid/Senior

What is the test automation pyramid, and why does it matter for sustainability?

Strong answer: The pyramid describes the recommended proportion of tests at each level: many fast unit tests at the base, fewer integration tests in the middle, and a small number of slow end-to-end tests at the top. The principle: tests should be as low in the pyramid as possible while still testing the intended behaviour. E2E tests are slow, brittle, and expensive to maintain — if the same behaviour can be tested at the unit or integration level, it should be. Organisations with inverted pyramids (many E2E, few unit tests) have slow, flaky CI pipelines that become a delivery bottleneck rather than a quality gate.

Junior/Mid

Q1: A navigation redesign breaks 280 of 400 tests. What pattern would have prevented this, and how?

Page Object Model. All selectors for the navigation live in a NavComponent page object. When the navigation changes, you update one file — the NavComponent. All 280 tests that use it automatically inherit the fix because they call page object methods, not raw selectors. The tests describe intent; the page object describes implementation.

Q2: What is the key difference between POM and Screenplay pattern?

POM organises tests around pages — a LoginPage has methods for actions on that page. Screenplay organises tests around actors performing tasks — an Actor performs a LoginTask using an Interaction. Screenplay is more verbose but scales better for complex multi-actor scenarios (e.g. testing a workflow where a GP submits a referral and a specialist receives it). POM is the right default for most teams.

Q3: When should you write a Custom Matcher instead of an inline assertion?

When the same domain-specific validation appears in 3 or more tests. NZ Revenue NZ number format, NZ bank account format, or NZ date range validation are good candidates — they're domain rules that belong in one place. An inline assertion is fine once; a custom matcher is right when the same logic would otherwise be copied across multiple tests.

Q4: Your team is building a Playwright suite for the Benefits NZ MyMSD portal, covering benefit applications, document uploads, and appointment bookings across three different user roles (client, case worker, manager). Which pattern or combination of patterns would you choose and why?

A: POM for each page area (ApplicationPage, DocumentPage, AppointmentPage), Factory to provide role-scoped page objects per test, Builder for application test data (benefit type, income details, dependent information), and Screenplay for the multi-actor workflows where a client submits then a case worker reviews. This is exactly the scenario Screenplay was designed for — three distinct actors performing overlapping tasks on the same system. POM alone would result in unwieldy page objects trying to model actions across all three roles.

Q5: What is the key difference between the Builder pattern and a plain object factory function for test data?

A: A Builder uses a fluent interface — you chain method calls to configure only the fields relevant to the current test, with all other fields provided as sensible defaults. A factory function typically requires you to pass all fields explicitly or use a large options object. The practical difference shows in readability: new ClaimBuilder().withAccidentType('fall').inRegion('Otago').build() communicates intent instantly and ignores irrelevant fields, whereas a factory call like createClaim({ accidentType: 'fall', region: 'Otago', amount: null, date: null, ... }) forces every test to know about every field even when it doesn't care about them.

Q6: A developer on your team says "We don't need Page Object Model — Playwright already has built-in locators and auto-waiting, so the maintenance problem POM was solving is basically gone." What is wrong with this argument and how do you respond?

A: Playwright's smart locators reduce flakiness from timing, but they don't eliminate the maintenance problem POM solves. POM's value is centralisation — when a button's label changes from "Submit Claim" to "Lodge Claim" across 60 tests, you change one method in one page object rather than hunting through 60 test files. Playwright's locators still need to live somewhere; without POM they live inline in every test. The developer is confusing flakiness (which Playwright helps with) with selector duplication (which POM addresses). They're different problems.

Q7: Your team is testing an TransitNZ licensing portal and wants to apply the Screenplay pattern. The test suite currently has 15 tests, one actor type (the licence applicant), and straightforward page flows. Is this a good time to introduce Screenplay?

A: No — this is the wrong context for Screenplay. Screenplay pays off in large suites with complex multi-actor workflows (e.g., applicant submits, verifier approves, system sends notification). With 15 tests and one actor type, POM is faster to write, easier for all team members to read, and requires no onboarding overhead. Introducing Screenplay here adds structural complexity without a concrete problem to justify it. Revisit the decision if the suite grows past 100 tests or if a second actor type (e.g., an TransitNZ assessor role) is added to the workflows.

13 ISTQB Mapping

ISTQB CTAL-TAE (Test Automation Engineering) — Section 4.2 (Automation code design patterns), Section 5.2 (Test data management), Section 6.3 (Verification of automation code quality). TAE candidates are expected to select and apply appropriate design patterns based on the automation context.

POM is explicitly referenced in CTAL-TAE. Screenplay is an evolution of POM that TAE practitioners encounter in advanced teams.