AAA pattern of unit test (Arrange/Act/Assert)

When writing test code, following the AAA pattern (Arrange/Act/Assert) improves readability and helps others understand your test code.

AAA pattern refers to dividing the test code into the following three steps.

  • Arrange : Arrange the necessary things before running the tests. For example, it means creating an object, creating a mock object, or calling APIs that need to be called before testing.
  • Act : Execute the test code
  • Assert : Verifies that the executed code behaves as expected. Codes such as assertTrue(), assertThat(), etc.

example

This is the test code written in AAA pattern.

@Test
public void testAAAPattern() {
    // Arrange
    List<String> list = new ArrayList<>();

    // Act
    list.add("123");
    list.add("abc");
    list.remove("abc");

    // Assert
    assertThat(list, hasItem("123"));
    assertThat(list, not(hasItem("abc")));
}
  • Arrange : Created a list object needed for testing
  • Act : Executed the code to be tested. Here, as an example, we have added and deleted strings from the list.
  • Assert: We have confirmed the expected result.

As in the example above, separating each step with a blank line makes the test code more readable. (It is not necessary to input Arrange, Act, Assert as comments.)

Most developers know the AAA pattern, so you can read the code in anticipation of this flow.

Example 2

The above example is also very simple, but the Act part is a bit crazy, and asserts that check different contents are being called. Even the name of the test doesnt clearly indicate what youre testing for.

The above test was divided into two tests as follows. Each test checks for only one behavior.

@Test
public void testDoingSomething_hasItem() {
    // Arrange
    List<String> list = new ArrayList<>();

    // Act
    addAndRemoveThings(list);

    // Assert
    assertThat(list, hasItem("123"));
}

@Test
public void testDoingSomething_hasNotItem() {
    // Arrange
    List<String> list = new ArrayList<>();

    // Act
    addAndRemoveThings(list);

    // Assert
    assertThat(list, not(hasItem("abc")));
}

private void addAndRemoveThings(List<String> list) {
    list.add("123");
    list.add("abc");
    list.remove("abc");
}

First, I changed the 3 lines of code performed in Act to one method called addAndRemoveThings(). Also, by naming the methods appropriately, we don`t need to see what the reader of the test is doing inside the method. Finally, we added only 1 assert to each test. Having a lot of asserts that check different results can obscure what behavior this test tests for. (It seems that there is no problem even if you check remove and add in one test. This is an extreme example, so please consider these parts.)

By keeping one test, you can save time in Arrange or Act. However, it can be difficult to understand the test code, and when the test fails, the assert code behind it is not checked and the test is terminated.

So, its a good idea to have a small number of asserts added to a single test, while keeping it lightweight so that splitting it up into multiple tests doesnt take too long. Of course, this is only a guide, and in some cases its fine to do so if theres a benefit to adding a lot of asserts.

codechachaCopyright ©2019 codechacha