5月25日

投稿者: | 2020年5月25日

MusicPlayerのテストを追加する。

以下のテストコードを追加する。

	@Test
	void 新規プレイリストに音楽を追加する() {
		MusicPlayer mp = new MusicPlayer();
		mp.addMusicToPlayList("お気に入り", "Official髭男dism", "パラボラ");
		int n = mp.countMusic();
		assertEquals(1, n);
		n = mp.countPlayList();
		assertEquals(1, n);
		PlayList p = mp.getPlayList(0);
		assertNotNull(p);
		assertEquals("お気に入り", p.getName());
		Music m = p.getMusic(0);
		assertEquals("パラボラ", m.getTitle());
	}

音楽プレイヤーの新しい機能を思いつかないので、別の課題にすすみましょう。

自動販売機クラス

TDDBC大阪の課題として出された自動販売機をやってみましょう。

TDD Boot Camp 大阪 2.0/課題( #tddbc )

新規Javaプロジェクト「vendingmachine」を作成する。
vendingmachineプロジェクトに VendingMachineクラスを作成する。

package jp.abc;

/**
 * 自動販売機クラス
 * @author satoshis
 *
 */
public class VendingMachine {

}

まずは「お金を投入する」機能を追加する。
投入するだけではどうなっているのかがわからないので、投入済みの金額を取得できるようにする。

package jp.abc;

/**
 * 自動販売機クラス
 * @author satoshis
 *
 */
public class VendingMachine {

	public void put(int i) {

	}

	public int entered() {
		return 0;
	}

}
package jp.abc;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class VendingMachineTest {

	@Test
	void お金を投入する() {
		VendingMachine vm = new VendingMachine();
		vm.put(10);
		int m = vm.entered();
		assertEquals(10, m);
	}

}

10円投入後に50円を投入する動作をテストで作ってみる。

	@Test
	void お金を投入する() {
		VendingMachine vm = new VendingMachine();
		vm.put(10);
		int m = vm.entered();
		assertEquals(10, m);
		vm.put(50);
		m = vm.entered();
		assertEquals(60, m);
	}

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

package jp.abc;

/**
 * 自動販売機クラス
 * @author satoshis
 *
 */
public class VendingMachine {

	private int total = 0;

	public void put(int money) {
		total += money;
	}

	public int entered() {
		return total;
	}

}

次の課題として、お金を払い戻す機能を追加する。
そのために、テストを作成する。

	@Test
	void お金を払い戻す() {
		VendingMachine vm = new VendingMachine();
		vm.put(500);
		int m = vm.entered();
		assertEquals(500, m);
		m = vm.refund();
		assertEquals(500, m);
	}

コンパイルエラーを解消するために、VendingMachineクラスにrefund()メソッドを追加する。

package jp.abc;

/**
 * 自動販売機クラス
 * @author satoshis
 *
 */
public class VendingMachine {

	private int total = 0;

	public void put(int money) {
		total += money;
	}

	public int entered() {
		return total;
	}

	public int refund() {
		return 0;
	}

}

fakeでテストにパスさせる。

	public int refund() {
		return 500;
	}

テストを追加する。
払い戻し後は投入金額が0円になる。

	@Test
	void お金を払い戻す() {
		VendingMachine vm = new VendingMachine();
		vm.put(500);
		int m = vm.entered();
		assertEquals(500, m);
		m = vm.refund();
		assertEquals(500, m);
		m = vm.entered();
		assertEquals(0, m);
	}

テストにパスするように自動販売機クラスを修正する。

	public int refund() {
		total = 0;
		return 500;
	}

テスト駆動開発のススメ方。

  1. 新しい機能に対するテストを作る→コンパイルエラーになる
  2. 新しいメソッドを作ってコンパイルエラーを解消する
  3. コンパイルエラーを解消できたらテストを実行する→エラーになる
  4. Fakeの実装でテストをパスさせる
  5. Fakeではパスできないテストを追加する→エラーになる
  6. 追加したテストにもパスするように修正する→パスする

お金を払い戻すテストに2回めのお金の投入と払い戻しを行う。

	@Test
	void お金を払い戻す() {
		VendingMachine vm = new VendingMachine();
		vm.put(500);
		int m = vm.entered();
		assertEquals(500, m);
		m = vm.refund();
		assertEquals(500, m);
		m = vm.entered();
		assertEquals(0, m);
		vm.put(100);
		m = vm.entered();
		assertEquals(100, m);
		m = vm.refund();
		assertEquals(100, m);
	}

テストがエラーに鳴るので、refund()メソッドを修正する。

	public int refund() {
		int r = total;
		total = 0;
		return r;
	}

ステップ1

想定外のお金が投入されたら、投入金額に加算せずにそのまま払い戻す。
テストを追加する。

	@Test
	void 想定外のお金を投入() {
		VendingMachine vm = new VendingMachine();
		vm.put(5);
		int m = vm.entered();
		assertEquals(0, m);
	}

1円から10000円までの全部をテストするコードを追加する。

	@Test
	void 想定外のお金を投入() {
		VendingMachine vm = new VendingMachine();
		vm.put(5);
		int m = vm.entered();
		assertEquals(0, m);
		vm.put(1);
		m = vm.entered();
		assertEquals(0, m);
		for (int i = 1; i <= 10000; i++) {
			vm.put(i);
			m = vm.entered();
			if (i == 10 || i == 50 || i == 100 || i == 500 || i == 1000) {
				assertEquals(i, m);
			} else {
				assertEquals(0, m);
			}
			vm.refund();
		}
	}