<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MohammadMahdi Shahbazi</title>
    <description>The latest articles on DEV Community by MohammadMahdi Shahbazi (@byshahbazi).</description>
    <link>https://dev.to/byshahbazi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4218877%2Fb25af991-6a1f-4934-80a9-37c79ba9c16f.jpg</url>
      <title>DEV Community: MohammadMahdi Shahbazi</title>
      <link>https://dev.to/byshahbazi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/byshahbazi"/>
    <language>en</language>
    <item>
      <title>From Copy-Paste to a Specification-Driven Test Engine: Reusing Behavior in Large Web Systems</title>
      <dc:creator>MohammadMahdi Shahbazi</dc:creator>
      <pubDate>Sat, 31 Oct 2026 12:12:11 +0000</pubDate>
      <link>https://dev.to/byshahbazi/from-copy-paste-to-a-specification-driven-test-engine-reusing-behavior-in-large-web-systems-3iap</link>
      <guid>https://dev.to/byshahbazi/from-copy-paste-to-a-specification-driven-test-engine-reusing-behavior-in-large-web-systems-3iap</guid>
      <description>&lt;h2&gt;
  
  
  Abstract
&lt;/h2&gt;

&lt;p&gt;Large web applications often contain many pages that share the same interaction patterns: data grids, filtering, sorting, pagination, detail views, status changes, and file exports. When each page has its own automated test suite, teams repeatedly implement and maintain tests for behavior that is largely identical.&lt;/p&gt;

&lt;p&gt;This article presents a specification-driven test engine built with Playwright. Instead of defining a separate suite for every page, the team describes each page through a compact specification containing its capabilities, column metadata, and setup requirements. A plan builder converts that specification into a test plan, and reusable behavior suites register only the tests that apply to the page.&lt;/p&gt;

&lt;p&gt;In the project described here, this approach reduced the test count by approximately 80% and the overall test-layer code by approximately 79%. A small catalog of shared tests now generates more than a thousand page-specific scenarios. This article explains the architecture, execution model, results, trade-offs, and limitations of the approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keywords:&lt;/strong&gt; specification-driven testing; Playwright; reusable test behaviors; capability model; test maintainability; test automation&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;Many enterprise web applications are built around families of similar pages rather than entirely unique screens. One page may display a data grid, while another displays a different dataset using the same grid component. Their filters, sorting controls, pagination, detail views, and export actions often follow the same interaction patterns. The underlying data and business rules may differ, but much of the user-facing behavior remains consistent.&lt;/p&gt;

&lt;p&gt;This consistency is beneficial for product development, but it can create a problem in test automation.&lt;/p&gt;

&lt;p&gt;A team may first build a comprehensive test suite for Page A. When Page B is introduced, engineers copy the existing suite and change a few names, selectors, or data values. The same process is repeated for Page C and every page that follows. Over time, the test repository grows, but a significant portion of its code represents the same behavior implemented multiple times.&lt;/p&gt;

&lt;p&gt;This article describes an alternative: &lt;strong&gt;specify each page once and reuse the tests that verify its capabilities&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Each page is represented by a structured specification. A test engine interprets that specification, builds a test plan, and uses shared Playwright suites to verify the applicable behaviors. The test logic is implemented once; page-specific differences are expressed as metadata.&lt;/p&gt;

&lt;p&gt;The approach is intended for QA engineers and software engineers responsible for maintaining UI automation across large applications. It focuses on the architecture and design principles rather than on a specific product or business domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The Problem: Copy-Paste at Scale
&lt;/h2&gt;

&lt;p&gt;Consider an enterprise application containing many data-oriented pages. Depending on the page, its functionality may include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A data grid with typed columns&lt;/li&gt;
&lt;li&gt;Filtering and sorting&lt;/li&gt;
&lt;li&gt;Pagination&lt;/li&gt;
&lt;li&gt;A detail view for a selected row&lt;/li&gt;
&lt;li&gt;Status changes or workflow actions&lt;/li&gt;
&lt;li&gt;File export&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the project behind this article, each page originally had its own test suite. Over time, the test layer grew to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;64 test files&lt;/li&gt;
&lt;li&gt;More than 800 individual tests&lt;/li&gt;
&lt;li&gt;Over 31,000 lines of code across tests, page objects, and test data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first, this appeared to be a healthy level of coverage. Tests were passing, and the number of scenarios suggested that the application was being tested thoroughly.&lt;/p&gt;

&lt;p&gt;However, adding a new page required repeating much of the existing work: navigation setup, test-data preparation, column validation, and interaction scenarios. Even when page objects were reused, the test definitions and scenario wiring were often duplicated.&lt;/p&gt;

&lt;p&gt;This created three main problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Authoring cost
&lt;/h3&gt;

&lt;p&gt;Every new page required engineers to configure navigation, prepare test data, define column assertions, and reproduce existing interaction scenarios. Much of this work added no new test logic; it simply adapted existing logic to another page.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 Maintenance cost
&lt;/h3&gt;

&lt;p&gt;When a shared UI component changed, the same update often had to be applied across multiple suites. Over time, those suites drifted apart. One might validate an outdated set of columns, another might be missing an export test, and a third might contain a hard-coded exception that should have been represented as configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.3 Coverage inconsistency
&lt;/h3&gt;

&lt;p&gt;Copied suites do not necessarily remain equivalent. Small differences accumulate, and some pages gradually lose checks that exist elsewhere. The resulting gaps are not always caused by missing test ideas. Often, they are caused by the absence of a common model defining what every page in the same family must verify.&lt;/p&gt;

&lt;p&gt;One possible alternative is to create a single generic test that discovers page functionality at runtime. However, this can become brittle. Without an explicit model of each page, the test runner has to infer too much about the interface, which can lead to weak or unreliable assertions.&lt;/p&gt;

&lt;p&gt;The goal, therefore, is to find a middle ground: &lt;strong&gt;make page capabilities explicit while keeping recurring test behavior reusable&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The Core Idea
&lt;/h2&gt;

&lt;p&gt;The design is based on one principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A page specification declares what a page can do; reusable behaviors define how those capabilities are tested.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Three concepts form the foundation of the engine.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 Page specification
&lt;/h3&gt;

&lt;p&gt;A page specification is a structured description of a page. It contains information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Page identity&lt;/li&gt;
&lt;li&gt;Supported capabilities&lt;/li&gt;
&lt;li&gt;Column metadata&lt;/li&gt;
&lt;li&gt;Navigation and setup requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It describes the page; it does not contain a complete test scenario or a sequence of UI interactions.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Reusable behavior
&lt;/h3&gt;

&lt;p&gt;A behavior is a reusable test suite for a recurring concern, such as filtering, pagination, opening a detail view, or validating an exported file.&lt;/p&gt;

&lt;p&gt;Each behavior is implemented once and relies on shared UI components and steps. It does not need a separate implementation for every page.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 Test plan
&lt;/h3&gt;

&lt;p&gt;A test plan connects the page specification to the reusable behavior suites.&lt;/p&gt;

&lt;p&gt;The engine reads a specification, determines which behaviors apply, groups columns by type, and produces a plan for the shared suites. A suite registers a test only when the plan indicates that the corresponding capability is supported.&lt;/p&gt;

&lt;p&gt;For example, if Page A supports detail views and file exports but does not support status changes, the engine registers detail and export tests without registering status-related tests.&lt;/p&gt;

&lt;p&gt;This design goes beyond the reuse provided by page objects. Page objects reduce duplication in locators and UI interactions, but they do not determine which scenarios should exist for each page. Here, the specification and plan builder make that decision. Playwright remains responsible for executing and reporting the resulting tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Architecture
&lt;/h2&gt;

&lt;p&gt;The engine consists of six main components:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Page specifications:&lt;/strong&gt; Structured descriptions of individual pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Registry:&lt;/strong&gt; The central collection of registered page specifications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan builder:&lt;/strong&gt; Converts validated specifications into test plans.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared behavior suites:&lt;/strong&gt; Playwright test suites that execute the applicable checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared UI components and steps:&lt;/strong&gt; Reusable locators, actions, and scenario-level operations used by the behavior suites.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run selection and reporting:&lt;/strong&gt; Determines which pages participate in a run and reports the results through the standard test runner.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The same test plans can also support API tests for corresponding capabilities. This makes it possible to keep UI and API coverage aligned without maintaining two independent page registries.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 High-level execution architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Page specification
        |
        v
     Registry
        |
        v
 Readiness validation
        |
        v
   Plan builder
        |
        v
Shared behavior suites
        |
        +-----------------------+
        |                       |
        v                       v
Shared UI components      Seed and teardown
        |                       |
        +-----------+-----------+
                    |
                    v
       Playwright runner and reporters
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The registry is the single source of registered page definitions. Before a specification can produce a test plan, it must pass readiness validation. Incomplete specifications are excluded from execution.&lt;/p&gt;

&lt;p&gt;A specification that declares a capability without providing the setup required by that capability should fail validation early. This is deliberate: configuration errors should be detected before browser execution, rather than appearing later as confusing assertion failures.&lt;/p&gt;

&lt;p&gt;Shared behavior suites do not maintain their own lists of pages. Instead, they consume the generated plans and register tests based on the actions and column groups defined in each plan.&lt;/p&gt;

&lt;p&gt;Shared UI components keep selectors and common interactions out of the behavior suites. Seed and teardown services are configured through the page specification, allowing tests to validate controlled test data rather than relying on unrelated or leftover records.&lt;/p&gt;

&lt;p&gt;Reporting remains part of the standard Playwright workflow. The engine does not introduce a separate verdict or reporting system. It registers ordinary Playwright tests and adds structured labels or tags that can be used for filtering and reporting in CI.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. The Page Specification Model
&lt;/h2&gt;

&lt;p&gt;A page specification answers four main questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1 What is this page?
&lt;/h3&gt;

&lt;p&gt;Identity fields provide a stable key and a human-readable display name. The key is used internally to identify the page, while the display name makes test reports easier to understand.&lt;/p&gt;

&lt;p&gt;For example, Page A may be registered using a stable identifier while appearing in reports under a descriptive page name.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.2 What can this page do?
&lt;/h3&gt;

&lt;p&gt;Capability flags describe the optional behaviors supported by the page. In this implementation, they include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether a detail view is available&lt;/li&gt;
&lt;li&gt;Whether a tracked field can be edited&lt;/li&gt;
&lt;li&gt;Whether status transitions are supported&lt;/li&gt;
&lt;li&gt;Whether bulk selection and group actions are available&lt;/li&gt;
&lt;li&gt;Whether file export is enabled&lt;/li&gt;
&lt;li&gt;Whether soft-deleted records or older record versions must remain hidden&lt;/li&gt;
&lt;li&gt;Whether additional rules apply to editing or filtering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These flags control which test scenarios are registered. They are not merely documentation or descriptive comments; they act as configuration contracts used by both the plan builder and the shared suites.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.3 What does the grid look like?
&lt;/h3&gt;

&lt;p&gt;Column metadata describes the grid structure, including column headers, identifiers, and value types such as strings, numbers, and dates.&lt;/p&gt;

&lt;p&gt;The value type determines which filtering operators and sorting checks are applicable. The metadata also defines how seeded sample fields map to the values used in filter tests.&lt;/p&gt;

&lt;p&gt;Some columns, such as row-index columns, may be included in grid-structure validation but excluded from filtering and sorting plans.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.4 How do we navigate to and prepare this page?
&lt;/h3&gt;

&lt;p&gt;Setup metadata connects the abstract page definition to the test environment. It describes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where the test should navigate&lt;/li&gt;
&lt;li&gt;How the page-specific data service should be created&lt;/li&gt;
&lt;li&gt;Which reference column is used to open detail views or anchor filters&lt;/li&gt;
&lt;li&gt;Which optional builders provide detail snapshots or export mappings&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A page is considered &lt;strong&gt;ready&lt;/strong&gt; only when its required setup is present and every field required by its enabled capabilities is configured.&lt;/p&gt;

&lt;p&gt;For example, enabling the detail-view capability without providing the required detail configuration should make the specification invalid. The same principle applies to other capabilities with additional setup requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.5 How the specification affects test execution
&lt;/h3&gt;

&lt;p&gt;The specification influences execution in two distinct ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Test selection:&lt;/strong&gt; It determines which test groups and individual cases are registered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test parameterization:&lt;/strong&gt; It provides the data needed to configure those tests, such as filterable columns, column types, reference values, detail snapshots, and export mappings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result, the behavior suites remain generic while the specification provides the page-specific information they need.&lt;/p&gt;

&lt;p&gt;Requirement documents written for analysts are not parsed directly at runtime. Engineers translate the agreed requirements into the page specification. This keeps test execution explicit and deterministic, but it also introduces a manual synchronization step whenever requirements change.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Behavior Catalog
&lt;/h2&gt;

&lt;p&gt;The behavior catalog contains the recurring checks that pages in this family are expected to satisfy. Each behavior is implemented once and is either registered when applicable or intentionally omitted when the page does not support it.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.1 Grid structure
&lt;/h3&gt;

&lt;p&gt;The suite compares the visible column headers with the column metadata in the page specification.&lt;/p&gt;

&lt;p&gt;This detects missing columns, renamed headers, and differences between the expected page structure and the actual UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.2 Typed filtering and sorting
&lt;/h3&gt;

&lt;p&gt;Columns are grouped by their declared data types. For each eligible column, the suite:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Seeds records with known values.&lt;/li&gt;
&lt;li&gt;Applies the filtering operators supported by that column type.&lt;/li&gt;
&lt;li&gt;Verifies that non-matching records are excluded.&lt;/li&gt;
&lt;li&gt;Checks sorting in ascending and descending order where applicable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A single set of matrix definitions can therefore cover all registered pages without duplicating the same filter and sort scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.3 Pagination
&lt;/h3&gt;

&lt;p&gt;The suite creates enough records to cross page boundaries, checks the available page-size options, and navigates between pages.&lt;/p&gt;

&lt;p&gt;Pagination is generally part of the common page behavior, so it depends primarily on the page's setup and data-seeding configuration rather than on optional capability flags.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.4 Detail view
&lt;/h3&gt;

&lt;p&gt;When a page declares support for a detail view, the suite opens a record using its configured reference cell and validates the resulting structure against the snapshot provided by the specification.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.5 Editing and status workflows
&lt;/h3&gt;

&lt;p&gt;When a page supports editable fields or status actions, the corresponding shared suites cover the main workflow and selected error paths.&lt;/p&gt;

&lt;p&gt;Bulk-action tests are registered only when the plan includes both bulk selection and group actions. Additional cases, such as restricted choice lists or rule-based editing limits, are registered only when the relevant flags are enabled.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.6 File export
&lt;/h3&gt;

&lt;p&gt;When export is enabled, the suite triggers the export operation and compares the generated file with the expected mapping defined for the page.&lt;/p&gt;

&lt;p&gt;Related checks may also cover file cleanup and request limits.&lt;/p&gt;

&lt;h3&gt;
  
  
  6.7 Visibility rules
&lt;/h3&gt;

&lt;p&gt;When soft deletion or record versioning is enabled, the suite verifies the corresponding visibility rules. For example, deleted records should remain hidden, and only the latest version of a record should be visible.&lt;/p&gt;

&lt;p&gt;The catalog is not intended to cover every possible product scenario. It defines the recurring contract for one family of similar pages. Product-specific workflows that cannot be generalized should remain in dedicated test suites outside the engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Execution Flow
&lt;/h2&gt;

&lt;p&gt;The execution process follows a deliberate sequence. Most decisions are made before the browser interacts with the application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Load:&lt;/strong&gt; The registry collects the page specifications. Specifications that satisfy the readiness requirements are validated and converted into runnable configurations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build the plan:&lt;/strong&gt; For each selected page, the plan builder derives the applicable actions from the capability flags and groups columns by type.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Register tests:&lt;/strong&gt; Shared suite files consume the plans and create a test group for each page. Individual cases are registered only when the corresponding behavior is allowed by the plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arrange test data:&lt;/strong&gt; Each test obtains the page-specific data service, generates the required sample records, and inserts them. Navigation uses the target defined in the specification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Act and assert:&lt;/strong&gt; Shared steps and UI components perform the interactions. Assertions compare the resulting UI state with the seeded data or with specification-driven snapshots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean up and report:&lt;/strong&gt; Fixture teardown removes the records created for the test. Playwright records the result, while reporters attach labels and tags that support filtering in CI.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most important characteristic of this process is that &lt;strong&gt;the engine decides which scenarios exist before any browser interaction takes place&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It does not explore a page at runtime and guess which controls or actions might be available. If a specification does not declare export support, the export test is not registered in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Extensibility
&lt;/h2&gt;

&lt;p&gt;The engine is designed to accommodate new pages and new recurring behaviors without recreating the original duplication problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.1 Adding a new page
&lt;/h3&gt;

&lt;p&gt;For a page that belongs to the existing page family, the process is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Agree on the page's capabilities and columns.&lt;/li&gt;
&lt;li&gt;Provide the required test-data seeding support.&lt;/li&gt;
&lt;li&gt;Create a specification containing the page's flags, column metadata, and setup configuration.&lt;/li&gt;
&lt;li&gt;Register the specification.&lt;/li&gt;
&lt;li&gt;Include the page in the run selection used by local execution and CI.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once these steps are complete, the existing shared suites can pick up the page automatically.&lt;/p&gt;

&lt;p&gt;Creating a new suite by copying an existing page's tests and changing a few constants should be avoided. That would reintroduce the duplication the engine is intended to eliminate.&lt;/p&gt;

&lt;p&gt;A simple page may support only grid structure, filtering, sorting, and pagination. A more complex page may also support details, editing, status workflows, and export. Both can use the same shared suites; their specifications determine which tests are registered.&lt;/p&gt;

&lt;h3&gt;
  
  
  8.2 Adding a new behavior
&lt;/h3&gt;

&lt;p&gt;A new recurring concern should be added to the behavior catalog deliberately:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Determine whether it is an always-on check, a primary capability, or an optional edge case.&lt;/li&gt;
&lt;li&gt;Extend the specification with the required flag or metadata.&lt;/li&gt;
&lt;li&gt;Update the plan builder so that the new information is represented in the generated plan.&lt;/li&gt;
&lt;li&gt;Reuse existing shared steps and UI components where appropriate.&lt;/li&gt;
&lt;li&gt;Gate the new test cases in the shared suite using the plan, rather than maintaining a hard-coded list of pages.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The following pseudocode illustrates the relationship between a specification, a test plan, and the behavior catalog:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spec = loadSpecification(pageKey)
requireReady(spec)

plan = {
    actions: deriveActions(spec.flags),
    columns: groupByType(spec.columns)
}

for each behavior in catalog:
    if behavior.isNeededBy(plan):
        registerCases(behavior, plan)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model discourages one-off conditions inside shared suites for individual pages. When a difference is reusable and meaningful, it should be represented by a capability flag or metadata. When it is unique to one page and does not belong to the common contract, it should remain in a dedicated test suite.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Results
&lt;/h2&gt;

&lt;p&gt;The approach was evaluated through a refactoring of one large project.&lt;/p&gt;

&lt;p&gt;Before the refactoring, the test layer contained 64 test files, more than 800 tests, and over 31,000 lines of code across tests, page objects, and test data.&lt;/p&gt;

&lt;p&gt;The reported changes were:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Measure&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Number of tests&lt;/td&gt;
&lt;td&gt;Approximately 80% reduction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lines of test-layer code&lt;/td&gt;
&lt;td&gt;Approximately 79% reduction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lines of page object code&lt;/td&gt;
&lt;td&gt;Approximately 70% reduction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Effort to add tests for one new page&lt;/td&gt;
&lt;td&gt;Reduced from approximately 18 hours to approximately 4 hours (team estimate)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The time estimates are based on the team's own assessment, not on a controlled experiment. The other figures come from a before-and-after comparison of the same project.&lt;/p&gt;

&lt;p&gt;Another important outcome is the change in how test logic is maintained. Approximately 25 shared test definitions now generate more than a thousand page-specific scenarios across the registered pages. When a new page joins the system, the team no longer needs to build a complete suite from scratch; it provides a specification that the existing engine can use.&lt;/p&gt;

&lt;p&gt;This also changes how coverage should be interpreted. A lower test count does not necessarily indicate lower coverage. In this project, removing duplicated tests did not reduce the behaviors being verified. Instead, it improved the relationship between coverage and implementation complexity.&lt;/p&gt;

&lt;p&gt;The more useful question is not always, "How many tests do we have?" It is also, "How many times have we implemented the same behavior?"&lt;/p&gt;

&lt;p&gt;These results come from a single project, so they should not be treated as universal benchmarks. Teams with fewer similar pages, or with pages that share less functionality, should expect smaller gains.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Benefits and Trade-offs
&lt;/h2&gt;

&lt;p&gt;The approach provides several benefits, but it also introduces design and maintenance responsibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.1 Benefits
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Lower maintenance effort.&lt;/strong&gt; A fix to a shared filtering step or pagination component benefits every registered page that uses it. The team maintains a behavior once instead of maintaining multiple copies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;More consistent coverage.&lt;/strong&gt; Capability flags make test selection explicit. If export is enabled, the corresponding export cases are registered. If it is disabled, their absence is intentional. This is more reliable than depending on every copied suite to maintain the same checklist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Faster onboarding for similar pages.&lt;/strong&gt; Once engineers understand the specification model, adding another page mainly involves defining its metadata and setup rather than designing and implementing another set of repeated scenarios.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better alignment between UI and API tests.&lt;/strong&gt; When both layers use the same plans, it becomes easier to identify differences between the capabilities verified through the browser and those verified through HTTP requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  10.2 Trade-offs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Upfront modeling effort.&lt;/strong&gt; The initial implementation requires careful design of capability flags, readiness rules, column metadata, and shared components. The first page may take more effort than a conventional standalone suite. The benefits become clearer as more similar pages are added.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Risk of over-abstraction.&lt;/strong&gt; Not every page belongs in the same family. Forcing a unique workflow into a collection of flags can make the specification and plan builder unnecessarily complex. The engine needs clear criteria for deciding which pages belong in the model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Larger impact of shared failures.&lt;/strong&gt; An unstable locator or incorrect assertion in a shared component can affect many pages at once. This increases the potential impact of defects in shared code and makes clear ownership and prompt fixes especially important.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Specification drift.&lt;/strong&gt; Requirements are not executed directly, so the coded specification can become inconsistent with the product. Updating the specification must therefore be part of the definition of done whenever a relevant feature changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Limitations and Future Work
&lt;/h2&gt;

&lt;p&gt;The design has several limitations that define where it is appropriate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It targets a specific page family.&lt;/strong&gt; The engine is suitable for similar, grid-based pages. It is not intended to automate arbitrary interfaces. Pages with unique workflows should remain ordinary Playwright suites.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Specifications are maintained manually.&lt;/strong&gt; Requirement documents do not directly drive test execution. This keeps the model explicit and under the team's control, but it creates a manual synchronization step between requirements and automation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Incomplete registrations are not executed.&lt;/strong&gt; A page that does not satisfy readiness validation is excluded from the shared suites. This prevents partially configured tests from running, but it can make unfinished registrations less visible unless readiness is tracked separately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Documentation can become outdated.&lt;/strong&gt; Specifications, implementation, documentation, and run configuration can gradually disagree. Keeping them aligned requires an explicit maintenance process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Domain-specific rules still require explicit modeling.&lt;/strong&gt; The engine does not discover business rules automatically. Special editing constraints, filtering limits, and workflow conditions still need corresponding metadata and test cases. The engine provides a consistent way to organize and execute them.&lt;/p&gt;

&lt;p&gt;Possible future improvements include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A readiness report showing registered pages that are not yet complete&lt;/li&gt;
&lt;li&gt;Generating column metadata from a single authoritative source to reduce manual synchronization&lt;/li&gt;
&lt;li&gt;Stronger contract checks between UI plans and API capabilities&lt;/li&gt;
&lt;li&gt;Clearer criteria for deciding when a page should be handled by the engine and when it should have a standalone suite&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These improvements do not change the central design. They strengthen the separation between page specifications, which declare capabilities, and reusable behaviors, which verify them.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Conclusion
&lt;/h2&gt;

&lt;p&gt;When many pages share grids, filters, pagination, detail views, status workflows, and exports, copying test suites may seem like the fastest way to expand coverage. Over time, however, it creates duplicated logic, inconsistent checks, and a growing maintenance burden.&lt;/p&gt;

&lt;p&gt;A specification-driven test engine changes the unit of reuse. Each page provides a specification, the engine converts that specification into a test plan, and shared behavior suites register only the checks that apply. Playwright remains responsible for test execution and reporting; the main change is the explicit decision model that determines which tests should exist.&lt;/p&gt;

&lt;p&gt;This approach requires careful capability modeling, clear ownership of shared components, and discipline about which pages belong to the same family. It is not a universal replacement for ordinary test suites. Its value comes from applying it to the right set of pages.&lt;/p&gt;

&lt;p&gt;For teams facing repeated test behavior across similar pages, a practical starting point is small: define a few meaningful capabilities, register one fully configured page, and implement one shared behavior suite. The model can then grow as more pages demonstrate that the same behavior is genuinely reusable.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>testing</category>
      <category>automation</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
