5月29日

テスト駆動開発で自動販売機を作る

例題はこちら⇒ TDDBC大阪

売上高を取得できるようにする

VendingMachineTest.java

	@Test
	public void testSale() {
		VendingMachine vm = new VendingMachine();
		int sale = vm.getSale();
		assertThat(sale, is(0));
		vm.throwInto(500);
		vm.purchace();
		sale = vm.getSale();
		assertThat(sale, is(120));
	}

売上高をインスタンス変数で保持する。
VendingMachine.java

public class VendingMachine {
	private int total = 0;
	private int stock = 5;
	private int sale = 0;

購入操作をしたときに売上高を増やし、そのインスタンス変数の値を返すようにする。
VendingMachine.java

	public Output purchace() {
		if (!isPurchacable()) {
			return new Output(0, 0);
		}
		total -= getJuicePrice();
		int change = total;
		total -= change;
		stock--;
		sale += getJuicePrice();
		return new Output(1, change);
	}

	public int getSale() {
		return sale;
	}

釣り銭を管理する

初期状態では、10円、50円、100円、500円の硬貨が、各10枚ずつ用意されている。

VendingMachineTest.java

	@Test
	public void testChangeStock() {
		VendingMachine vm = new VendingMachine();
		int s10 = vm.get10YenStock();
		assertThat(s10, is(10));
		int s50 = vm.get50YenStock();
		assertThat(s50, is(10));
		int s100 = vm.get100YenStock();
		assertThat(s100, is(10));
		int s500 = vm.get500YenStock();
		assertThat(s500, is(10));
	}

このテストにパスするコードを書く。
VendingMachine.java

	public int get10YenStock() {
		return 10;
	}

	public int get50YenStock() {
		return 10;
	}

	public int get100YenStock() {
		return 10;
	}

	public int get500YenStock() {
		return 10;
	}

150円を投入してジュースを買ったら、10円の釣り銭ストックが減る。
VendingMachineTest.java

	@Test
	public void testChangeStock() {
		VendingMachine vm = new VendingMachine();
		int s10 = vm.get10YenStock();
		assertThat(s10, is(10));
		int s50 = vm.get50YenStock();
		assertThat(s50, is(10));
		int s100 = vm.get100YenStock();
		assertThat(s100, is(10));
		int s500 = vm.get500YenStock();
		assertThat(s500, is(10));
		vm.throwInto(100);
		vm.throwInto(50);
		Output o = vm.purchace();
		s10 = vm.get10YenStock();
		assertThat(s10, is(7));
	}

購入するところで釣り銭のストックを減らす。
1回の購入なら残り7になるので、Fakeコードで実装する。

VendingMachine.java

	public Output purchace() {
		if (!isPurchacable()) {
			return new Output(0, 0);
		}
		total -= getJuicePrice();
		int change = total;
		decreaseStock(change);
		total -= change;
		stock--;
		sale += getJuicePrice();
		return new Output(1, change);
	}

	private void decreaseStock(int change) {
		stock10yen = 7;
	}

テストに2回目の購入を追加して、Fakeコードではテストにパスしないようにする。
VendingMachineTest.java

	@Test
	public void testChangeStock2() {
		VendingMachine vm = new VendingMachine();
		vm.throwInto(100);
		vm.throwInto(50);
		Output o = vm.purchace();
		assertThat(o.getJuiceCount(), is(1));
		assertThat(o.getChange(), is(30));
		int s10 = vm.get10YenStock();
		assertThat(s10, is(7));

		vm.throwInto(100);
		vm.throwInto(50);
		vm.purchace();
		s10 = vm.get10YenStock();
		assertThat(s10, is(4));
	}

お釣りに出す枚数だけ減らすように実装を修正する。
VendingMachine.java

	private void decreaseStock(int change) {
		stock10yen -= change / 10;
	}

200円を入れて購入したときのテストを用意する。
VendingMachineTest.java

	@Test
	public void testChangeStock3() {
		VendingMachine vm = new VendingMachine();
		vm.throwInto(100);
		vm.throwInto(100);
		vm.purchace();
		int s10 = vm.get10YenStock();
		assertThat(s10, is(7));
		int s50 = vm.get50YenStock();
		assertThat(s50, is(9));
	}

200円のテストにパスするコードを書く。
VendingMachine.java

	private void decreaseStock(int change) {
		if (change >= 50) {
			change -= 50;
			stock50yen--;
		}
		stock10yen -= change / 10;
	}

500円を入れて購入したときのテストを用意する。
VendingMachineTest.java

	@Test
	public void testChangeStock4() {
		VendingMachine vm = new VendingMachine();
		vm.throwInto(500);
		vm.purchace();
		int s10 = vm.get10YenStock();
		assertThat(s10, is(7));
		int s50 = vm.get50YenStock();
		assertThat(s50, is(9));
		int s100 = vm.get100YenStock();
		assertThat(s100, is(7));
	}

500円のテストにパスするコードを書く。
VendingMachine.java

	private void decreaseStock(int change) {
		if (change >= 100) {
			int c = change / 100;
			change -= c * 100;
			stock100yen -= c;
		}
		if (change >= 50) {
			change -= 50;
			stock50yen--;
		}
		stock10yen -= change / 10;
	}

1000円を入れて購入したときのテストを用意する。
VendingMachineTest.java

	@Test
	public void testChangeStock5() {
		VendingMachine vm = new VendingMachine();
		vm.throwInto(1000);
		vm.purchace();
		int s10 = vm.get10YenStock();
		assertThat(s10, is(7));
		int s50 = vm.get50YenStock();
		assertThat(s50, is(9));
		int s100 = vm.get100YenStock();
		assertThat(s100, is(7));
		int s500 = vm.get500YenStock();
		assertThat(s500, is(9));
	}

1000円のテストにパスするコードを書く。
VendingMachine.java

	private void decreaseStock(int change) {
		if (change >= 500) {
			change -= 500;
			stock500yen--;
		}
		if (change >= 100) {
			int c = change / 100;
			change -= c * 100;
			stock100yen -= c;
		}
		if (change >= 50) {
			change -= 50;
			stock50yen--;
		}
		stock10yen -= change / 10;
	}

10円玉の釣り銭を使い果たすテストを用意する。

VendingMachineTest.java

	@Test
	public void testChangeStock6() {
		VendingMachine vm = new VendingMachine();
		for (int i = 0; i < 3; i++) {
			vm.throwInto(100);
			vm.throwInto(50);
			vm.purchace();
		}
		int s10 = vm.get10YenStock();
		assertThat(s10, is(1));
		vm.throwInto(100);
		vm.throwInto(50);
		Output o = vm.purchace();
		s10 = vm.get10YenStock();
		assertThat(s10, is(1));
		assertThat(o.getJuiceCount(), is(0));
		assertThat(o.getChange(), is(0));
		int total = vm.getTotal();
		assertThat(total, is(150));
	}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です