Notice
Recent Posts
Recent Comments
Link
«   2025/09   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

사적인 개발자

[TDD] Spock BDD test (feat.grails) 본문

TIL

[TDD] Spock BDD test (feat.grails)

DevYeri 2025. 8. 4. 19:56

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