사적인 개발자
[TDD] Spock BDD test (feat.grails) 본문
grails에 장착되어있는 Spock를 활용해 TDD 샘플코드를 테스트 해 보았다.
grails의 경우에는 도메인을 만들면 테스트 파일을 스캐폴딩을 통해 같이 만들어주는데,
아직 실무에서는 거의 쓰지 않고있어 성능 확인차, 그리고 TDD는 어떻게 진행되는건가 보고싶어 테스트를 진행했다.
TDD
TDD 실행 순서
1. Red: 실패하는 테스트를 먼저 작성한다
2. Green: 테스트를 통과시키기 위한 최소한의 코드를 작성
3. Refactor: 코드를 리팩터링하며 구조를 개선
생성한 파일
- Book.groovy
- BookService.groovy
- BookServiceSpec.groovy
Book.groovy
package test
class Book {
String title
Date dueDate
}
BookService.groovy
package test
class BookService {
static final BigDecimal LATE_FEE_PER_DAY = 1000
BigDecimal calculateLateFee(Book book){
def today = new Date()
def dueDate = book.dueDate
if(dueDate.before(today)){
def diffMillis = today.time - dueDate.time
def daysOverdue = (diffMillis / (1000 * 60 * 60 * 24)) as int
return daysOverdue * LATE_FEE_PER_DAY
} else {
return 0
}
}
}
BookServiceSpec.groovy 테스트 코드
package test
import spock.lang.Specification
import grails.test.mixin.TestFor
/**
* See the API for {@link grails.test.mixin.support.GrailsUnitTestMixin} for usage instructions
*/
@TestFor(BookService)
class BookServiceSpec extends Specification {
// @Before
def setup() { // 테스트 메서드 실행 전 초기화
}
// @After
def cleanup() { // 테스트 메서드 실행 후 정리
}
// @Test
void "should calculate late fee for overdue book"() {
// Arrange
given: "A book that is 5 days overdue"
def fiveDaysAgo = new Date() - 5
def book = new Book(title: "Clean Code", dueDate: fiveDaysAgo)
// Act
when: "We calculate the late fee"
def fee = service.calculateLateFee(book)
// Assert
then: "The fee should be 3000"
fee == 3000
}
}
Spock의 TDD 코드에서는 given / when / then 으로 명확하게 구분하여 상황을 부여한다.
우선은 Red Test를 진행한다. grails에서 해당 테스트를 진행할 때에는 Run/Debug Configurations에서
Command Line에 'test-app unit:' 을 작성하여 실행한다.
또는 이렇게 테스트 메서드의 왼쪽편에 있는 Run 버튼을 눌러도 되고!
Red 단계이기 때문에 Tests Failed가 보이면 성공한거다.
실패 로그
"C:\Program Files\java\jdk1.7.0_80\bin\java.exe" -Dgrails.home=C:\Users\admin\Desktop\grails-2.4.3 "-Dtools.jar=C:\Program Files\java\jdk1.7.0_80\lib\tools.jar" -Dgroovy.starter.conf=C:\Users\admin\Desktop\grails-2.4.3/conf/groovy-starter.conf -Dgrails.full.stacktrace=true -Xmx768M -Xms768M -XX:MaxPermSize=256m -XX:PermSize=256m -Djline.WindowsTerminal.directConsole=false -Dbase.dir=C:\Users\admin\Desktop\projects\happycode -Dgrails.build.listeners=org.jetbrains.groovy.grails.rt.GrailsIdeaTestListener -Dgrails.project.fork.test.debugArgs -Dfile.encoding=UTF-8 -classpath C:\Users\admin\Desktop\grails-2.4.3\lib\org.codehaus.groovy\groovy-all\jars\groovy-all-2.3.6.jar;C:\Users\admin\Desktop\grails-2.4.3\dist\grails-bootstrap-2.4.3.jar org.codehaus.groovy.grails.cli.support.GrailsStarter --classpath C:\Users\admin\AppData\Roaming\JetBrains\IntelliJIdea2022.3\plugins\groovy-grails\lib\groovy-grails-rt.jar --main org.codehaus.groovy.grails.cli.GrailsScriptRunner --conf C:\Users\admin\Desktop\grails-2.4.3/conf/groovy-starter.conf "test-app unit: \"test.BookServiceSpec.should calculate late fee for overdue book\" -echoOut -plain-output"
Testing started at AM 10:19 ...
|Loading Grails 2.4.3
|Configuring classpath
.
|Environment set to test
.........................................................
|Running without daemon...
.......................................................................
|Compiling 2 source files
.
|Running 2 unit tests...
|Running 2 unit tests... 1 of 2
--Output from should calculate late fee for overdue book--
Failure: |
should calculate late fee for overdue book(test.BookServiceSpec)
|
Condition not satisfied:
fee == 3000
| |
| false
5000
at test.BookServiceSpec.should calculate late fee for overdue book(BookServiceSpec.groovy:27)
Condition not satisfied:
fee == 3000
| |
| false
5000
Condition not satisfied:
fee == 3000
| |
| false
5000
at test.BookServiceSpec.should calculate late fee for overdue book(BookServiceSpec.groovy:27)
|Completed 1 unit test, 1 failed in 0m 2s
.Tests FAILED
|
- view reports in C:\Users\admin\Desktop\projects\happycode\target\test-reports
Error |
Forked Grails VM exited with error
Process finished with exit code 1
친절히 왜 틀렸는지까지 설명해준다.
수정 코드
class BookService {
static final BigDecimal LATE_FEE_PER_DAY = 600 // 1000 => 600으로 수정
BigDecimal calculateLateFee(Book book){
def today = new Date()
def dueDate = book.dueDate
if(dueDate.before(today)){
def diffMillis = today.time - dueDate.time
def daysOverdue = (diffMillis / (1000 * 60 * 60 * 24)) as int
return daysOverdue * LATE_FEE_PER_DAY
} else {
return 0
}
}
}
fee에서 틀렸기때문에, 오류를 수정하고 Green 테스트를 진행한다.
성공 로그
"C:\Program Files\java\jdk1.7.0_80\bin\java.exe" -Dgrails.home=C:\Users\admin\Desktop\grails-2.4.3 "-Dtools.jar=C:\Program Files\java\jdk1.7.0_80\lib\tools.jar" -Dgroovy.starter.conf=C:\Users\admin\Desktop\grails-2.4.3/conf/groovy-starter.conf -Dgrails.full.stacktrace=true -Xmx768M -Xms768M -XX:MaxPermSize=256m -XX:PermSize=256m -Djline.WindowsTerminal.directConsole=false -Dbase.dir=C:\Users\admin\Desktop\projects\happycode -Dgrails.build.listeners=org.jetbrains.groovy.grails.rt.GrailsIdeaTestListener -Dgrails.project.fork.test.debugArgs -Dfile.encoding=UTF-8 -classpath C:\Users\admin\Desktop\grails-2.4.3\lib\org.codehaus.groovy\groovy-all\jars\groovy-all-2.3.6.jar;C:\Users\admin\Desktop\grails-2.4.3\dist\grails-bootstrap-2.4.3.jar org.codehaus.groovy.grails.cli.support.GrailsStarter --classpath C:\Users\admin\AppData\Roaming\JetBrains\IntelliJIdea2022.3\plugins\groovy-grails\lib\groovy-grails-rt.jar --main org.codehaus.groovy.grails.cli.GrailsScriptRunner --conf C:\Users\admin\Desktop\grails-2.4.3/conf/groovy-starter.conf "test-app unit: \"test.BookServiceSpec.should calculate late fee for overdue book\" -echoOut -plain-output"
Testing started at AM 10:23 ...
|Loading Grails 2.4.3
|Configuring classpath
.
|Environment set to test
.......................
|Compiling 1 source files
..................................
|Running without daemon...
.......................................................................
|Compiling 1 source files
.
|Running 2 unit tests...
|Running 2 unit tests... 1 of 2
--Output from should calculate late fee for overdue book--
|Completed 1 unit test, 0 failed in 0m 2s
.
|Tests PASSED - view reports in C:\Users\admin\Desktop\projects\happycode\target\test-reports
Process finished with exit code 0
Tests PASSED가 나오면 Green 테스트 성공!
이후 코드를 약간씩 리팩토링해가면서 Tests Passed 를 계속 받는다면 Refactor 단계까지 Pass다!
참조:
https://jojoldu.tistory.com/228
Spock 소개 및 튜토리얼
안녕하세요? 이번 시간엔 spock 에 대해 소개하는 시간을 가지려고 합니다. 모든 코드는 Github에 있기 때문에 함께 보시면 더 이해하기 쉬우실 것 같습니다. (공부한 내용을 정리하는 Github와 세미
jojoldu.tistory.com
'TIL' 카테고리의 다른 글
주니어 개발자의 AI 바이브코딩, 학습과 자기효능감에 대해서 (0) | 2025.09.03 |
---|---|
[Linux] Fluentd 로그파일 자동 모니터링 스크립트 crontab 적용기 - 후기(2) (0) | 2025.08.01 |
[Linux] Fluentd 로그파일 자동 모니터링 스크립트 crontab 적용기 - 후기 (2) | 2025.07.30 |
[보안][Dreamhack] 워게임 Exercise: SSH 풀이 (feat.ssh -p 접속) (0) | 2025.07.29 |
[CI/CD] Jenkins + Bash로 Tomcat 배포 후 로그 자동 압축 파이프라인 구축기 (최종) (0) | 2025.07.03 |