티스토리 뷰

테스트

테스트 주도 개발_5

Hilu 2023. 2. 12. 18:25

오늘은 10,11,12 장 내용을 다루어 보자!

 

10장. 흥미로운 발급 

 

책에서는 또 비유적으로 시간이라는 은유를 썻는데 나는 있는 그대로(?) 작성 하였다.

 

카드 수수료 (20%)
카드번호, 유효기간, 결제 금액 값 필요
card 부작용?
+ 수수료비율 필드 추가
+ 수수료금액 필드 추가
+ getChargeAmt 추가
equals()

hashCode()
chageAmt private 하게 만들기
계좌 수수료 (30%)
카드, 계좌 중복
공용 equals
공용 newIssuance
Card와 Account 비교 하기
newIssuance 신규 발급 추가
사용가능 국가

공용 newIssuance 로 중복 코드를 줄이자.

 

	Payment newIssuance(double chargeRate) {
		if (getClass().equals(Card.class)) {
			return Payment.card(chargeRate);
		} else if (getClass().equals(Account.class)){
			return Payment.account(chargeRate);
		} else {
			return null;
		}
	}

 

위 처럼 코드를 수정하고 테스트를 돌리면 승리의 초록색 막대가 나온다~! 오늘도 하나의 업적을 만들고 퇴근!

 


11장 모든 악의 근원

 

카드 수수료 (20%)
카드번호, 유효기간, 결제 금액 값 필요
card 부작용?
+ 수수료비율 필드 추가
+ 수수료금액 필드 추가
+ getChargeAmt 추가
equals()

hashCode()
chageAmt private 하게 만들기
계좌 수수료 (30%)
카드, 계좌 중복
공용 equals
공용 newIssuance
Card와 Account 비교 하기
newIssuance 신규 발급 추가
사용가능 국가

Paymt 에 두 하위 클래스에는 이제 생성자 밖에 없다.

 

package com.example.demo;

public class Card extends Payment{

	Card(double chargeRate, String country) {
		super(chargeRate, country);
	}
}
package com.example.demo;

public class Account extends Payment{

	Account(double chargeRate, String country) {
		super(chargeRate, country);
	}
}

 

생성자만 있는 하위 클레스는 필요가 없기 때문에, 삭제하도록 하자 삭제 가능하게 Payment 에 하위 클래스에 대한 참조를 상위 클래스에 대한 참조로 변경하자.

 

	static Payment card(double chargeRate) {
		return new Payment(chargeRate, "Korea");
	}

	static Payment account(double chargeRate) {
		return new Payment(chargeRate, "USA");
	}

 

이제 테스트 코드에서 Card, Account 에 대한 의존성을 지울 수 있다. 다음 으로 동치성 테스트가 충분히 되었는지 확인해 보자.

 

	@Test
	void equalsTest() {
		assertTrue(Payment.card(0.2).equals(Payment.card(0.2)));
		assertFalse(Payment.card(0.2).equals(Payment.card(0.3)));
		assertTrue(Payment.account(0.2).equals(Payment.account(0.2)));
		assertFalse(Payment.account(0.2).equals(Payment.account(0.3)));
		assertFalse(Payment.account(0.3).equals(Payment.card(0.3)));
	}

 

너무 과하게 테스트를 하고 있다. 첫번째, 두번째 assert 를 같은 의미 이므로 삭제하자.

 

	@Test
	void equalsTest() {
		assertTrue(Payment.account(0.2).equals(Payment.account(0.2)));
		assertFalse(Payment.account(0.2).equals(Payment.account(0.3)));
		assertFalse(Payment.account(0.3).equals(Payment.card(0.3)));
	}

 

1. 이번장에서는, 하위 클래스의 속을 들어내는 것을 완료 하고, 하위 클래스를 삭제하였다.

2. 기존 소스 구조에서는 필요 했지만 새로운 구조에서는 필요 없게 된 테스트를 제거 했다.

 


12장. 드디어, 복합 결제

 

요구 사항 항목이 너무 많다. 이쯤에서 한번 요구사항을 정리하고 진행하자.

 

카드 수수료(0.2) + 계좌 수수료(0.3) = 결제 금액 (복합결제가 가능 50대 50 으로만 결제 가능)

전체 복합결제 스토리를 한번에 다룰지 모르겠다. 

카드 수수료(0.2) + 계좌 수수료(0.3) = 결제 금액 (복합결제가 가능 50대 50 으로만 결제 가능)
카드 수수료(0.2) + 카드 수수료(0.3)

우선 같은 결제 수단에 대한 복합결제에서 시작해 보자.

 

복합결제에 대하여 테스트 코드를 만들고

	@Test
	public void testSimplePaymentAddition() {
		Payment add = Payment.card(0.2).add(Payment.card(0.3));
		assertEquals(Payment.card(0.25), add);
	}

Payment.card(0.25) 를 반환하는 식으로 가짜 구현 할 수도 있지만, 구현해야 할 상황이 명확 하므로 명확하게 구현한다.

 

	public Payment add(Payment addPayment) {
		return new Payment((this.chargeRate + addPayment.chargeRate) / 2, this.country);
	}

 

여기서 우리는 Card, Account 의 복합결제를 나타는데 이를 나타내는 Payment 객체를 만들 것이다.

 

이를 이해 하기 위해, 메타포를 아래와 같이 생각해 보도록 하겠다.

 

(Card 수수료 + 게좌 수수료) / 2 와 같은 수식어다.

 

여기서 연산의 결과로 Expression 들이 생기는데, 그중 하나는 합이 될 것이다. 

 

결제수수료를 이용해서 Expression 은 대표 결제 수단으로 축약할 수 있다.

 

이 메타포를 테스트에 적용해 보자.

 

	@Test
	public void testSimplePaymentAddition() {
    	...
		assertEquals(Payment.card(0.25), reduced);
	}

 

reduced(축약된)란 이름의 Expression은 Expression에 대표 결제수단을 적용함으로서 얻어진다. 

 

실세계에서 수수료가 적용되는 곳은 어디인가. 온라인 쇼핑몰 이라고 가정하자.

 

	@Test
	public void testSimplePaymentAddition() {
		...
        
		Payment reduced = onlineShoppingMall.reduce(representativePayment, "korea");
		assertEquals(Payment.card(0.25), reduced);
	}

 

OnlineShoppingMall 객체를 만들고 

 

	@Test
	public void testSimplePaymentAddition() {
		...
        
		OnlineShoppingMall onlineShoppingMall = new OnlineShoppingMall();
		Payment reduced = onlineShoppingMall.reduce(representativePayment, "korea");
		assertEquals(Payment.card(0.25), reduced);
	}

 

두 결제수단에서 대표결제수단을 구하는건 Expression 이다.

 

	@Test
	public void testSimplePaymentAddition() {
    	...
        
		Expression representativePayment = card.add(card);
		OnlineShoppingMall onlineShoppingMall = new OnlineShoppingMall();
		Payment reduced = onlineShoppingMall.reduce(representativePayment, "korea");
		assertEquals(Payment.card(0.25), reduced);
	}

 

card 를 만든다.

 

	@Test
	public void testSimplePaymentAddition() {
		...
		Payment card = Payment.card(0.25);
		Expression representativePayment = card.add(card);
		OnlineShoppingMall onlineShoppingMall = new OnlineShoppingMall();
		Payment reduced = onlineShoppingMall.reduce(representativePayment, "Korea");
		assertEquals(Payment.card(0.25), reduced);
	}

 

이제 컴파일 하려면 Expression 인터페이스가 필요하다. (class 도 좋지만 interface 가 더 가볍다.)

 

그리고 초록 막대가 나오도록 쭉 구현 하겠다.

 

초록 막대가 보인다.

 

 

이제 다음 장에서 리팩토링할 준비가 되었다. 다음장에서 부터 리팩토링을 진행 하겠다.

 

이 장에서 우리는 

 

1. 메타포들을 신중히 생각해 보았다.

2. 새 메타포에 기반하여 기존의 테스트를 재작성 하였다.

3. 큰 테스트를 작은 테스트로 줄여서 발전을 할 수 있도록 했다.

 

 

참고 : 테스트주도 개발 (켄트백)

'테스트' 카테고리의 다른 글

테스트 주도 개발 - TDD 마스터 하기  (0) 2023.03.19
테스트 주도 개발_6  (0) 2023.02.18
테스트 주도 개발_4  (0) 2023.02.12
테스트 주도개발_3  (0) 2023.02.12
테스트 주도개발_2  (0) 2023.02.11
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함