jonnifyagile agents
jonnify / Agile Agent Workflow / A2 · Decomposition / A2.04 / A2.04.1 · Given / When / Then

A2.04 · Acceptance · dive 1

Given, When, Then

A scenario has three clauses: Given fixes the context, When is the single action, Then is the observable outcome. One behaviour, one scenario.

The values are concrete, never abstract: “a learner not enrolled” and “enrolled exactly once”, not “valid input” and “correct state”. A reader can check a concrete example; nobody can check “correct”. Read each clause of one Portal scenario on the right.

The three clauses of one scenario · read each

GIVEN · the precondition a learner who is not enrolled in the course WHEN · the action the learner enrols in the course THEN · the observable they appear in their enrolments exactly once
Given: the precondition — a learner who is not enrolled. It sets the state of the world before the action; a concrete starting point, not “valid input”.

Three clauses, one behaviour

Gherkin names three keywords. Given is the precondition: what is true before the action, the state that sets up the world. When is the event: the one thing the actor does — exactly one action per scenario. Then is the postcondition: the observable result the scenario asserts. Read top to bottom, the three clauses are a complete, checkable account of one behaviour.

The discipline is concreteness. “Given a learner not enrolled” names a specific starting state; “Then enrolled exactly once” names a specific, observable result. Compare “Given valid input, Then correct state”: nobody can check “correct” without first agreeing what it means, which is the argument the scenario was meant to end. A concrete example settles it — one reading, one check.

Given
The precondition: what is true before the action. It sets up the world — a concrete starting state, not “valid input”.
When
The event: the one action the actor takes. Exactly one per scenario.
Then
The postcondition: the observable outcome the scenario asserts — concrete, so it can be checked.

Concrete values are the point: a scenario exists to end an argument about “done”, and only a concrete example can be checked rather than debated.

One behaviour per scenario

A scenario isolates one behaviour. If a When describes two actions, or a Then asserts two unrelated outcomes, it is two scenarios wearing one title. The cost is real: when such a scenario fails, the failure does not say which behaviour broke, so the check that was meant to localise a defect instead hides it. Splitting restores the one-to-one map from scenario to behaviour.

Switch the view to compare a well-formed scenario with an overloaded draft. The well-formed one has a single action and a single outcome. The overloaded one crams two actions into one When and asserts two outcomes — it is shown in burgundy. The readout counts the actions and outcomes from the draft and reports whether it is one scenario or two.

One behaviour, or two in one? · switch the draft

the draft scenario WHEN the learner enrols in the course THEN they appear in their enrolments exactly once 1 action · 1 outcome · one behaviour
1 action · 1 outcome · one behaviour — a well-formed scenario. The single action under test maps to the single outcome asserted.

One scenario, one behaviour: two actions or two outcomes are two scenarios in disguise — and a failure that cannot say which behaviour broke hides the defect it was meant to find.

Given / When / Then on the Portal

Take the Portal rung “enrol in a course”. Its happy-path scenario is one Given, one When, one Then. Given a learner not enrolled fixes the starting state; When the learner enrols is the single action; Then they appear in their enrolments exactly once is the observable outcome. The id authority is Portal.ID: Portal.ID.generate/1 mints the enrolment id when the action runs. Nothing else about the engine is asserted — the scenario states the behaviour, not the implementation.

# A2.04.1 — the enrol rung's behaviour as one scenario.
Scenario: a learner enrols in a course
  Given a learner who is not enrolled in "Functional Programming"
  When  the learner enrols in "Functional Programming"
  Then  the learner appears in their enrolments exactly once

# concrete, not abstract — "exactly once", not "correct state".
# the action mints one id; the rest of the engine is not asserted here.
id = Portal.ID.generate(:enrolment)   # => "ENR0Nb...": one enrolment id, on the action

The principle

State a behaviour as Given (context) / When (one action) / Then (observable outcome), with concrete values — one scenario per behaviour.

On the Portal

The enrol behaviour is one scenario: Given a learner not enrolled, When they enrol, Then they appear in their enrolments exactly once — the action mints one id via Portal.ID.generate/1.

Three clauses, one behaviour, concrete values — Given the world, When one action, Then one observable outcome.

Recap — the shape of a check

Given sets the world, When fires one action, Then asserts one observable outcome — and the values are concrete, so the scenario is a check rather than a debate. Two actions or two outcomes mean two scenarios; one behaviour per scenario keeps a failure able to say what broke. With the structure in hand, the next dive shows that these concrete examples are not documentation about the spec — they ARE the shared definition of done.

Next in A2.04: A2.04.2 · Examples as the spec — the concrete examples are the shared definition of done, the one artifact product, the Operator, and the Author all read.

References

Primary sources for the scenario structure, and where it connects in the course.

Sources

Related in this course