SpringBoot + Spock 설정 방법

본 글에서는 SpringBoot와 Spock Test Framework를 연동하는 방법에 대해 소개한다.

     

    구성 환경 (의존성)

    • SpringBoot: 2.4.2
      • Default JUnit: 5.x
    • Spock: 1.3
    • Groovy: 2.5

    만약, 이후에 다른 버전으로 테스트 한다면, 그에 맞는 설정 방법을 다시 확인해야할 것이다.

     

    기본 틀잡기

    Spring Initializer(https://start.spring.io/)를 활용하여, 일단 기본적인 프로젝트를 다음과 같이 설정해 보았다.

    plugins {
      id 'org.springframework.boot' version '2.4.2'
      id 'io.spring.dependency-management' version '1.0.11.RELEASE'
      id 'java'
    }
    group = 'com.example'
    version = '0.0.1-SNAPSHOT'
    sourceCompatibility = '11'
    repositories {
      mavenCentral()
    }
    dependencies {
      implementation 'org.springframework.boot:spring-boot-starter'
      testImplementation 'org.springframework.boot:spring-boot-starter-test'
    }
    test {
      useJUnitPlatform()
    }

     

    Spock 설정

    예전 프로젝트에 적용한 설정을 참고하여,

    ...
    apply plugin: 'groovy'
    ...
    dependencies {
    ...
        testCompile "org.spockframework:spock-core:1.2-groovy-2.4"
        testCompile "org.spockframework:spock-spring:1.2-groovy-2.4"
    ...
    }

    만 일단 추가해 보았다. 예전 환경(SpringBoot/Spock 등) 기준에서는, 이것으로 설정 자체는 완료라고 할 수 있었다. 그러나, 2021/2월 기준으로는 위와 같이 설정하는 것만으로는 충분하지 않다.

     

    샘플 테스트 코드 작성

    기본적으로는 test directory가 java용으로만 생성되어 있을 것이다. Spock 테스트와 분리하여 (관리 편의성) 작성하기 위해, groovy라는 디렉토리를 생성한다. 새로 생성한 groovy 디렉토리에 커서를 두고 마우스 오른쪽 버튼을 누른 후, Mark Directory as > Test Sources Root로 설정한다. 그러면 아래 스크린샷처럼, java 디렉토리와 마찬가지로 groovy 디렉토리 색깔도 동일해진다.

    groovy 디렉토리내에 groovy 테스트 코드를 작성하자.

    작성한 Spock 테스트 코드는 아래와 같다.

    class FirstSpec extends Specification {
        def "first test"() {
            expect:
            1 == 1
        }
    }

    그리고, Spock 테스트 코드를 간단하게 작성하여 실행해 보았다. 그랬더니, 다음과 같은 에러가 발생하였다.

     

    No Tests found for given includes 에러 발생 상황

    IntelliJ에서 테스트코드를 작성하여 실행하려고 할 때, 이전에는 못보던 에러다.

    > Task :test FAILED
    FAILURE: Build failed with an exception.
    * What went wrong:
    Execution failed for task ':test'.
    > No tests found for given includes: [FirstSpec.first test](filter.includeTestsMatching)
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    * Get more help at https://help.gradle.org
    BUILD FAILED in 3s
    

    사람마다 이 에러를 만나는 상황은 다양하겠지만 내 경우는 java 테스트 코드는 성공적으로 실행되는데, Spock로 작성한 groovy 코드만 테스트 코드 실행시 위와 같은 에러가 발생하였다. (Gradle로 관리)

     

    해결방안 1 - IntelliJ 설정

    우선 간단한 해결책은, IntelliJ의 설정을 변경하는 것이다. Preferences 메뉴를 선택하여, 다음 스크린샷과 같이 변경한다.

    • Build, Execution, Deployment > Build Tools > Gradle > Run tests using > Gradle(Default)을 IntelliJ IDEA로 변경한다.

    이와 같이 변경하고, 위에 실패한 테스트 코드를 다시 실행시켜 본다. 일단, 아래와 같이 성공하는 것을 볼 수 있다.

    그런데, 이렇게 해놓는 것으로도 충분할까? 분명, 내 로컬에서는 괜찮을 것이다. 그러나, 프로젝트 파일을 공유해야 하는 상황이라면 어떨까?

     

    예상되는 문제점

    위와 같이 설정한 경우라면, 분명 IDE에서는 잘 넘어간다. 그런데, CI/CD를 돌린다면 정상적으로 테스트가 진행될까? 다음의 커맨드로 우선 확인해 보자.

    $ ./gradlew test
    
    BUILD SUCCESSFUL in 5s
    5 actionable tasks: 1 executed, 4 up-to-date

    위 명령어로만 보면, 테스트가 성공한 것처럼 보인다. 그러나, 다음의 명령어로 다시 확인해 보자.

    $ ./gradlew test --tests FirstSpec
    
    > Task :test FAILED
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':test'.
    > No tests found for given includes: [FirstSpec](--tests filter)
    
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    
    * Get more help at https://help.gradle.org
    
    BUILD FAILED in 2s
    5 actionable tasks: 1 executed, 4 up-to-date

    위 명령어에서 내가 작성한 테스트 파일의 이름이 FirstSpec.groovy이다. 그런데, 위와 같이 실행하면 처음과 같은 에러가 발생함을 알 수 있다. 즉, IntelliJ 내부에서는 에러가 발생하지 않지만, IDE 밖에서는 (외부 툴) 아직 문제가 해결되지 않았다.

     

    테스트 여부 확인하기 - 1

    다른 관점에서 실제 테스트 실행여부를 확인해 보고자 한다. 즉, 테스트 커버리지 리포트를 확인해 본다면 실행 여부를 확인할 수 있을 것이다. build.gradle에 다음의 설정을 추가한다.

    apply plugin: 'jacoco'

    플러그인을 추가했으니, 빌드하고 테스트 리포트를 확인해 보자.

    $ ./gradlew build
    $ ./gradlew jacocoTestReport

    build 디렉토리를 탐색해서 확인해 본다.


    내가 작성한 테스트클래스는 FirstSpec.groovy인데 목록에 보이지 않는다. 즉, test되지 않았음을 확인할 수 있다.

     

    해결방안 2 - 설정 변경

    build.gradle 설정에 다음 항목을 넣어보자.

    testRuntimeOnly('org.junit.vintage:junit-vintage-engine')

    적용효과(?)를 확인하기 위해, 앞서 Preferences 메뉴에서 설정한 것을 IntelliJ IDEA -> Gradle (Default)로 원복하자.
    그리고, 다시 테스트를 실행해보자.

    (앞서 떴던 WARNING 메시지도 안보인다)

    위에서 에러가 발생한 케이스를 커맨드라인에서도 동일하게 다시 테스트해 보자.

     $ ./gradlew test --tests FirstSpec
    
    BUILD SUCCESSFUL in 5s
    5 actionable tasks: 1 executed, 4 up-to-date

    이번에는 테스트가 성공했다.

     

    테스트 여부 확인하기 - 2

    잘 테스트가 진행되었는지 테스트 커버리지로 다시 확인해 보자.

    $ ./gradlew build
    $ ./gradlew jacocoTestReport

    를 실행한 후, build 디렉토리에서 결과를 확인해 본다.

     


    테스트 항목이 노출되는 것을 확인할 수 있다.

     

    결론

    이와 같이 돌아오게 된 이유는 대략 다음과 같다.

    • SpringBoot 2.2.X부터 JUnit5가 기본적으로 탑재되었음
    • 기존에는 JUnit4기반이었기 때문에, 처음에 기록한 것과 같은 설정만으로도 충분했음
    • 그런데, Spock 현재 버전은 (Groovy 2.5) JUnit4 의존성을 지님.
    • 따라서, 설정에 JUnit4 기반 설정을 추가로 진행해줘야 함.

    이 설정을 별도로 진행해 주지 않으면, 외부 툴/외부 환경에서 독립적으로 테스트가 실행이 안될 수도 있겠다.

    Spock Repo(https://github.com/spockframework/spock#latest-versions)에 설명된 바에 따르면,

    NOTE: Spock 1.3 is the last release for 1.x based on JUnit 4. Spock 2.0 is based on the JUnit 5 Platform and require Java 8/groovy-2.5

    와 같이 설명이 되어 있는 것을 확인할 수 있다.

    지금까지 테스트한 최종 설정은 다음과 같다. 최초 테스트에서 groovy 버전은 2.4로 했으나, 정리본에서는 2.5로 기록했다.

     

     

    소스 참고)

    https://github.com/luran-codes/springboot-spock-config

     

    댓글

    Designed by JB FACTORY