java - TDD

yunzivv·2025년 3월 18일

JAVA 기초

목록 보기
21/23

TTD


오늘 intellij communitiy 버전에서 professional 버전으로 옮겼다. 이제부터 TDD를 도입하여 코드를 구현할 거라고 하셨고 TDD개발에 대해서 알아보는 시간도 가졌다.

TTD(Test-Driven Development)는 테스트 주도 개발을 뜻한다.
보통의 소프트웨어 개발 생명 주기 단계는 분석-설계-구현-테스트-유지보수의 단계로 이루어져 있다. 이 개발 방식의 단점은 코드를 전체 구현한 후 테스트를 수행하여 디버깅 시간이 오래걸리고, 기능의 추가가 어렵다는 것이다.

하지만 TDD를 도입하게 되면, 개발 주기를 짧게하고 지속적으로 테스트한다. 이를 통해 재설계의 필요성이 줄어들게 되고 보통 개발 방식의 단점을 극복할 수 있다.

TDD개발을 구글링하면서 설명을 읽는데 애자일 개발 모형이 생각났다. 실제로 TDD방법론이 애자일 모형에서 파생되었다는 것도 알게 됐다. 자격증 공부할 때는 그냥 그렇구나만 했다가 TDD방법론을 직접 사용해보고 애자일에서 파생되었다고 하니 더 이해가 잘 된 것 같다. TDD


1. TDD 단계


일반적인 방식과의 차이점은 테스트 코드를 작성한 뒤에 실제 코드를 구현하는 것이다.

1. Red 단계
- 실패하는 테스트 코드를 먼저 작성한다.
2. Green 단계
- 테스트 코드를 성공시키기 위한 실제 코드를 작성한다.
- 완벽한 코드보단 최대한 빠르게 작업하는 것을 1순위로 작업한다.
3. Blue 단계
- 중복 코드의 제거, 일반화 등 코드를 리팩토링한다.

개발 주기를 짧게하여 유닛테스팅을하 고 위 3단계를 계속 반복한다.
3단계를 수행하기 위해 프로그래밍 목적을 미리 정의 하고, 무엇을 테스트 할 지 미리 테스트 케이스를 작성해야만 한다.


좋은 테스트의 규칙 FIRST

Fast: 테스트는 빠르게 동작하여 자주 돌릴 수 있어야 한다.
Independent: 각각의 테스트는 독립적이며 서로 의존해서는 안된다.
Repeatable: 어느 환경에서도 반복 가능해야 한다.
Self-Validating: 테스트 결과를 boolean 값으로 결과를 내어 자체적으로 검증되어야 한다.
Timely: 테스트는 적시에 즉, 테스트하려는 실제 코드를 구현하기 직전에 구현해야 한다.


2. AssertThat


AssertThat메서드를 활용해 TDD개발을 할 수 있다. 이 메서드는 출력문을 사용하지 않고 테스트 케이스를 검사할 수 있도록 도와준다.

AssertJ를 정적(static) import하면 클래스 이름없이 바로 사용할 수 있다.
import static org.assertj.core.api.Assertions.assertThat;
패키지.클래스.* 형식으로 클래스의 모든 정적 멤버에 접근할 수 있지만 이는 권장되지 않는다고 한다. (공식가이드 : 정적 멤버가 어느 클래스에서 왔는지 알 수 없습니다. 클래스에서 모든 정적 멤버를 가져오는 것은 특히 가독성에 해로울 수 있습니다. 하나 또는 두 개의 멤버만 필요한 경우 개별적으로 가져오세요.)

AssertJ의 메서드는 사용자가 테스트 중 필요하다고 생각하는 거의 모든 메서드를 갖고 있다.

  • 예시
  1. assertEquals(기대값, 실제값): 실제값(actual)이 기대값(expected)과 내용이 같은지 검증한다.
  2. assertThat(실제값).isEqualTo(기대값): 실제값(actual)이 기대값(expected)과 내용이 같은지 검증한다.

3. TDD개발 적용


TDD개발론을 적용해서 다항식 문자열을 입력 받아 연산하여 결과를 반환하는 클래스를 구현했다.
아래는 내가 오늘 AssertThat메서드를 활용하여 TDD개발 방법론을 적용한 순서다.

  1. 테스트 케이스를 작성한다.
  2. 테스트 코드를 작성한다. 중요한 점은 테스트 코드만 통과하는 코드로 작성해도 된다는 것이다.
  3. 테스트 코드를 통과하면 실패할 테스트 케이스를 작성한다.
  4. 테스트 케이스 전체를 통과하기 위해 코드를 추가하거나 수정한다.
  5. 중복 코드와 불필요한 코드를 정리하여 코드를 간략화한다.
  6. 위 단계를 계속 반복한다.
  7. 개발 단계에서 마주칠 수 있는 모든 테스트 케이스를 통과하면 실제 코드로 작성한다.
1. `3 * 1 + (1 - (4 * 1 - (1 - 1)))`를 계산할 수 있는 계산기 만들기를 목표로 설정
2. `1 + 1`을 입력하면 `2`를 출력하도록 테스트 케이스 작성하고 코드 구현
3. `2 + 1`입력 -> `3` 출력하고 이전 테스트 케이스에 영향이 없도록 코드 수정
4. `50 - 30`입력 -> `20` 출력 '''
5. `10 - 20 + 30`입력 -> `20` 출력 '''
6. 중복 코드 제거
7.  `10 - 10 - 10 - 10 + 10 + 10 - 10` 입력 -> `-10` 출력 '''
8.  `10 * 10 * 10 ` 입력 -> `1000` 출력 '''
⋮

이런식으로 목표를 조금씩 키우는 테스트 케이스 18개를 만들고 나서야 목표한 3 * 1 + (1 - (4 * 1 - (1 - 1))) 문자열을 연산할 수 있었다.

실제로 적용해보니 어려움이 살짝 있었다. 새로운 테스트 케이스만 통과하면 되는데 그 이상을 자꾸 생각하게 되었다. 이런 문제 때문에 실제로 적용하기 어렵다고 한 건가 싶었다. 지금도 바로 적용을 못했는데 나중에 일반적인 개발 주기가 익숙해진다면 더 어려워질 것이다. 꾸준히 연습해서 TDD개발을 진짜 빠르게 할 수 있는 사람이 되고 싶다.



참고 자료


AssertJ

0개의 댓글