I was thinking about event sourcing and event storming the other day, and something clicked. Events in these systems are always named in past tense: “OrderPlaced,” “PaymentReceived,” “InvoiceAged.” They capture what has happened.

This connects directly to how I frame Given-When-Then scenarios: Given is past, When is present, Then is future. The Given section describes what has already happened—the conditions that are now in place.

We Can Only Capture What Has Happened

Here’s where it gets interesting. Consider an “InvoiceAged” event. This happens when an invoice hasn’t been paid within the payment terms. But there’s no “payment not made” event to capture—because nothing happened. The customer didn’t act.

So what actually happened? Time passed.

The event we can capture is that time has elapsed. Given the invoice was issued, given the payment terms were seven days, given seven days have passed, and given there’s no record of payment—now the invoice has aged.

We cannot capture what has not happened. We can only capture what has.

Writing Given Statements That Reflect Reality

This shapes how I write Given-When-Then scenarios. I used to see scenarios like this:


Given I have not paid my invoice

When...

But “I have not paid” isn’t an action to track. There’s no event there. It’s the absence of something.

Instead, I write it like this:


Given I purchased something
  and I was invoiced for it last week
  and the payment terms are seven days
  and seven days have passed
When I look for aged invoices
Then I see that invoice marked as aged
  and I am informed of how I can pay it

Now every Given statement describes something that actually happened:

  • A purchase occurred

  • An invoice was issued

  • Payment terms were established

  • Time elapsed

These are all events—things that happened in the past that set up the present moment.

The Pattern Across Domains

This isn’t just about invoices. It’s a pattern that shows up everywhere:

  • Not “Given the user is not logged in” but “Given the user’s session has expired”

  • Not “Given no items in cart” but “Given the user started a new shopping session”

  • Not “Given the feature is disabled” but “Given the feature flag was set to off”

Each reframing shifts from describing absence to describing what actually occurred.

Why This Matters

When I write scenarios this way, they map more naturally to how systems actually work. Event-sourced systems, audit logs, state machines—they all track what happened, not what didn’t happen.

It also makes scenarios more testable. “Seven days have passed” is something I can set up in a test. “Has not paid” is harder to reason about—how long do I wait? What conditions prove the absence?

And it keeps me honest about what I’m actually testing. If I’m checking for an aged invoice, I need to establish that time has passed and no payment was recorded. Those are the real conditions.

The Connection to Event Storming

When teams do event storming workshops, they put sticky notes on a wall representing domain events—all in past tense. “Customer registered.” “Order shipped.” “Refund processed.”

Those same events become the Given statements in scenarios. The past events that happened in the domain become the past conditions in the tests.

It’s the same mental model, the same language, flowing from domain modeling through to scenario writing.

The “InvoiceAged” event prompted my thinking about this topic.

What events have your system actually captured?

Leave a Reply

Trending

Discover more from Claudio Lassala's Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading