종목 | 주 | 가격 | 합계 |
---|---|---|---|
IBM | 1000 | 25USD | 25000USD |
Novartis | 400 | 150CHF | 60000CHF |
합계 | 65000USD |
기준 | 변환 | 환율 |
---|---|---|
CHF | USD | 1.5 |
1.할일 목록을 작성한다.
2.작업을 시작한다.
3.작업을 마친다.
4.새로운 테스트를 할일 목록에 추가한다.
할일 목록
$5 + 10CHF = $10(환율이 2:1일 경우)
**$5 X 2 = $10****
→ 두번째 할일 목록부터 진행하겠다는 의미
테스트후 객체를 만든다.
테스트는 작은 것부터 시작한다.
테스트를 작성할 때는 오퍼레이션의 완벽한 인터페이스에 대해 상상해보는 것이 좋다.
우리는 지금 오퍼레이션이 외부에서 어떤 식으로 보일지에 대한 이야기를 테스트 코드에 적고 있는 것이다.
가능한 최선의 API에서 시작해서 거꾸로 작업하는 것이 애초부터 일을 복잡하고 보기 흉하며 '현실적'이게 하는 것 보다 낫다.
간단한 곱셈 예
public func testMultiplication() {
let five = Dollar(5)
five.times(2)
XCTAssertEqual(10, five.amount)
}
할일목록 갱신
$5 + 10CHF = $10(환율이 2:1일 경우)
**$5 X 2 = $10**
amount를 private으로 만들기
Dollar 부작용
Money 반올림?
- Dollar 클래스가 없음.
- 생성자가 없음.
- times(int) 메서드가 없음.
- amount 필드가 없음.
Dollar
class Dollar {
var amount: Int!
init(_ amount: Int) { }
func times(_ multiplier: Int) { }
}
class Dollar {
var amount: Int! = 10 //수정부분
init(_ amount: Int) {}
func times(_ multiplier: Int) {}
}
amount
를 수정하면 XCTAssertEqual(10, five.amount)
테스트는 성공한다.💡 의존성과 중복
스티브 프리만(Steve Freeman)은 테스트와 코드 간의 문제는 중복이 아님을 지적하였다. 문제는 테스트와 코드 사이에 존재하는 의존성이다. 즉, 코드나 테스트 중 한쪽을 수정하면 반드시 다른 한쪽도 수정해야만 한다는 것이다.
우리의 목표는 코드를 바꾸지 않으면서도 뭔가 의미 있는 테스트를 하나 더 작성하는 것인데, 현재의 구현으로는 불가능하다.
의존성은 소프트웨어 개발의 모든 부분에서 핵심적인 문제다. 만약 특정 데이터베이스 벤더가 제공하는 세세한 기능들을 코드 여기저기에서 사용하는 상황에서 다른 벤더의 제품으로 변경하고자 한다면 코드가 해당 벤더에 대해 의존성을 갖는다는 사실을 알게 될 것이다.
의존성이 문제 그 자체라면 중복(duplication)은 문제의 징후다. 중복의 가장 흔한 예는 로직의 중복이다. 중복된 로직이란 동일한 문장이 코드의 여러 장소에 나타나는 것을 의미한다. 중복된 로직을 하나로 끄집어내는 일엔 객체를 이용하는 것이 최고다.
문제 자체는 남겨둔 채로 징후만을 제거하면 다른 어딘가에서 최악의 형태로 문제가 드러나곤 하는 현실 세계의 일반적인 양상과는 달리, 프로그램에서는 중복만 제거해 주면 의존성도 제거된다. 이게 바로 TDD의 두번째 규칙이 존재하는 이유다. 다음 테스트로 진행하기 전에 중복을 제거함으로써, 오직 한 가지 (one and only one)의 코드 수정을 통해 다음 테스트도 통과하게 만들 가능성을 최대화하는 것이다.
지금까지 TDD 주기의 1번부터 4번 항목까지를 수행했으므로, 이제 중복을 제거할 차례다.
데이터도 중복으로 간주한다.
보통 중복을 찾기 위해 코드를 비교할 테지만, 이번 경우엔 중복이 '테스트에 있는 데이터'와 '코드에 있는 데이터' 사이에 존재한다.
class Dollar {
var amount = 5 * 2
}
amount = 10
을 amount = 5 * 2
로 수정하였다. (원래 10은 5와 2의 곱이니..)
테스트 코드에 보면 5와 2가 있고, Dollar 클래스에도 5와 2가 있으므로 중복되는 데이터가 된다.
중복을 제거해보자
```swift
class Dollar {
var amount: Int!
init(_ amount: Int) {}
func times(_ multiplier: Int) {
amount = 5 * 2 //수정부분
}
}
```
- 5와 2를 한 번에 제거할 수 있는 방법은 없지만, 객체의 초기화 단계에 있는 설정 코드를 `times()` 메서드 안으로 옮겨보자.
- 테스트는 통과될 것이고, 테스트 막대 역시 초록색이다.
- 이러한 단계가 작아보이지만 TDD의 핵심은 이런 작은 단계를 밟아야 한다는 것이 아니라, **이런 작은 단계를 밟을 능력을 갖추어야 한다는 것**이다.
```swift
class Dollar {
var amount: Int!
init(_ amount: Int) {
self.amount = amount //수정부분
}
func times(_ multiplier: Int) {
amount = amount * 2 //수정부분
}
}
```
- 5는 테스트 코드의 생성자에서 넘어오는 값이니 amount 변수에 저장해보자.
```swift
class Dollar {
var amount: Int!
init(_ amount: Int) {
self.amount = amount
}
func times(_ multiplier: Int) {
amount = amount * multiplier //수정부분
}
}
```
- 테스트 코드에서 인자 multiplier의 값이 2이므로, 상수를 이 인자로 대체할 수 있다.
```swift
class Dollar {
var amount: Int!
init(_ amount: Int) {
self.amount = amount
}
func times(_ multiplier: Int) {
amount *= multiplier //수정부분
}
}
```
- Dollar 클래스의 중복 제거를 위해 `amount = amount * multiplier`의 중복되는 부분도 제거하자
$5 + 10CHF = $10(환율이 2:1일 경우)
$5 X 2 = $10(완료)
amount를 private으로 만들기
Dollar 부작용
Money 반올림?