Arrange-Act-Assert



Source: William C. Wake


In a unit test, three things typically need to happen: you must first create a context, then execute the thing that you're trying to verify, and finally verify that what was executed actually behaved as expected. So if, for example, I need to verify that the system properly applies a fine to a library patron for returning a delinquent book, I:


  • arrange the context by creating a new patron object and setting its fine balance to $0

  • act by executing the applyFine method with an argument of $0.10

  • assert that the patron's balance is $0.10, thus verifying that the fine was applied correctly to the patron


The most direct result of thinking about tests in this manner is its impact on the code's visual layout:

@Test public void applyFine() {
Patron patron = new Patron();
patron.setBalance(0);

patron.applyFine(10);

assertEquals(10, patron.fineBalance());
}

Note the blank lines separating the three act, arrange, and assert sections in the test applyFine. I've even seen some test code with guiding comments to make the section names explicit:

// arrange
...
// act
...
// assert
...

Honestly, it's idiomatic--once this organization is explained, the intent is obvious, and thus it's only a waste of time and space to include such low-value comments.


Emphasizing AAA (Arrange-Act-Assert) played a significant factor in the evolution of the Rhino Mocks framework for NUnit. Ayende Rahien introduced a new interface for Rhino Mocks 3.5, one that dispenses with the need to call a "verify mock" method after assertions are complete. This allows for cleaner, AAA-compliant tests. In contrast, older "classic" syntax for record-replay mock tools generates "mock clutter" across the test--record, replay, and verify calls are littered through the test.


Note that the form can vary. If you're verifying a static function, there may be no need to Arrange anything. And you may also want to introduce preconditions that verify things are in an appropriate state before the Act step--you could end up with Arrange-Assert-Act-Assert, or even Assert-Arrange-Act-Assert. And it's also possible for Act and Assert to be combined effectively in a single line of code. I don't believe there's value in being dogmatic about the organizational form, but there is value in striving to ensure that the intent of the test is clear. Keeping sections clear and visually separate from each other helps!


Arrange-Act-Assert is a simple concept, and probably only adds marginal value. But it costs nothing to practice, and it gets us that much closer to being a community willing to agree on some standards. What I also like about memorable acronyms like AAA is that they provide a consistent way to communicate simple ideas, which often don't have concise and consistent names.

7 comments:

  1. AKA "BOC" for Build, Operate, Check.

    ReplyDelete
  2. Right. I just used to call it "setup, execute, verify." I like the idea of a standard mnemonic, and AAA seems more memorable.

    ReplyDelete
  3. Is that also a synonym for Given/When/Then?

    ReplyDelete
  4. G/W/T you hear more in AT, AAA/BOC/etc in unit test.
    But yes.

    This is one of those incredibly simple ideas that effectively fights writers' block for testers. G/W/T, AAA, BOC, regardless of the name I've seen people break out of a funk just by reciting it.

    And when that breaks down, I like "write the assert first", because that further focuses the mind.

    ReplyDelete
  5. Oh, now that I re-read this, I remember that I originally wrote the code funky:

    @Test public void applyFine() {
    Patron patron = new Patron();
    patron.setBalance(0);
    // ...
    }

    on purpose, so as to show Arrange-Assert-Act-Assert:

    @Test public void applyFine() {
    Patron patron = new Patron();
    assertEquals(0, patron.fineBalance());

    patron.applyFine(10);

    assertEquals(10, patron.fineBalance());
    }

    Now that I coded this and saw that I didn't like it with 4 chunks, I deleted the first blank line. Thus visually, at least, any precondition assert is probably just treated as part of "Arrange."

    ReplyDelete
  6. I think it adds more than marginal value. Check out my post about Why and what is Arrange Act Assert here http://www.arrangeactassert.com/why-and-what-is-arrange-act-assert/

    ReplyDelete