Case study / Believe · 2023–2025

QaaS

A shared platform that lets teams write tests around business behaviour, then prepare and run them through a guided engineering workflow.

Platform architecturepytest · Cypress · k6Developer experience

The problem

Each test could bring its own setup: API access, authentication, data, selectors, waits, dependencies and reporting. Teams spent time rebuilding the conditions for a test before expressing what it should verify.

The cost appeared in onboarding, duplicated code, maintenance and differences between local execution and CI.

My contribution

Architecture and development of the shared test libraries and execution tooling, alongside integration and adaptation of CI components. I worked on the interfaces exposed to test authors, reusable technical services, container environments, launch and reporting interfaces, and the documentation supporting adoption.

I designed and developed the shared test foundation and integrations for QaaS, working with engineers from the contributing teams.

01 / WRITE

Keep business intent visible.

Test authors assemble capabilities already prepared in the platform. The shared layer carries the details that would otherwise be copied into every scenario.

API tests · pytest

Fixtures prepare clients and test data. Shared assertions check responses and business objects. Public imports expose these capabilities without requiring authors to navigate the internal package structure.

Web tests · Cypress

Business commands combine recurring steps such as session setup and release workflows. Selectors, waits and technical status codes can be maintained behind those commands.

Performance · k6

Scenario factories assemble reusable operations, load settings, checks and metrics. Shared HTTP and instrumentation layers keep request handling and measurement consistent.

Metadata, decorators, registries and pytest plugins support how scenarios are declared, selected and executed. A change to a shared operation can then be maintained in one place and distributed through the platform.

02 / AN EXAMPLE

Move the plumbing into the platform.

Illustrative API scenario: create an asset and check its upload state. Shared clients, data fixtures and assertions carry the recurring preparation.

Repeated inside each test

def test_asset_upload():
    settings = load_settings()
    token = authenticate(settings)
    client = build_client(settings, token)
    payload = build_asset_data()
    created = client.create_asset(payload)
    assert created.status == 201
    asset_id = created.body["id"]
    client.mark_uploaded(asset_id)
    current = client.get_asset(asset_id)
    assert current.body["upload_state"] == "ready"

Composed from shared capabilities

def test_asset_upload(asset_client, asset_data):
    created = asset_client.create(asset_data)
    assert_asset_created(created)
    asset_client.mark_uploaded(created.id)
    current = asset_client.get(created.id)
    assert_upload_state(current, "ready")

The client fixture supplies configured access; data preparation and assertions have their own shared implementation. The author can read the business sequence while maintainers retain access to the underlying mechanisms.

03 / PREPARE & RUN

A prepared environment around every engine.

Versioned runtimes

Docker images carry the engine and its software dependencies. Compose profiles support development, debugging, collection and shell access; Cypress also has a graphical route through noVNC.

Execution tooling

Launchers prepare configuration, containers, mounts and result locations. Docker diagnostics, dependency caches and user/permission handling address recurring setup problems.

Delivery & results

CI builds and publishes images, runs configured checks and publishes documentation. A k6 launcher generates Kubernetes Jobs and provides status, logs and cleanup operations.

Platform profiles support macOS, Linux and Windows through WSL2. Containers provide Python, Node and browser dependencies; host preparation takes into account networking, permissions, resources and CPU architecture.

Follow the launch and reporting workflow →

04 / USER INTERFACES

Guide the run.
Make the result readable.

QaaS also provides the layer people use to launch and understand a test. Entry points translate a context and test selection into engine parameters, container configuration and result locations.

pytest output

Structured logging, readable API responses and per-test status and duration. Summary components bring together passed, failed and skipped tests with access to the report.

Cypress consoles

A dedicated terminal formatter organises time, type, context and message, separates execution phases and provides quiet, normal, verbose and debug levels. Screenshots and videos support investigation.

API exploration

The VS Code API Tester brings Swagger endpoint selection, request fields and history into the development workspace.

A platform entry point such as make cys-cli-showcase int smoke selects scenarios by metadata and delegates the launch configuration. Authors can focus on the scenario and its outcome.

05 / SHARED ACCESS

Prepare service access once.

From API contract to Python client

The generator retrieves OpenAPI contracts from Backstage, the internal service catalogue, then produces Python clients. Teams can reuse typed request and response models instead of rebuilding each integration by hand.

Generated clients provide typed service access. Scenario authors combine that access with business data and assertions.

Configuration & authentication

A client factory assembles the appropriate generated client with configuration and authentication. Shared Vault and OIDC integrations support reusable access patterns across services and teams.

Development environments include a local Vault instance. Shared adapters keep access configuration out of the business scenario.

06 / RESULTS

A shorter path to useful tests.

13 → 2

A Cypress design example

A release-search and export interface condensed into two Cypress calls: a login and a business command.

Explore the interface example →

Shared preparation keeps scenarios readable and makes recurring behaviour easier to maintain. Figure context →

07 / PLATFORM DIRECTION

One intention, several kinds of verification.

Foundations already present

Modular libraries, shared services, guided launch commands, container environments, metadata, custom output and a local documentation assistant provide the platform foundation.

Next platform step

A common request format and scenario catalogue could let users choose a business verification, target and profile, then follow its result across front-end, API and performance testing.

Engine adapters would translate this common contract into the execution and checks required by each tool.