본문 바로가기
공부/프로그래밍

[SpringBoot] Spock 이용해 테스트코드 작성하기

by demonic_ 2018. 10. 14.
반응형

최근 배민 기술블로그를 보다가 Spock라는 테스트 코드 작성 소개가 있어 정리겸 남깁니다.


일단 이 테스트 방법은 SpringBoot 환경에서 해야합니다. 저는 이것도 모르고 Spock만 추가했다가 이상한 에러에 몇시간동안 삽질을 했습니다... SpringBoot가 없이 작성하게 되면 아래의 메세지를 보게됩니다.


Caused by: java.lang.ClassNotFoundException: org.springframework.test.context.ContextConfiguration

at java.net.URLClassLoader.findClass(URLClassLoader.java:381)

at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)

at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

... 11 more


그럼 이제 설정 및 작성법에 대해 알아보겠습니다.


gradle에 다음을 추가합니다.


1
2
3
4
5
dependencies {
    ...
    testCompile('org.spockframework:spock-core:1.1-groovy-2.4')
    testCompile('org.spockframework:spock-spring:1.1-groovy-2.4')
}
cs


spock 는 groovy 문법을 사용합니다. 그래서  test 패키지에 groovy 라는 폴더를 추가했습니다. 사실 이것은 선택이기는 하지만 추후 java 로 만드는 것과 분리하는 것이 좋을것 같아 분리했습니다.



파일을 생성합니다. 확장자는 groovy 로 합니다.

그리고 뒤에 extends로 Specification를 추가해줍니다. 이렇게하면 테스트 클래스가 됩니다.




- 기본사용법


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import spock.lang.Specification
 
// Specification 를 extends 하면 테스트클래스가 된다.
class TestSpockApplicationTest extends Specification {
    def "Spock 테스트 입니다"(){
        // given: 테스트 하기 위한 기본 설정작업
        given:
        List<Integer> list = new ArrayList<>();
 
        // 테스트할 대상 코드를 실행
        when:
        list.add(1)
 
        // 테스트 결과 검증
        then:
        2==list.get(0)
    }
}
cs


groovy에서는 function을 한글로 작성가능합니다. 그리고 def라고 명시해주어야 합니다. 그리고 테스트 할때에는 given, when, then을 꼭 넣어주어야 합니다. 


- given: 테스트 하기 전 기본 설정작업 입니다

- when: 테스트 할 대상코드를 실행

- then: 테스트 후 결과검증을 이곳에 넣어줍니다.


이렇게 해서 실행하면 다음과 같은 결과를 얻습니다.

위의 테스트는 틀리게 작동하게 했으므로 다음과 같은 에러를 보여줍니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
Condition not satisfied:
 
2==list.get(0)
 | |    |
 | [1]  1
 false
 
Expected :1
 
Actual   :2
 
 <Click to see difference>
 
    at demonic.testspock.TestSpockApplicationTest.Spock 테스트 입니다(TestSpockApplicationTest.groovy:19)
cs


기존 JUnit 을 사용할때보다 명시적이어서 좋은 것 같습니다.

성공으로 수정하면 다음과 같이 뜨고 완료됩니다.





- when, then 대신 expect 사용하기

expect는 쉽게말해 when 과 then을 합친거라 보면 됩니다. 다만 여러번 실행해야 할때 유리한 면을 갖습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// when, then 대신 expect 사용하기.
def "Spock expect 테스트"() {
 
    // 대상 코드를 실행 + 검증합니다.
    // a와 b를 메서드에 넣은 후 결과값을 c에 저장합니다.
    expect:
    Math.max(a, b) == c
 
    // feature 메소드를 파라미터로 삼아 실행시킵니다.
    // a라인과 b라인 c라인이 각각 변수이며
    // a=4, b=1, c=4 로 실행한 후 다음줄을 또 실행합니다.
    // feature 메소드를 파라미터로 변환하여 실행합니다.
    where:
    a | b | c
    4 | 1 | 4
    3 | 9 | 9
    7 | 4 | 7
}
cs


보면 where 에다 구분자 '|'를 이용해서 3개를 한 줄에 담았는데, 첫번째가 a라는 변수에 대입할 값을, 두번째가 b라는 변수에 대입할 값을, 세번째가 expect에서 실행한 값을 c에 넣었는데, 이 값이 작성한 값과 일치하는지 봐줍니다.


성공하면 위의 성공과 같은 초록화면이 뜨는데, 이중에 값이 달라 실패하게 되면 다음과 같은 결과를 보여줍니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
Condition not satisfied:
 
Math.max(a, b) == c
     |   |  |  |  |
     9   3  9  |  8
               false
 
Expected :8
 
Actual   :9
 
 <Click to see difference>
 
    at demonic.testspock.TestSpockApplicationTest.Spock expect 테스트(TestSpockApplicationTest.groovy:28)
cs





- Exception 테스트

마지막으로 exception 을 보겠습니다. Spock의 장점은 Exception 테스트를 할때에 exception에 담기는 객체의 값을 볼 수 있다는 점입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def "Exception 테스트"(){
    given:
    def testExceptionClass = new TestExceptionClass();
    def a = 0;
    println "= Exception 테스트 Start "
 
    when:
    a = testExceptionClass.testValue(1)
 
    then:
    def e = thrown(RuntimeException.class)
    println e.message
    // exception 이 발생했기 때문에 아래 a 는 0 이 들어있다.
    1 == a
}
 
// Exception를 발생시키기 위해 임의의 클래스 생성
class TestExceptionClass {
    // 1 값을 return 함
    public static int testValue(int a){
        throw new RuntimeException("테스트 Exception 입니다");
        return a;
    }
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
=== Exception 테스트 Start 
exception message: 테스트 Exception 입니다
 
Condition not satisfied:
 
1 == a
  |  |
  |  0
  false
 
Expected :0
 
Actual   :1
 
 <Click to see difference>
 
    at demonic.testspock.TestSpockApplicationTest.Exception 테스트(TestSpockApplicationTest.groovy:54)
cs




흥미로운 것은 Exception이 일어나면 e.message를 통해 Exception의 메세지를 바로 볼 수 있습니다. 그리고 Exception이 일어났다 하더라도 거기서 멈추지 않고 마지막 비교문(1==a)까지 실행합니다.



공식사이트:

http://spockframework.org/spock/docs/1.0/spock_primer.html



참조사이트:

https://jojoldu.tistory.com/229

http://woowabros.github.io/study/2018/03/01/spock-test.html



샘플코드 Github

https://github.com/lemontia/test-spock





반응형

댓글