STS 4.0.1(스프링 부트)에서
TDD(테스트 주도 개발 Test Driven Development) 실습하기
테스트 주도 개발 TDD 라는 책을 읽었었다.
뭐 이것도 작년이지만.. 이제야 포스팅을 해본다. 일단 JAVA 부분만 포스팅을 해보고자 한다. 생각보다 짧아서 다른 포스팅과 동시에 작성해도 무리는 없어 보인다.
책의 내용은 한 회사에서 보유한 프로그램 와이캐시 WhyCash에 대해 의뢰인으로부터 일부 기능(다중 통화 기능적용)에 대한 수정을 요청받는 가상의 사건이 있고 그 프로젝트를 수행하기 위해 TDD를 적용하여 개선해가는 과정을 다루고 있다.
자, 이제 시작해보겠다. 아, 나의 TDD 테스트 환경은 아래와 같다.
- OS : mac
- STS : 4.0.1
- Build : gradle
- frame-work : JUnit
1. ~에서 저자는 다음과 같은 미묘한 농담을 던진다. 당신이 천재라면 당신에게 이런 법칙은 필요 없다. 또 당신이 멍청이라면 역시 이런 법칙이 도움이 되지 않을 것이다. 그 사이에 존재하는 대다수의 사람들은 다음 두 가지 단순한 법칙을 따름으로써 잠재력을 한껏 발휘할 수 있을 것이다. - 어떤 코드건 작성하기 전에 실패하는 자동화된 테스트를 작성하라. - 중복을 제거하라. 2. 예제에 앞서 예제의 목적은 테스트 주도 개발의 리듬을 보도록 하는 데 있다고 한다. 1. 재빨리 테스트를 하나 추가한다. 2. 모든 체스트를 실행하고 새로 추가한 것이 실패하는 지 확인한다 3. 코드를 조금 바꾼다. 4. 모든 테스트를 실행하고 전부 성공하는지 확인한다. 5. 리팩토링을 통해 중복을 제거한다. 1+ 관련 참고 블로그
|
2) 세팅 값 입력, 개인적으로는 그래들을 선택했다.
3) 개인적으로 이 부분의 옵션은 아무것도 선택하지 않았다.
2. 프로젝트가 생성되었으면
1) TEST 하위폴더에 있는 Test.class를 열어보자
2) 1차 요구사항은 다름과 같다.
$5 + 10CHF = $10 (환율이 2:1일 경우) $5 x 2 = $10 <-- 부터 해결해 보자, amount를 private로 만들기 Dollar 부작용(side effect)? Money 반올림? |
코드는 간단한 곱셈의 예이다. <-- 아래 코드가 디버그와 리팩토링 시작의 첫 기준이 됩니다.
public class TddStudy2019ApplicationTests {
@Test
public void testMultiplication() {
Dollar five = new Dollar(5);
five.times(2);
assertEquals(10,five.amount);
}
}
(1) 첫 예제를 작성하여 Run As > JUnit 을 구동시키면 중간에 에러 팝업이 뜨는데 무시해도 좋다. Dollar 클래스 선언이 안되어 있어서 그렇다. 일단 테스트하고 에러를 확인하게되면 그 뒤에 해결할 예정이다. 일종의 TDD의 과정으로 봐도 무관하다.
(2) 빨간 줄이 나타난다. 구동 결과는 예상했던 바와 같이 에러이다. 우하단에 있는 에러 메시지를 확인해보자.
- Doller class가 없음
2) 에러 메시지를 반영하여 코드를 개선해보자.
(1) 일단 가볍게 Doller를 inner class로 선언해보았다.
public class TddStudy2019ApplicationTests {
@Test
public void testMultiplication() {
Dollar five = new Dollar(5);
five.times(2);
assertEquals(10,five.amount);
}
}
class Dollar{
}
(2) 다시 빨간 줄이 나타난다. 이번엔 에러 메시지가 바뀌었다. 그리고 본문 코드에 뭔가 빨간 줄들이 추가되었다. 하지만 걱정하지 말자. 그만큼 개선할 대상이 명확해졌음을 의미한다.
- 생성자가 없음 The constructor Dollar(int) is undefined
- times(int) 메서드가 없음 The method times(int) is undefined for the type Dollar
- amount 필드가 없음 amount cannot be resolved or is not a field
3) 변경된 에러 메시지를 반영하여
(1) 다시 코드를 개선해보았다.
- 생성자를 만들고 Dollar(int amount),
- times(int) 메서드를 만들고 times(int multiplier), <-- 책에서는 times() 스텁을 구현한다. 라고 표현했다. 2+ 관련 내용 링크
- amount 필드 int amount =10;를 추가했다.
public class TddStudy2019ApplicationTests {
@Test
public void testMultiplication() {
Dollar five = new Dollar(5);
five.times(2);
assertEquals(10,five.amount);
}
}
class Dollar{
Dollar(int amount){
}
void times(int multiplier) {
}
int amount =10;
}
3. 첫 예제가 성공했다.
1) 하지만 개선해야 할 사항이 많다. 이는 마치 얼마 전에 포스팅 한 스프링 부트에서 토비 3.1 따라하기 : 1장 - 1.1 초난감 DAO 에서의 첫 예제와 동일한 맥락이다. 일단 돌아가게 하고 코드를 개선해가는 과정이 앞으로의 책 전반의 진행 방향이다.
2) 테스트를 계속 진행하기 전에 일반화해야하는 주기. 잊지 말 것.
(1) 작은 테스트를 하나 추가한다 완료
(2) 모든 테스트를 실행해서 테스트가 실패하는 것을 확인한다 완료
(3) 조금 수정한다 완료
(4) 모든 테스트를 실행해서 테스트가 성공하는 것을 확인한다 완료
(5) 중복을 제거하기 위해 리팩토링을 한다.
의존성이 문제라면 중복 duplicarion은 문제의 징후이다.문제 자체는 남겨둔 채로 징후만 제거하면 다른 어딘가에서 최악의 형태로 문제가 드러나는 현실과 달리 프로그램에서는 중복만 제거하면 의존성도 제거된다. 다음 테스트로 진행하기 전에 중복을 제거함으로써 오직 한가지 one and only one의 코드 수정을 통해 다음 테스트도 통과되게 만들 가능성을 최대하기 위함이다.
4. 리팩토링. 이제 중복을 제거할 차례이다.
1) 그럼 뭘 조정할 수 있을까요? 사실상 첫 예제는 저자가 독자의 이해와 이야기 전개를 위한 상황극이다보니 코드가 조금 이상? 했습니다. 물론 그 이상한 점들을 개선하는 과정이 책 내용이니까 너무 시니컬하게 받아들이지는 마시고욥 >< 여하튼, 위의 예제는 사실 아래 내용과 동일합니다.
캡쳐사진에서는 amount가 이미 10 이니, 불필요해보이는(또는 헷갈리는) 매서드의 인자 값을 먼저 제거해봤습니다. 그러면 assertEquals(10, amount);와 같은 결과가 나온거죠. 이렇게 중복을 없애도 돌아가네요.
다만, 상황극 상 5달러를 두번 곱해야하는 상황을 먼저 테스트 하고 그 테스트를 일단 돌아가게 하느라 예제와 같은 코드가 나온거죠. 어찌보면 캡쳐에 있는 코드가 더 맞는 코드 같지만 현실세계에서 이와같은 요구사항은 있을 수 없겠죠, 말그대로 그래서 저자는 예제와 같은 코드를 작성한 것이 아닌가 생각됩니다. 따라서 위에 기재한 '<-- 아래 코드가 디버그와 리팩토링 시작의 첫 기준이 됩니다.' 에서 가르키는 코드를 기준으로 개선해나가면 될 것 같다.
2) 위 내용을 전재로, 먼저 int amount = 10; 를 amount = 5 * 2; 로 조정할 수 있을 것 같습니다.
class Dollar{
int amount;
Dollar(int amount){
}
void times(int multiplier) {
amount = 5 * 2;
}
}
3) 그리고 나머지도 아래와 같이 수정할 수 있을 것 같습니다. 결과는 '2), 3)' 모두 녹색바 입니다.
class Dollar{
int amount;
Dollar(int amount){
this.amount = amount;
}
void times(int multiplier) {
amount = amount * multiplier;
}
}
4) 이렇게 해서 테스트 주기를 한 바퀴 돌릴 수 있었습니다.
(1) 작은 테스트를 하나 추가한다 완료
(2) 모든 테스트를 실행해서 테스트가 실패하는 것을 확인한다 완료
(3) 조금 수정한다 완료
(4) 모든 테스트를 실행해서 테스트가 성공하는 것을 확인한다 완료
(5) 중복을 제거하기 위해 리팩토링을 한다. 완료
'새로워지기 > 서른의 생활코딩' 카테고리의 다른 글
스프링 부트에서 테스트 주도 개발 실습 - 2장. 타락한 객체 (0) | 2019.02.19 |
---|---|
스프링 부트에서 토비 3.1 따라하기 : 1장 - 1.1 초난감 DAO (0) | 2019.02.17 |
삼팔광땡~ MYSQL 입문기 08 - 관계형 모델, 정규화, 테이블 설계, 트랜젝션 (0) | 2019.02.15 |
삼팔광땡~ MYSQL 입문기 07 - 복수의 테이블 다루기 (0) | 2019.02.13 |
삼팔광땡~ MYSQL 입문기 06 - 데이터베이스 객체, 스키마, 테이블 관리(create, insert, alter, drop), ALTER DEFAULT 설정, INDEX, EXPLAIN, VIEW (0) | 2019.02.13 |
댓글