Skip to main content

Xcepto was trying to solve RabbitMQ testing. It ended up reinventing testing itself.

· 2 min read
Daniel Maß
Maintainer of Xcepto

When I started Xcepto, I wasn't trying to build a testing framework.

I was trying to solve a messaging problem.

RabbitMQ systems are notoriously awkward to test: events arrive asynchronously, processing order is not guaranteed, listeners must be configured before messages are published.

The obvious solution seemed to be better messaging abstractions. But the deeper I went, the more I realized messaging wasn't the real problem.

The real problem was that control flow and execution flow had diverged.

The mismatch

Consider a typical acceptance test:

  • Given a system
  • When a message is published
  • Then a response should be observed

The test appears sequential. The runtime isn't.

  • ❌ Message handlers execute elsewhere.
  • ❌ Callbacks execute later.
  • ❌ Assertions depend on behavior that is not visible in the control flow.

The code says one thing. The execution does another.

The model

That realization completely changed the direction of Xcepto.

Instead of executing test steps immediately, Xcepto builds a declarative model first:

  • Test structure is defined before execution begins
  • Subscriptions and expectations are prepared upfront
  • Developers keep the sequential Given-When-Then mental model

The runtime then executes that model.

The result was a surprising discovery: messaging was not the root problem. RabbitMQ merely exposed it. The execution model was the real issue.

Today, RabbitMQ support is no longer the center of Xcepto. The execution model is.

Funny how sometimes the problem you start with is only a symptom of a much deeper one.


Originally published on themassiveone.net.