최근 배민 기술블로그를 보다가 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
'공부 > 프로그래밍' 카테고리의 다른 글
[linux-centos7] docker 설치 (0) | 2018.10.17 |
---|---|
[linux-centos7] nginx 설치 + php7 연동 + 도메인설정 (0) | 2018.10.16 |
[linux-centos7] DokuWiki(도쿠위키) 설치 (0) | 2018.10.11 |
[linux-centos7] gitlab 설치하기 (0) | 2018.10.10 |
[python-django] 파일 업로드(CSV파일) 및 파일내용 읽기 (0) | 2018.10.05 |
댓글