Junit5 tag를 이용해 Unit test, Integration test 분리하기

테스트 분리의 필요성

각 팀의 테스트 룰에 맞추어 Unit test, Integration test를 작성하게 될 텐데 Integratio test의 경우에 당연히도 Unit test보다는 훨씬 느린 수행속도를 갖게 될 것 입니다.

사실 Integration test를 개발을 하는 과정중에 매번 수행하게되면 생산성이 매우 낮아지게 될 것입니다. 이러한 이유로 인해 Unit testIntegration test는 분리해서 실행되어야 합니다.

보신분들도 있으시겠지만, 최근에 진행된 토스 개발자 컨퍼런스에서 가장 눈여겨 보았던 아래 세션을 통해서 분리의 필요성을 더 느낄수 있게 되었습니다. (테스트 약 3,000개 -> 6초 수행)

일반적으로 테스트 커버리지 확인시 jacoco를 사용하게 되는데, IDE에서 선택적으로 테스트를 run 시키는 것 뿐만 아니라 gradle test 과정에서도 unit test 만을 대상으로 할 수 있도록 필터링이 가능해야합니다.


Junit5 @Tag

Junit5 에서 제공하는 @Tag 기능을 사용하면 쉽게 구현 할 수 있습니다. Tag 기능을 통해 테스트들을 subset으로 묶어주는 기능으로, Tag 이름을 기반으로 필터링하는 기능까지 제공해 주고 있습니다.

저는 아래와 같이 사용합니다.

// IntegrationTest.java


@Tag("IntegrationTest")
@SpringBootTest
@AutoConfigureMockMvc
public abstract class IntegrationTest
{
    @Autowired
    protected MockMvc mockMvc;
}

// SomethingIntegrationTest.java

public class SomethingIntegrationTest extends IntegrationTest
{
  @Test
  void something_success()
  {

  }
}

// UnitTest.java

@Tag("UnitTest")
public abstract class UnitTest
{
}
// SomethingUnitTest.java

public class SomethingUnitTest extends UnitTest
{
  @Test
  void something_success()
  {

  }
}

abstract class에 tag를 선언해두고 테스트 목적에 따라 extends 해서 간단하게 설정 할 수 있습니다. 태그를 설정해두면 아래와 같이 테스트를 분리해서 사용 가능합니다.

  • IntelliJ IDEA 설정

1

2

  • gradle 설정
// build.gradle

test {
    useJUnitPlatform{
        includeTags 'UnitTest'
        excludeTags 'IntegrationTest'
    }
}

task integrationTest(type: Test) {
    useJUnitPlatform{
        includeTags 'IntegrationTest'
        excludeTags 'UnitTest'
    }
}

위의 설정들을 통해 IDE, gradle 모두에서 Tag 기반으로 테스트를 필터링해서 수행 시킬 수 있습니다. 테스트 커버리지 확인시에도 물론 Unit test만 으로 측정되게 됩니다.