When I started working on distributed systems, one of the most painful parts was always end-to-end testing. You have services in different languages, they talk through REST, Kafka, databases, and webhooks, and you need to verify that a full business flow actually works. Most tools either force you to write everything in code or become very flaky in CI.
That’s why I built VouchFx — a declarative end-to-end testing platform that lets you describe tests in simple YAML, while still running them against real containers with proper orchestration.
How VouchFx works
The idea is quite simple but powerful. You write a test in .e2e.yaml. VouchFx validates it, compiles it to real C# code (only once), and then executes it against containers that are started and managed properly.
Here’s the flow:
This approach gives you several advantages:
- Tests are written in readable YAML
- You get the full power of C# when you need it (via
script.csharp) - Real containers are used (not mocks)
- The tool works with any language on the service side
- Memory is handled safely and CI exit codes are meaningful
A simple example
Here’s what a basic test can look like:
metadata:
name: simple-order-flow
tags: [smoke]
environment:
services:
api:
image: mycompany/orders-api:latest
db:
image: postgres:16
steps:
- id: create-order
type: http.rest
method: POST
url: http://{api}/orders
body: { "customerId": 42, "amount": 99.5 }
capture:
orderId: $.id
- id: verify-in-db
type: db-assert.postgres
connection: { service: db }
query: SELECT status FROM orders WHERE id = {orderId}
expected: { status: "CREATED" }
You describe what should happen. VouchFx takes care of starting the containers, waiting for them to be healthy, running the steps with retries, and collecting clear results.
When YAML is not enough
Most of the time, writing tests in declarative YAML is enough and actually very pleasant. However, sometimes a test scenario becomes really complex — for example when you need custom logic, loops, or advanced calculations.
In those cases you can use C# scripts directly. VouchFx supports the script.csharp step type, where you can write C# code inline or even load external .csx files. This gives you the full power of the C# language when you need it, while the framework still handles container orchestration, resilience, variable capturing, and reporting.
So you don’t have to choose between simple YAML and full code — you can mix both approaches in the same test suite.
Why I built it this way
I wanted something that feels natural to write, but still reliable when it runs in CI. Many testing tools either become too complex or produce flaky results because they don’t handle infrastructure properly.
With VouchFx you get:
- Clear separation between Pass, Fail, Environment Error, and Inconclusive
- Proper exit codes so your pipeline only breaks on real test failures
- Good reporting (terminal, HTML, JUnit)
- VSCode support with autocomplete and Test Explorer integration
It also works well in polyglot environments. Your services can be in Java, Python, Node.js, Go — VouchFx doesn’t care. It only cares about the seams between them.
Honest comparison with other tools
Here’s a comparison with some popular tools in this space. I tried to be honest about the strengths and weaknesses:
| Feature | VouchFx | NBomber | Testcontainers + xUnit | Aspire.Hosting.Testing | Reqnroll (SpecFlow) | Karate |
|---|---|---|---|---|---|---|
| Main style | Declarative YAML | C# code | C# code | C# code | Gherkin + C# | Declarative (DSL) |
| Polyglot support (any service language) | Strong | Limited | Limited | .NET only | .NET only | Good |
| Real container orchestration | Built-in (Aspire + Testcontainers) | Manual | Good | Good | Manual | Manual |
| CI integration | Ready-to-use templates (GitHub + GitLab) | You build it yourself | You build it yourself | You build it yourself | You build it yourself | You build it yourself |
| Exit code handling | Clear (Fail / Env Error / Inconclusive) | Basic | Basic | Basic | Basic | Basic |
| Memory safety & performance | Verified (collectible ALC) | Good | Depends on your code | Depends on your code | Good | JVM-based |
| Extensibility | Provider SDK + Community hub | Plugins | Write your own | Limited | Step definitions | Custom steps (Java/Kotlin) |
| Best for | Polyglot distributed systems | Load & performance testing | .NET teams using containers | .NET Aspire projects | BDD-style .NET teams | Teams comfortable with JVM |
Quick summary of VouchFx advantages:
- Strong focus on polyglot systems (your services don’t need to be .NET)
- Much better CI reliability thanks to proper exit codes and ready templates
- Declarative YAML makes tests easier to read and maintain for complex flows
- Built-in support for both simple YAML and powerful C# scripts when needed
Other tools can be better if you are doing heavy load testing (NBomber), pure BDD (Reqnroll), or if you are already deep in the Java ecosystem (Karate).
Getting started
Installation is simple:
dotnet tool install --global vouchfx --prerelease
Then you can run:
vouchfx run
There are also ready-to-use GitHub Actions and GitLab CI templates if you don’t want to set everything up yourself.
You can find the full documentation and examples here:
https://tomas-rampas.github.io/vouchfx/
Would love your feedback
VouchFx is still relatively new. I’ve been using it on my own projects and I think it solves some real pain points, but I would really like to hear from other people who do integration and end-to-end testing regularly.
If you work with distributed systems and have 30–60 minutes, I would appreciate it if you could try it on one of your flows (or just look at the samples) and tell me what you think — what feels good, what’s confusing, or what’s missing.
No pressure at all. Honest feedback is very valuable at this stage.
Source: https://tomas-rampas.github.io/vouchfx/
Samples: https://tomas-rampas.github.io/vouchfx-samples/
Thanks for reading!

Top comments (0)