[java,gradle]단위 테스트(unit test)와 통합 테스트(integration test) 환경 분리

Minsu Kang·2021년 7월 3일
0

테스트를 작성하다가 아래와 같은 불편함을 겪은적이 있습니다.

  • UserService 라는 클래스에 대한 단위 테스트를 작성하기 위해 UserServiceTest 라는 클래스를 만들었다. 근데 이후에 UserService 에 대한 통합 테스트를 만들고 싶어졌다. 이미 UserServiceTest 라는 클래스명이 존재하는데 클래스명은 어떻게 지어야 할까??

  • 테스트 소요 시간의 차이 때문에 통합 테스트는 통합 테스트끼리, 단위 테스트는 단위 테스트끼리 실행하고 싶다. 어떻게 해야할까?

Java, Gradle 환경에서는 유닛테스트와 통합테스트 환경을 분리하여 위의 불편함을 해소할 수 있습니다.

프로젝트 생성

gradle 프로젝트를 하나 생성합니다.

초기 build.gradle 설정

plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
}

test {
    useJUnitPlatform()
}

build.gradle 통합테스트 환경 설정

통합 테스트 환경 구성에 필요한 설정들을 추가 해줍니다.

plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
}

test {
    useJUnitPlatform()
}

sourceSets {
    integrationTest {
        java.srcDir "$projectDir/src/integrationTest/java"
        resources.srcDir "$projectDir/src/integrationTest/resources"
        compileClasspath += main.output + test.output
        runtimeClasspath += main.output + test.output
    }
}

configurations {
    integrationTestImplementation.extendsFrom implementation
    integrationTestImplementation.extendsFrom testImplementation
    integrationTestRuntimeOnly.extendsFrom testRuntimeOnly
}

task integrationTest(type: Test) {
    testClassesDirs = sourceSets.integrationTest.output.classesDirs
    classpath = sourceSets.integrationTest.runtimeClasspath
    useJUnitPlatform()
}

check.dependsOn integrationTest

sourceSets

sourceSets은 Java 소스와 리소스 파일의 논리적 그룹을 의미합니다.
하나 이상의 Source 디렉터리를 Gradle에서 처리를 하기 위해서 SourceSets에 Source 디렉터리를 등록해 주면 됩니다.

  • java.srcDir : 자바 소스 파일을 포함하고 있는 소스 디렉토리들
  • resources.srcDir : 리소스를 포함하고 있는 소스 디렉토리들
  • compileClassPath : 소스를 컴파일할 때 사용할 클래스패스, += 는 기존 compileClassPath 를 overwrite 하는게 아니라 append 하는 기능이다.
  • runtimeClassPath : 클래스 실행시의 클래스패스

여기까지 설정하면 intergrationTest 디렉터리가 활성화 됩니다.


configurations

해당 프로젝트에서 사용할 의존성 구성을 의미 합니다.
integrationTest 에서 필요한 의존성을 지정해줍니다.

  • integrationTestImplementation.extendsFrom implementation
    : 메인(production) 프로젝트에 선언된 모든 dependency 가 integrationtest 의 dependency 에 포함된다.
  • integrationTestImplementation.extendsFrom testImplementation
    : 유닛 테스트에 선언된 모든 dependency 가 integrationtest 의 dependency 에 포함된다.
  • integrationTestRuntimeOnly.extendsFrom testRuntimeOnly
    : 마찬가지의 의미이다.

또한 integrationTest 환경에서만 사용할 dependency를 추가할 수도 있습니다.

integrationTestImplementation("org.springframework.batch:spring-batch-test")

task integrationTest

integraionTest 라는 이름의 task를 생성합니다.
type: test 로 선언하면 해당 task를 실행시 지정한 소스 밑에 있는 모든 테스트 케이스가 실행됩니다.

즉, ./gradlew integrationTest 명령을 실행하면 모든 통합 테스트 디렉터리 아래에 있는 테스트 케이스가 실행됩니다.

테스트 실행

integrationTest 밑에 테스트 케이스를 생성하니 잘 실행되는 모습입니다!

references
https://docs.gradle.org/current/userguide/java_testing.html#sec:configuring_java_integration_tests
https://kwonnam.pe.kr/wiki/gradle/java

profile
백엔드 개발자

0개의 댓글