How to Architect Maintainable Journey Tests

Ensure your users’ workflows are always functional

Alexa De La Garza
Slalom Build
5 min readMay 17, 2024

--

Introduction

As complex applications grow, managing and maintaining journey tests can become a significant challenge for testers. Issues like test fragility, scalability limitations, and lack of maintainability can hinder the effectiveness of testing efforts.

In most UI test frameworks, a multi-layered architecture is used to create a scalable and maintainable codebase. At the highest level of these layers, testers typically capture business-level workflows into journey tests. These tests protect the most important part of the system being developed: the business proposition of the application.

However, these tests become brittle and start to fail the moment that business workflows are changed. Maintaining and repairing these tests can be time-consuming and expensive for testers.

To improve the stability of these tests, we introduced a new layer of abstraction that enabled us to write journey tests faster and capture business practices into maintainable functions.

Current Multi-Layer Architecture

Figure 1: Current Multi-Layer Architecture

Figure 1 denotes a typical Playwright architecture consisting of the following:

  • Playwright Config: Parameters such as browser options, timeout thresholds, global setup and tear down, and reporter options
  • Utils: Our reusable artifacts
  • User Sessions: User tokens for authentication of the front-end
  • Data Mocks: Synthetically created data used to drive testing
  • Page Objects: Encapsulated selectors used by Playwright to interact with UI Elements
  • Specs: Our implementation-level tests
  • Journey Test: Our business-level tests

The Problem

While we architect most tests to allow for flexibility of code changes, we often fail to consider the potential disruption that changing business workflows will have on our test suites.

When workflows change and the system becomes more complex, testers tend to:

  • Spend time repairing broken journey tests.
  • Duplicate code via the recapture of partial workflows for new tests.
  • Become maintainers of tests and not writers of them.

For example, if a user would normally find data within the tested application on form A, but due to valid business needs, we move the data to form B, our tests will no longer function as expected.

The Solution

To combat code duplication and the writing of brittle tests, we introduced a new layer of abstraction that enabled us to write journey tests faster and capture business practices into maintainable functions. We called this layer Macros.

Figure 2: Multi-Layer Architecture with Macro Layer

This layer introduced a higher-order level of testing by prioritizing the actual business workflows. The Macro layer encapsulates business processes into reusable functions. With Macros, we no longer need to repeatedly define the same sequence of actions across multiple journey tests. Instead, we can invoke the relevant Macro when needed.

If a particular business process changes, we only need to update the corresponding Macro, and all tests relying on it automatically reflect the change. This approach streamlines the testing process and minimizes the risk of overlooking critical business requirements during updates or feature additions.

How To

Macro Overview

In the following code snippet, we showcase an example of one of the macros we’ve developed for the account creation process that users must follow within our application. To navigate successfully through the account creation flow, users must complete several steps. First, they fill out the first page, which requests essential details such as their first name, last name, email address, and other necessary information, including credentials like email and password, which are later used for account creation. After filling out these essential details on the first page, users are prompted to provide their contact information on the second page. Finally, the third page prompts users to finish filling out demographic and supplementary details.

Advantages of Macros

  1. Improves test stability: Macros contribute to test stability by encapsulating frequently used actions within functions. The personalInformationPage,contactInformationPage, and supplementalInfromationPage functions handle the process of filling out the different pages of the account creation flow. By bringing together this logic, we ensure consistent behavior across tests, lowering the chance of instability due to inconsistent test environments or UI changes.
  2. Accelerates test development: Using macros can speed up test development. For example, with the personalInformationPage,contactInformationPage, and supplementalInfromationPage functions, developers can easily create new tests for the account creation process by simply invoking these functions with the appropriate parameters. This approach simplifies test creation, allowing teams to iterate more quickly and maintain an effective testing setup.
  3. Mitigates code duplication and fragility: Macros prevent code duplication and the creation of fragile tests by simplifying the account creation process into three different functions. This decreases redundant code across tests and establishes a central hub for common test actions, improving code maintainability and reducing the risk of test failures caused by minor UI changes.
  4. Ensures comprehensive test coverage: Using macros streamlines the testing process, reducing the likelihood of overlooking critical business requirements during updates or feature additions. Macros promote the reusability and standardization of test actions, simplifying the creation of comprehensive journey tests. All three functions ensure that all fields are filled out, thereby verifying the core functionalities of the account creation flow.

Journey Test

The following Playwright test showcases our journey test created for the entire account creation process, leveraging the macros developed in the previous section. This test ensures the functionality of the account creation form, navigating through multiple pages and filling out essential details. By using macros, the test maintains clarity and simplicity, making it easy to understand and maintain.

Conclusion

The adoption of Macros improves our testing approach, emphasizing the business logic that drives our application. By abstracting technical complexities and focusing on the core workflows that matter most to our users, we improve the efficiency of our testing process and enhance the overall quality and reliability of our applications.

--

--