Skip to content
Jose Constela
Go back

Introducing lab34-flows: Declarative E2E Testing with YAML

Testing complex multi-step processes has always been a pain point in software development. Think about a typical user registration flow, an e-commerce checkout, or an IoT device responding to commands. Each process involves multiple services - APIs, database transactions, async protocols, slow network connections. Each step depends on the previous one. Any of them could fail.

I’ve spent years dealing with this challenge, writing integration tests that inevitably become fragile, hard to understand, and leave little room for fuzzing. The worst part? They often don’t even pass in local environments.

So I built something better.

What is lab34-flows?

lab34-flows is an orchestration tool that executes multi-step workflows defined in YAML. Instead of writing code to glue services together, you describe the sequence of operations in a human-readable format.

Here’s what a test case looks like:

title: Verify product stock
description: Creates a product and validates initial stock is zero

steps:
  - application: product_catalog
    method: api_create_product
    parameters:
      body:
        name: R/C Car

  - application: product_catalog
    method: database_search_ean
    test:
      body:
        stock_amount: 0
      retry:
        delay: 5000
        times: 10

No code. Just a clear description of what applications are involved and what actions to perform. The tool reads this file and executes the steps in order, handling state and data flow between them.

The Architecture

The system has three main components:

The Tool (lab34-flows): The CLI engine that reads and executes YAML workflow files. It parses steps, calls the appropriate application methods, manages data flow, and runs defined tests.

The Organization Context: A shared folder or repository where developers define integrations. This acts as a bridge between simple YAML files and your actual services. For example, the stripe_gateway application and its tokenize_card method are defined here. This means QA, DevOps, or product managers can write and review test scenarios in plain YAML without knowing the underlying implementation details.

Credentials (.env files): Standard .env files for environment-specific configs like URLs, database credentials, and API keys. By swapping the .env file, you can run the exact same workflow against a local mock, staging, or even production.

Built-in Testing Features

Beyond simple execution, lab34-flows is a powerful testing tool. You can define assertions directly within a step using the test key:

A Real-World Example: Payment Processing

Here’s how you’d test an entire e-commerce payment flow:

title: Process New Customer Payment
description: Tests the entire payment process from user registration to transaction reporting.

steps:
  - application: user_service
    method: signup
    description: Create user record if not exists
    parameters:
      body:
        userEmail: "customer@example.com"
        name: "Jane Doe"
    test:
      status: [201]

  - application: stripe_gateway
    method: tokenize_card
    description: Securely obtain a token for card details
    parameters:
      body:
        cardNumber: "4242..."

  - application: payment_db
    method: create_record
    description: Create internal DB records for the transaction
    parameters:
      body:
        amount: 1000
        currency: "USD"

  - application: reporting_service
    method: trigger_report_generation
    description: Kick off an async report generation job

  - application: reporting_service
    method: get_report_by_transaction
    description: Verify the report has been generated successfully
    test:
      body:
        status: "COMPLETED"
      retry:
        times: 10
        delay: 5000

If user_service returns anything other than 201, the flow stops immediately. It also gracefully handles the reporting service delay by polling until the job completes.

Local Development Without External Dependencies

One of the biggest challenges with complex systems is dealing with external dependencies. How do you run an E2E test of your payment flow without making real API calls to Stripe?

Because each application is a modular component defined in the Context, you can configure the flow runner to substitute a real service with a local mock. In a local or CI environment, you can set up lab34-flows so the stripe_gateway application points to a mock server you control.

This means you can test scenarios where credit card “4242-4242-4242-4242” is expected to work, but “1111-1111-1111-1111” is expected to fail. All from your localhost.

Key Features

Get Started

The project is open source and available on GitHub:

I built this to solve my own testing and orchestration challenges, and I believe it can help others build more reliable and maintainable applications. Dive into the docs, explore the examples, and let me know what you think. Contributions, feedback, and ideas are welcome!


This post is based on the original article published on Lab34’s blog.


Share this post on:

Previous Post
Ronsel: Tests You Read, Docs You Run
Next Post
Introducing ReArch: Self-Hosted AI Coding Agents for Your Whole Team