Posts

Given-When-Then is not just syntax. It’s a mindset.

A post about why Given-When-Then fits asynchronous system behavior better than Arrange-Act-Assert.

Given-When-Then is not just syntax. It’s a mindset.

For years, system tests have been written with Arrange–Act–Assert.

That works — until asynchronous behavior enters the picture.

AAA implicitly assumes synchronicity:

  1. Arrange
  2. Act
  3. Assert

The assertion happens after the action, as if the system has already settled.

But distributed systems don’t behave like that.

  • An API call may publish an event
  • A queue consumer may process it later
  • A workflow may eventually converge

Timing becomes unpredictable.

The common workaround?

  • Sleep(5000)
  • Retries
  • Polling loops

Fragile tests are built on timing assumptions.

Waiting for causality

The real problem is this:

We wait for time instead of waiting for causality.

In asynchronous systems, timing should be causal rather than actual.

Instead of saying:

"Wait 5 seconds, then assert"

You say:

"Wait until this condition becomes true, then continue"

That is the real power behind Given–When–Then.

  1. Given a scenario
  2. When a condition becomes true
  3. Then validate the resulting system state

And once you think about testing causally, an interesting property emerges:

You can chain multiple When -> Then transitions together.

Each validated state becomes the next Given.

Xcepto.NET

This is exactly the execution model behind Xcepto.NET — my open-source system testing framework.

Tests are compiled into condition-driven state machines where transitions happen because conditions are satisfied, not because enough time passed.

  • No manual sleeps
  • No retry loop
  • No pretending distributed systems are synchronous

Xcepto.NET