5月6日

自動販売機の在庫を取得するメソッドを追加する。

	@Test
	public void testStock() {
		VendingMachine vm = new VendingMachine();
		Stock s = vm.getStock();
	}

在庫を表現するクラス Stock を作成する。
まずは、名前・価格・在庫数を表すフィールドだけを用意する。

package tdd;

public class Stock {
	private String name;
	private int price;
	private int count;
}

Eclipseではgetter/setterを自動生成できる。
メニューから[ソース]-[getterおよびsetterの生成]を選択する。
ダイアログで「すべて選択」をクリックして全部のフィールドにチェックを入れる。
挿入ポイントは「最後のメンバー」を選択する。
「完了」すると、getter/setterが生成される。

package tdd;

public class Stock {
	private String name;
	private int price;
	private int count;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public int getCount() {
		return count;
	}
	public void setCount(int count) {
		this.count = count;
	}
}

自動販売機は初期状態で120円のコーラを5本保持しているので、それを確認するテストコードを作成する。

	@Test
	public void testStock() {
		VendingMachine vm = new VendingMachine();
		Stock s = vm.getStock();
		assertEquals(5, s.getCount());
		assertEquals("コーラ", s.getName());
		assertEquals(120, s.getPrice());
	}

そのテストをパスするようにVendingMachineを実装する。

	public Stock getStock() {
		Stock s = new Stock();
		s.setName("コーラ");
		s.setPrice(120);
		s.setCount(5);
		return s;
	}

テストにパスしたら、次のテストを実装する。
次は、購入可能かどうかを投入金額と在庫を元に取得できるようにする。
購入可能かどうかを調べるメソッドを isPurchasable() としてbooleanで結果を返すようにする。
自動販売機では、購入できることを示すランプに対応する。

	@Test
	public void testPurchasable() {
		VendingMachine vm = new VendingMachine();
		boolean b = vm.isPurchasable();
		assertEquals(false, b);
	}

VendingMachineにメソッドを追加する。
コンパイルエラーになっているうえにマウスカーソルを持っていくとメソッドを生成できる。

	public boolean isPurchasable() {
		return false;
	}

メソッドを生成するだけでテストにパスする。
500円を投入したら購入可能になるはずなので、それをテストに追加する。

	@Test
	public void testPurchasable() {
		VendingMachine vm = new VendingMachine();
		boolean b = vm.isPurchasable();
		assertEquals(false, b);
		vm.insert(500);
		b = vm.isPurchasable();
		assertEquals(true, b);
	}

テストがエラーになるので、テストにパスするように実装する。
投入済みの金額が120円以上ならtrueを返すようにする。

	public boolean isPurchasable() {
		if (amount >= 120) return true;
		return false;
	}

テストにパスするので、実際に購入する部分のテストを追加する。
purchase()メソッドで購入の操作を表現する。
購入するとコーラ(Coke)が出てくるはずなので、それをテストで表現する。

	@Test
	public void testPurchasable() {
		VendingMachine vm = new VendingMachine();
		boolean b = vm.isPurchasable();
		assertEquals(false, b);
		vm.insert(500);
		b = vm.isPurchasable();
		assertEquals(true, b);
		Coke c = vm.purchase();
		assertNotNull(c);
	}

Cokeクラスを作成し、purchase()メソッドでCokeのインスタンスを生成して返すようにする。

	public Coke purchase() {
		return new Coke();
	}

テストにパスするので、投入済みの金額が減ったことを確認するテストを追加する。

	@Test
	public void testPurchasable() {
		VendingMachine vm = new VendingMachine();
		boolean b = vm.isPurchasable();
		assertEquals(false, b);
		vm.insert(500);
		b = vm.isPurchasable();
		assertEquals(true, b);
		Coke c = vm.purchase();
		assertNotNull(c);
		int amount = vm.getAmount();
		assertEquals(500 - 120, amount);
	}

テストにパスするようにコードを実装する。

	public Coke purchase() {
		amount -= 120;
		return new Coke();
	}

次は、在庫が減ったことを確認するテストコードを追加する。

	@Test
	public void testPurchasable() {
		VendingMachine vm = new VendingMachine();
		boolean b = vm.isPurchasable();
		assertEquals(false, b);
		vm.insert(500);
		b = vm.isPurchasable();
		assertEquals(true, b);
		Coke c = vm.purchase();
		assertNotNull(c);
		int amount = vm.getAmount();
		assertEquals(500 - 120, amount);
		Stock s = vm.getStock();
		assertEquals(4, s.getCount());
	}

在庫を表す変数は、getStock()メソッドのローカル変数で宣言しているが、これをインスタンス変数に変更する。
コンストラクタ内で初期化する。

package tdd;

public class VendingMachine {
	private int amount = 0;
	private Stock stock;

	public VendingMachine() {
		stock = new Stock();
		stock.setCount(5);
		stock.setName("コーラ");
		stock.setPrice(120);
	}

getStock()メソッドは、インスタンス変数を返すように修正する。

	public Stock getStock() {
		return stock;
	}

購入操作で在庫を減らすコードを追加する。

	public Coke purchase() {
		amount -= 120;
		int c = stock.getCount();
		stock.setCount(c - 1);
		return new Coke();
	}

これでテストにパスする。
次は、売り上げ金額を確認するテストを追加する。
getSaleAmount()メソッドで売り上げ金額を取得できるようにする。

	@Test
	public void testPurchasable() {
		VendingMachine vm = new VendingMachine();
		boolean b = vm.isPurchasable();
		assertEquals(false, b);
		vm.insert(500);
		b = vm.isPurchasable();
		assertEquals(true, b);
		Coke c = vm.purchase();
		assertNotNull(c);
		int amount = vm.getAmount();
		assertEquals(500 - 120, amount);
		Stock s = vm.getStock();
		assertEquals(4, s.getCount());
		int sa = vm.getSaleAmount();
		assertEquals(120, sa);
	}

テストにパスするように実装する。

	public int getSaleAmount() {
		return 120;
	}

自動販売機のインスタンスを生成した直後は売り上げが0のはずなので、テストを追加する。

	@Test
	public void testPurchasable() {
		VendingMachine vm = new VendingMachine();
		int sa = vm.getSaleAmount();
		assertEquals(0, sa);
		boolean b = vm.isPurchasable();
		assertEquals(false, b);
		vm.insert(500);
		b = vm.isPurchasable();
		assertEquals(true, b);
		Coke c = vm.purchase();
		assertNotNull(c);
		int amount = vm.getAmount();
		assertEquals(500 - 120, amount);
		Stock s = vm.getStock();
		assertEquals(4, s.getCount());
		sa = vm.getSaleAmount();
		assertEquals(120, sa);
	}

テストにパスするように実装を修正する。
getSaleAmount()メソッドでは、インスタンス変数 saleAmount の値を返すようにする。
購入の操作の中で、投入金額を減らすと同時に売り上げ金額をプラスする。

package tdd;

public class VendingMachine {
	private int amount = 0;
	private int saleAmount = 0;
	private Stock stock;

	(略)

	public Coke purchase() {
		amount -= 120;
		saleAmount += 120;
		int c = stock.getCount();
		stock.setCount(c - 1);
		return new Coke();
	}

	public int getSaleAmount() {
		return saleAmount;
	}
}

「投入金額が足りない場合もしくは在庫がない場合、購入操作を行っても何もしない。」を実装するために、そのテストを追加する。
お金を入れていない状態では、purchase()メソッドを呼び出してもnullを返して、コーラが出てこないようにする。

	@Test
	public void testPurchase() {
		VendingMachine vm = new VendingMachine();
		Coke c = vm.purchase();
		assertNull(c);
	}

投入金額が120円未満の場合は購入できずにnullを返すようにする。

テストにパスしたら、在庫がない場合も購入できないようにするためのテストを追加する。

	@Test
	public void testPurchase() {
		VendingMachine vm = new VendingMachine();
		Coke c = vm.purchase();
		assertNull(c);
		vm.insert(1000);
		for (int i = 0; i < 5; i++) {
			c = vm.purchase();
			assertNotNull(c);
		}
		c = vm.purchase();
		assertNull(c);
	}
&#91;/java&#93;


VendingMachineに購入可能かどうかを調べるisPurchasable()メソッドがあるので、purchase()メソッド内でもそれを使うようにする。

&#91;java&#93;
	public Coke purchase() {
		if (!isPurchasable()) return null;
		amount -= 120;
		saleAmount += 120;
		int c = stock.getCount();
		stock.setCount(c - 1);
		return new Coke();
	}
&#91;/java&#93;

isPurchasable()メソッドで在庫を確認する。

&#91;java&#93;
	public boolean isPurchasable() {
		if (amount < 120) return false;
		if (stock.getCount() == 0) return false;
		return true;
	}
&#91;/java&#93;

これでテストにパスする。

次の機能拡張に挑戦する!



<blockquote>
ジュースを3種類管理できるようにする。
在庫にレッドブル(値段:200円、名前”レッドブル”)5本を追加する。
在庫に水(値段:100円、名前”水”)5本を追加する。
投入金額、在庫の点で購入可能なドリンクのリストを取得できる。
</blockquote>




	@Test
	public void test購入可能なドリンクのリストを取得() {
		VendingMachine vm = new VendingMachine();
		String[] names = vm.getPurchasableNames();
		assertEquals(0, names.length);
	}

コメントを残す

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