People often ask me if Arrange-Act-Assert (AAA) is the same as Given-When-Then (GWT). On the surface, they look similar. Both give structure to tests. Both help organize thinking. But there’s a fundamental difference that affects how I approach refactoring.
The Refactoring Definition
Martin Fowler defines refactoring as “to change the internal implementation without changing the externally observable outcome.” That definition is key to understanding why I prefer starting with Given-When-Then.
Where AAA Falls Short
When I write tests using Arrange-Act-Assert, I’m typically practicing Test-Driven Design (TDD). I write the test first, describing the code I’d like to have: the classes, methods, parameters, and return values. All of that lives in the test.
This works well for refactoring the implementation. I can change how a method works internally without touching the test, as long as the externally observable outcome stays the same.
But what if I want to refactor the API itself?
If I decide to change the method signature, rename a class, or restructure how objects collaborate, I have to change the test. The test is coupled to the API, not just to the behavior.
Why I Start with Given-When-Then
This is where Given-When-Then shines. When I write a spec using GWT, I’m describing the externally observable outcome first. I’m not committing to a specific API or implementation structure yet.
This gives me more freedom to refactor:
-
I can change the API without touching the spec
-
I can replace one class with a combination of classes
-
I can introduce a service layer in front of existing objects
-
I can restructure the entire internal design
As long as the externally observable outcome remains the same, my spec doesn’t need to change.
My Workflow: BDD First, Then TDD
Here’s how I typically work:
-
Start with BDD: Write a Given-When-Then spec that describes the desired externally observable outcome
-
Drop into TDD: Describe the APIs I’d like to have to achieve that outcome
-
Write the implementation: Build the internal code that makes it work
-
Refactor freely: If the implementation gets too big, I can extract parts into smaller components
If I need to verify those extracted parts separately, I can write smaller specs for them. But I keep that original external spec in place. It continues to verify the initial desired outcome, regardless of how the internals evolve.

Differences Between BDD and TDD.
The Difference in Practice
The distinction isn’t just theoretical. It affects how much flexibility I have when the code needs to change.
With AAA-style tests, I’m verifying that specific objects and methods work correctly. That’s valuable, but it locks me into those specific objects and methods.
With GWT-style specs, I’m verifying that the system produces the right outcome. The internal structure can shift without invalidating my specifications.
A Question Worth Sitting With
When you write tests, are you describing behavior or implementation? And does that choice give you the freedom to refactor when you need it?





Leave a Reply