前回は返金するテストを作ったところで終わっていたので、まずはテストを実行してみる。
すると、返金するテストでエラーになるので、そこから作業を再開すればいいことがわかる。
返金を実装する。
public int refund() {
int refund = total;
total = 0;
return refund;
}
扱えないお金
テストを書く。
@Test
void 投入できないお金() {
VendingMachine vm = new VendingMachine();
vm.put(1);
int total = vm.getTotal();
assertThat(total, is(0));
vm.put(5);
total = vm.getTotal();
assertThat(total, is(0));
vm.put(20);
total = vm.getTotal();
assertThat(total, is(0));
vm.put(5000);
total = vm.getTotal();
assertThat(total, is(0));
}
10円・50円・100円・500円・1000円だけ受け付けるようにすればよい。
public void put(int i) {
// 10円・50円・100円・500円・1000円だけ受け付ける
if (i == 10 ||
i == 50 ||
i == 100 ||
i == 500 ||
i == 1000) {
total += i;
}
}
ジュースの管理
テストを書く。
@Test
void ジュースを格納できる() {
VendingMachine vm = new VendingMachine();
String name = vm.getJuiceName();
assertThat(name, is("コーラ"));
int price = vm.getJuicePrice();
assertThat(price, is(120));
int stock = vm.getJuiceStock();
assertThat(stock, is(5));
}
このテストに関しては、fakeだけでテストにパスできる。
public String getJuiceName() {
return "コーラ";
}
public int getJuicePrice() {
return 120;
}
public int getJuiceStock() {
return 5;
}
ジュースを購入する。
テストを書く。
@Test
void ジュースを購入する() {
VendingMachine vm = new VendingMachine();
boolean b = vm.canBuy("コーラ");
assertThat(b, is(false));
vm.put(500);
b = vm.canBuy("コーラ");
assertThat(b, is(true));
}
テストにパスするように自動販売機を実装する。
public boolean canBuy(String name) {
return total >= getJuicePrice();
}
購入できるようにする。
@Test
void ジュースを購入する() {
VendingMachine vm = new VendingMachine();
boolean b = vm.canBuy("コーラ");
assertThat(b, is(false));
vm.put(500);
b = vm.canBuy("コーラ");
assertThat(b, is(true));
Juice juice = vm.buy("コーラ");
Juiceがないので新規にクラスを作成する。
package jp.abc;
public class Juice {
private String name;
private int price;
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;
}
}
Juiceを作ったので、テストの続きを作成する。
@Test
void ジュースを購入する() {
VendingMachine vm = new VendingMachine();
boolean b = vm.canBuy("コーラ");
assertThat(b, is(false));
vm.put(500);
b = vm.canBuy("コーラ");
assertThat(b, is(true));
Juice juice = vm.buy("コーラ");
assertThat(juice.getName(), is("コーラ"));
}
テストではジュースの名前だけチェックしているのでfakeで実装しておく。
public Juice buy(String name) {
Juice j = new Juice();
j.setName("コーラ");
return j;
}
ジュースを購入すると在庫を減らさないといけないのでテストを追加する。
@Test
void ジュースを購入する() {
VendingMachine vm = new VendingMachine();
boolean b = vm.canBuy("コーラ");
assertThat(b, is(false));
vm.put(500);
b = vm.canBuy("コーラ");
assertThat(b, is(true));
Juice juice = vm.buy("コーラ");
assertThat(juice.getName(), is("コーラ"));
int stock = vm.getJuiceStock();
assertThat(stock, is(4));
}
テストをパスするようにまじめに実装する。
Juiceクラスには、引数付きコンストラクタが欲しいので追加しておく。
既存のコードで引数なしのコンストラクタを使っているので引数なしのコンストラクタも定義しておく。
public Juice(String name, int price) {
this.name = name;
this.price = price;
}
public Juice() {
this("", 0);
}
package jp.abc;
import java.util.ArrayList;
import java.util.List;
public class VendingMachine {
private int total;
private List<Juice> juices = new ArrayList<>();
public VendingMachine() {
total = 0;
for (int i = 0; i < 5; i++) {
juices.add(new Juice("コーラ", 120));
}
}
public void put(int i) {
// 10円・50円・100円・500円・1000円だけ受け付ける
if (i == 10 ||
i == 50 ||
i == 100 ||
i == 500 ||
i == 1000) {
total += i;
}
}
public int getTotal() {
return total;
}
public int refund() {
int refund = total;
total = 0;
return refund;
}
public String getJuiceName() {
return "コーラ";
}
public int getJuicePrice() {
return 120;
}
public int getJuiceStock() {
return juices.size();
}
public boolean canBuy(String name) {
return total >= getJuicePrice();
}
public Juice buy(String name) {
Juice j = juices.remove(0);
return j;
}
}
ジュースを購入すると合計金額が減るのをテストに追加する。
@Test
void ジュースを購入する() {
VendingMachine vm = new VendingMachine();
boolean b = vm.canBuy("コーラ");
assertThat(b, is(false));
vm.put(500);
b = vm.canBuy("コーラ");
assertThat(b, is(true));
Juice juice = vm.buy("コーラ");
assertThat(juice.getName(), is("コーラ"));
int stock = vm.getJuiceStock();
assertThat(stock, is(4));
int total = vm.getTotal();
assertThat(total, is(380));
}
テストにパスするように実装する。
public Juice buy(String name) {
Juice j = juices.remove(0);
total -= j.getPrice();
return j;
}
投入金額が足りないときはジュースを購入できないテストを追加する。
@Test
void 金額不足でジュースを購入できない() {
VendingMachine vm = new VendingMachine();
Juice j = vm.buy("コーラ");
assertThat(j, is(nullValue()));
}
テストにパスするように実装する。
public Juice buy(String name) {
if (!canBuy(name)) return null;
Juice j = juices.remove(0);
total -= j.getPrice();
return j;
}
在庫がないときはジュースを購入できないテストを追加する。
@Test
void 在庫がないのでジュースを購入できない() {
VendingMachine vm = new VendingMachine();
vm.put(1000);
for (int i = 0; i < 5; i++) {
Juice j = vm.buy("コーラ");
assertThat(j.getName(), is("コーラ"));
}
Juice j = vm.buy("コーラ");
assertThat(j, is(nullValue()));
}
テストにパスするように実装する。
在庫が0なので購入できない。
public boolean canBuy(String name) {
if (juices.size() == 0) return false;
return total >= getJuicePrice();
}
売上金額を取得できるようにする。
まずはテストを作成する。
@Test
void 現在の売上金額を取得できる() {
VendingMachine vm = new VendingMachine();
int sales = vm.getSales();
assertThat(sales, is(0));
vm.put(1000);
Juice j = vm.buy("コーラ");
sales = vm.getSales();
assertThat(sales, is(120));
}
テストにパスするように実装する。
package jp.abc;
import java.util.ArrayList;
import java.util.List;
public class VendingMachine {
private int total;
private int sales;
private List<Juice> juices = new ArrayList<>();
public VendingMachine() {
total = 0;
for (int i = 0; i < 5; i++) {
juices.add(new Juice("コーラ", 120));
}
}
public void put(int i) {
// 10円・50円・100円・500円・1000円だけ受け付ける
if (i == 10 ||
i == 50 ||
i == 100 ||
i == 500 ||
i == 1000) {
total += i;
}
}
public int getTotal() {
return total;
}
public int refund() {
int refund = total;
total = 0;
return refund;
}
public String getJuiceName() {
return "コーラ";
}
public int getJuicePrice() {
return 120;
}
public int getJuiceStock() {
return juices.size();
}
public boolean canBuy(String name) {
if (juices.size() == 0) return false;
return total >= getJuicePrice();
}
public Juice buy(String name) {
if (!canBuy(name)) return null;
Juice j = juices.remove(0);
total -= j.getPrice();
sales += j.getPrice();
return j;
}
public int getSales() {
return sales;
}
}
返金操作で釣銭を返すテストを作成する。
@Test
void 返金操作で釣銭を返す() {
VendingMachine vm = new VendingMachine();
vm.put(1000);
Juice j = vm.buy("コーラ");
int refund = vm.refund();
assertThat(refund, is(880));
}
何も実装しないでもテストにパスした!!!!!!!
機能拡張する。
ジュースを3種類管理できるようにする。
@Test
void ジュースを3種類管理できる() {
VendingMachine vm = new VendingMachine();
vm.put(100);
boolean b = vm.canBuy("水");
assertThat(b, is(true));
b = vm.canBuy("コーラ");
assertThat(b, is(false));
b = vm.canBuy("レッドブル");
assertThat(b, is(false));
}