Some unit tests are focused, other are like a run-on sentence. How can we create tests that are focused and communicate well?
What's a good structure for a unit test?
3A: Arrange, Act, Assert
We want to test the behavior of objects. One good approach is to put an object into each "interesting" configuration it has, and try various actions on it.
Consider the various types of behaviors an object has:
- Mutators, also known as modifiers or commands
- Accessors, also known as queries
I learned this separation a long time ago but I don't know the source (though my guess would be some Abstract Data Type research). It's embodied in Bertrand Meyer's "command-query separation" principle, and others have independently invented it.
With those distinctions in mind, we can create tests:
Arrange: Set up the object to be tested. We may need to surround the object with collaborators. For testing purposes, those collaborators might be test objects (mocks, fakes, etc.) or the real thing.
Act: Act on the object (through some mutator). You may need to give it parameters (again, possibly test objects).
Assert: Make claims about the object, its collaborators, its parameters, and possibly (rarely!!) global state.
Where to Begin?
You might think that the Arrange is the natural thing to write first, since it comes first.
When I'm systematically working through an object's behaviors, I may write the Act line first.
But a useful technique I learned from Jim Newkirk is that writing the Assert first is a great place to start. When you have a new behavior you know you want to test, Assert First lets you start by asking "Suppose it worked; how would I be able to tell?" With the Assert in place, you can do what Industrial Logic calls "Frame First" and lean on the IDE to "fill in the blanks."
Aren't some things easier to test with a sequence of actions and assertions?
Occasionally a sequence is needed, but the 3A pattern is partly a reaction to large tests that look like this:
- Arrange more
To understand a test like that, you have to track state over a series of activities. It's hard to see what object is the focus of the test, and it's hard to see that you've covered each interesting case. Such multi-step unit tests are usually better off being split into several tests.
But I won't say "never do it"; there could be some case where the goal is to track a cumulative state and it's just easier to understand in one series of calls.
Sometimes we want to make sure of our setup. Is it OK to have an extra assert?
Such a test looks like this:
- Assert that the setup is OK
- Assert that the behavior is right
First, consider whether this should be two separate tests, or whether setup is too complicated (if we can't trust objects to be in the initial state we want). Still, if it seems necessary to do this checking, it's worth bending the guideline.
What about the notion of having "one assert per test"?
I don't follow that guideline too closely. I consider it for two things:
- A series of assertions may indicate the object is missing functionality which should be added (and tested). The classical case is equals(): It's better to define an equals() method than (possibly create and) repeat a bunch of assertions about held data.
- A series of similar assertions might benefit from a helper (assertion) method.
(If an object has many accessors, it may indicate the object is doing too much.)
When a test modifies an object, I typically find it easiest to consider most accessors together.
For example, consider a list that tracks the number of objects and the maximum entry. One test might look like this:
List list = new List();
That is, it considers the case "what all happens when one item is inserted into an empty list?" Then the various assertions each explore a different "dimension" of the object.
What about setup?
Most xUnit frameworks let you define a method that is called before each test. This lets you pull out some common code for the tests, and it is part of the initial Arrange. (Thus you have to look in two places to understand the full Arrange-ment.)
What about teardown?
Most xUnit frameworks let you define a method that is called after each test. For example, if a test opens a file connection, the teardown could close that connection.
If you need teardown, use it, of course. But I'm not adding a fourth A to the pattern: most unit tests don't need teardown. Unit tests (for the bulk of the system) don't talk to external systems, databases, files, etc., and Arrange-Act-Assert is a pattern for unit tests.
I (Bill Wake) observed and named the pattern in 2001. "Arrange-Act-Assert" has been the full name the whole time, but it's been variously abbreviated as AAA or 3A. Kent Beck mentions this pattern in his book Test-Driven Development: By Example (p. 97). This article was written in 2011. Added a description of Assert First and Frame First due to Brian Marick's comment. [4/26/11]