4장. 프라이버시
Dollar.times() 연산은
호출을 받은 객체의 값 * 인자로 받은 곱수
를 갖는 Dollar를 반환해야 함.
public void testMultiplication() {
Dollar five = new Dollar(5);
Dollar product = five.times(2);
assertEquals(10, product.amount);
product = five.times(3);
assertEquals(15, product.amount);
}
// 첫번째와 두번째 단언 assertion을 Dollar와 Dollar를 비교하는것으로 재작성
public void testMultiplication() {
Dollar five = new Dollar(5);
Dollar product = five.times(2);
assertEquals(new Dollar(10), product.amount);
product = five.times(3);
assertEquals(new Dollar(15), product.amount);
}
// 임시변수인 product는 쓸모없으니 인라인시키자.
public void testMultiplication() {
Dollar five = new Dollar(5);
assertEquals(new Dollar(10), five.times(2));
assertEquals(new Dollar(15), five.times(3));
}
이 테스트는 일련의 오퍼레이션이 아니라 참인 명제에 대한 단언들.
이제 Dollar의 amount 인스턴스 변수를 사용하는 코드는 Dollar 자신 밖에 없으므로
변수를 private 으로 변경가능.
할일목록 삭제 가능 amount를 private으로 만들자
- 오직 테스트를 향상시키기 위해서만 개발된 기능을 사용
- 두 테스트가 동시에 실패하면 망한다는 것을 인식
- 위험요소가 있음에도 계속 진행
- 테스트와 코드 사이의 결합도를 낮추기 위해, 테스트하는 객체의 새 기능을 사용.
5장. 솔직히 말하자면 Franc-ly Speaking
달러 대신 Franc을 표현할 수 있는 객체가 필요하다.
Dollar테스트를 복사한 후 수정해보자
public void testFrancMultiplication() {
Franc five = new Franc(5);
assertEquals(new Franc(10), five.times(2));
assertEquals(new Franc(15), five.times(3));
}
1. 테스트 작성.
2. 컴파일되게 하기.
3. 실패하는지 확인하기 위해 실행
4. 실행하게 만듦.
5. 중복 제거.
새 기능이 포함되면 속도를 위해
처음의 네 단계를 쉽게 뛰어넘도록 이미 진행된 것의 복붙을 용인할 것이다.
class Franc {
private int amount;
Franc(int amount) {
this.amount = amount;
}
Franc times(int multiplier) {
return new Franc(amount*multiplier);
}
public boolean equals(Object object) {
Franc franc = (Franc) object;
return amount == franc.amount;
}
}
중복이 많으므로 다음테스트 전에 이것을 제거해야한다.
할일 목록에 적어두자.
$5 + 10CHF = $10(환율이 2:1일 경우)
amount를 private으로 만들기
Money 반올림?
hashCode() Equal null Equal object
Dollar/Franc 중복 공용 equals 공용 times |
- 큰 테스트보다 진전을 나타내는 작은 테스트를 했다.
- 중복을 만들고 조금 고쳐 테스트를 작성함
- 일단 모델코드까지 복사 수정하여 테스트를 통과하게 했다.
- 이제 중복을 모두 고쳐야한다.
6장. 돌아온 '모두를 위한 평등 '
공동의 상위 클래스를 찾아내자
Dollar 와 Franc 상위로 Money 클래스를 만들고 공통의 equals 코드를 가지게 하자.
class Money{
protected int amount;
public boolean equals(Object object) {
Money money = (Money) object; // 변경
return amount == money.amount;
}
}
class Dollar extends Money{
}
적절한 테스트를 갖지 못한 코드에서 TDD를 해야 하는 경우가 종종 있을 것이다.(적어도 향후 십년정도는)
-> 이 부분에서 작가는 단순 테스트와 TDD하는것은 다르게 생각한다고 느꼈다.
public void testEquality() {
assertTrue(new Dollar(5).equals(new Dollar(5)));
assertFalse(new Dollar(5).equals(new Dollar(6)));
assertTrue(new Franc(5).equals(new Franc(5)));
assertFalse(new Franc(5).equals(new Franc(6)));
}
실제 통과할 테스트 부분을 위해 코드 리펙토링이 이루어지게 되는데
적절한 테스트가 아니면 테스트가 통과하더라도 리펙토링이 덜 이루어지게 되는것이다.
적절한 테스트를 잘 골라 작성하는것이 좋은 리펙토링 결과를 얻게 된다.
어떻게 하면 적절한 테스트를 잘 작성할 수 있을까?
Franc도 Dollar와 같이 고칠 수 있다.
$5 + 10CHF = $10(환율이 2:1일 경우)
amount를 private으로 만들기
Money 반올림?
hashCode() Equal null Equal object
Dollar/Franc 중복
공용 times Franc 과 Dollar 비교하기 |
- 공통된 코드를 첫 번째 클래스(Dollar)에서 상위 클래스(Money)로 단게적으로 옮김
- 두번째 클래스(Franc)도 Money 의 하위 클래스로 만듬.
- 불필요한 구현을 제거하기전에 두 equals() 구현을 일치시킴
'IT Book Summary > TDD' 카테고리의 다른 글
18장-20장 xUnit (0) | 2020.03.24 |
---|---|
13-17장 (0) | 2020.03.18 |
10-12장 (0) | 2020.03.10 |
7-10장 (0) | 2020.03.09 |
1-3장 (0) | 2020.02.25 |