테스트 주도 개발이라고 부릅니다.
반복 테스트를 이용한 소프트 웨어 방법론으로써 작은 단위의(Unit Test)테스트 케이스를 작성하고 이를 통과하는 코드를 추가하는 단계를 반복하며 구현합니다.
애자일 방법론 중 하나인 Test-First의 개념에 기반을 둡니다.
위의 그림은 TDD의 개발주기를 표현한 것입니다.
<Red>단계에서는 실패하는 테스트 코드를 먼저 작성한다.
<Green>단계에서는 테스트 코드를 성공시키기 위한 실제 코드를 작성한다.
<Yellow>단계에서는 중복 코드 제거, 일반화 등의 리팩토링을 수행한다.
중요한 것은 실패하는 테스트 코드를 작성할 때까지 실제 코드를 작성하지 않는 것과, 실패하는 테스트를 통과할 정도의 최소 실제 코드를 작성해야 하는 것이다. 이를 통해, 실제 코드에 대해 기대되는 바를 보다 명확하게 정의함으로써 불필요한 설계를 피할 수 있고, 정확한 요구 사항에 집중할 수 있다.
기존의 프로세스와 다릅니다.
기존의 프로세스는 디자인이 잡히면 코드개발을 진행하고 테스트를 진행합니다.
하지만 여기에서 디자인이 수정된다거나 클래스 단위의 개발을 진행하면서 개발자가 생소한 영역을 개발하게 된다면 설계를 처음부터 다시 진행해야 하는 일들이 발생합니다.
애자일 방법론을 따를 경우
해당 기획 , 디자인, 개발 방법에 대해서 불확실성이 높을 때 잦은 피드백과 협력이 중요하게 됩니다.
따라서 TDD와 애자일 방법론은 뗄수 없는 관계입니다.
행동 주도 개발이라는 의미로 사용자의 행위를 생각하며 테스트를 개발합니다.
BDD는 사실 TDD의 한 종류로 클라이언트 개발자들에게 좀 더 장점이 있는 개발 방법론입니다.
모듈, 메서드 위주의 TDD보다는 어떤 시나리오를 강조하기 때문입니다.
TDD를 하다보면 TestCase에 대한 유지보수, 일정의 압박, 예외케이스에 대해 매번 생각해야합니다.
하지만, 만약 기획이나 요구사항이 이미 작성되어 있다면 위와 같은 시간 비용이 줄어들게 될것입니다.
그렇다면 TDD,BDD 둘중 하나만 선택해서 개발자는 진행을 해야할까? 라는 의문이 생기게 됩니다.
하지만 이 둘은 분명 장단점이 극명하므로 상황에 맞추어 두가지를 골고루 사용해야할 것입니다.
프로젝트에서 BDD의 테스트 케이스로 시나리오에 대한 검증을 진행하고 시나리오에서 사용하는 각 모듈들은 TDD의 테스트케이스를 통하여 검증을 하는 방법을 진행해야 합니다.
예시)
Given >
"로그인 상태에서"
When >
"닉네임을 1글자만 작성"
"닉네임에 금칙어가 포함"
"닉네임에 특수문자 포함"
Then >
"경고문구를 '두글자 이상으로 작성'이라고 보여줌"
"경고문구를 '금칙어가 포함됨'이라고 보여줌"
"경고문구를 '특수문자가 포함됨'이라고 보여줌"
Given , When, Then으로 나누어 지는 Flow를 사용합니다.
class MyTests4 : BehaviorSpec({
given("100점이 만점인 상황에서") {
val totalMarks = 100
`when`("학생의 점수가") {
and("90점 이상이라면") {
val obtainedMarks = 99
then("등급은 A") { getGrade(obtainedMarks, totalMarks) shouldBe "A" }
}
and("80점 이상 90점 미만이라면") {
val obtainedMarks = 88
then("등급은 B") { getGrade(obtainedMarks, totalMarks) shouldBe "B" }
}
and("70점 이상 80점 미만이라면") {
val obtainedMarks = 77
then("등급은 C") { getGrade(obtainedMarks, totalMarks) shouldBe "C" }
}
and("60점 이상 70점 미만이라면") {
val obtainedMarks = 66
then("등급은 D") { getGrade(obtainedMarks, totalMarks) shouldBe "D" }
}
and("60점 미만이라면") {
val obtainedMarks = 34
then("등급은 F") { getGrade(obtainedMarks, totalMarks) shouldBe "F" }
}
}
}
})
fun getGrade(obtainedMarks: Int, totalMarks: Int): String {
val percentage = getPercentage(obtainedMarks, totalMarks)
return when {
percentage >= 90 -> "A"
percentage in 80..89 -> "B"
percentage in 70..79 -> "C"
percentage in 60..69 -> "D"
else -> "F"
}
}
private fun getPercentage(obtainedMarks: Int, totalMarks: Int): Int {
return (obtainedMarks / totalMarks.toFloat() * 100).roundToInt()
}
다만 BDD는 테스트 케이스를 만들어 줄 QA의 존재가 필요하며 기획자의 시나리오가 중요해집니다.
또한 BDD에 사용한 메서드에 대한 검증이 필요합니다.