Unit test의 AAA 패턴(Arrange/Act/Assert)

테스트 코드를 작성할 때 AAA패턴(Arrange/Act/Assert)을 따르면 가독성이 향상되며, 다른 사람이 테스트 코드를 이해하는데 도움이 됩니다.

AAA패턴이란, 테스트 코드를 아래 3단계 순서로 구분하는 것을 말합니다.

  • Arrange(준비) : 테스트를 실행하기 전에 필요한 것들을 준비합니다. 예를 들어, 객체를 생성하거나, Mock 객체를 만들거나, 테스트 전에 호출되어야 할 API들을 호출하는 것들을 의미합니다.
  • Act(실행) : 테스트 코드를 실행합니다.
  • Assert(단언) : 실행한 코드가 예상한대로 동작했는지 확인합니다. assertTrue(), assertThat() 등의 코드들이 여기에 해당합니다.

예제

AAA패턴으로 작성한 테스트 코드입니다.

@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 : 테스트에 필요한 리스트 객체를 생성하였습니다.
  • Act : 테스트하려는 코드를 실행하였습니다. 여기서는 예로, 리스트에서 문자열 추가와 삭제를 수행하였습니다.
  • Assert : 예상하는 결과를 확인하였습니다.

위의 예제 처럼, 각 단계마다 빈줄로 구분하면 테스트 코드의 가독성이 더욱 좋아집니다. (주석으로 Arrange, Act, Assert를 입력해줄 필요는 없습니다.)

대부분의 개발자들은 AAA패턴을 알고 있기 때문에, 이런 흐름을 예상하면서 코드를 읽을 수 있습니다.

예제 2

위의 예제도 매우 간단하지만, Act 부분이 좀 정신없고, 서로 다른 내용을 체크하는 assert들이 호출되고 있습니다. 테스트 이름도 무엇을 테스트하려고 하는지 의도를 분명히 드러내고 있지 않습니다.

위의 테스트를 아래와 같이 두개의 테스트로 분리하였습니다. 각각의 테스트는 한가지 동작만 확인합니다.

@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");
}

먼저, Act에서 수행하는 3줄의 코드를 addAndRemoveThings()라는 메소드 1개로 변경하였습니다. 또한, 적절한 메소드 이름을 지어, 테스트를 읽는 사람이 메소드 안에서 무엇을 하는지 확인할 필요가 없도록 했습니다. 마지막으로 각 테스트에는 1개의 assert만 추가하였습니다. 서로 다른 결과를 확인하는 assert들이 많으면 이 테스트가 어떤 행위를 테스트하는지 논점이 흐려질 수 있습니다. (remove와 add를 하나의 테스트에서 체크해도 문제는 없어보입니다. 극단적으로 예를 들었으니 이런 부분들은 감안해주세요.)

테스트를 1개로 유지하면, Arrange나 Act에서 걸리는 시간을 절약할 수 있습니다. 하지만, 테스트 코드를 이해하는데 어려울 수 있고, 테스트가 실패했을 때, 그 뒤에 있는 assert 코드들은 확인되지 않고 테스트가 종료된다는 단점이 있습니다.

따라서, 여러 테스트로 분리해도 수행 시간이 오래 걸리지 않도록 가볍게 유지하면서, 1개의 테스트에 적은 수의 assert가 추가되도록 만드는 것이 좋습니다. 물론, 가이드일 뿐, 경우에 따라 많은 assert를 추가하는 것에서 이득이 있다면 그렇게 하시는 것이 좋습니다.

Loading script...

Related Posts

codechachaCopyright ©2019 codechacha