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: Arrange, then Act, then Assert — 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 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:
"Wait 5 seconds, then assert"
you say:
"Wait until this condition becomes true, then continue"
That is the real power behind Given–When–Then.
- Given a scenario
- When a condition becomes true
- 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.
The Xcepto execution model
This is exactly the model behind Xcepto. 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 loops
- No pretending distributed systems are synchronous
Originally published on themassiveone.net.
