TDD: テスト駆動開発

勇者のLevelを経験値によって判断するクラス Level を作成する。

package rpg;

public class Level {
	public static int getLevel(int exp) {
		return 1;
	}
}

Level.java を右クリックして[新規]-[その他]を選択する。
Junitテストケースを選択して「次へ」をクリック。
getLevel()メソッドにチェックして「完了」をクリックする。

LevelTest.javaが作成される。
以下のコードを追加する。

package rpg;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class LevelTest {

	@Test
	void testGetLevel() {
		int l = Level.getLevel(0);
		assertThat(l, is(1));
	}

}

仕様を決める。

Level 経験値
1 0~10
2 11~30
3 31~60
4 61~150
5 151~

経験値が0から10まではレベル1で、経験値が11だとレベル1ではないというテストを書く。

package rpg;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class LevelTest {

	@Test
	void testGetLevel1() {
		int l = Level.getLevel(0);
		assertThat(l, is(1));
		l = Level.getLevel(10);
		assertThat(l, is(1));
		l = Level.getLevel(11);
		assertThat(l, not(1));
	}

}

このテストにパスするように、Level.java を修正する。

package rpg;

public class Level {
	public static int getLevel(int exp) {
		if (exp > 10) return 2;
		return 1;
	}
}

徐々にテストを増やしていき、Lebel.javaのコードにはテストにパスするように追加していく。

package rpg;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class LevelTest {

	@Test
	void testGetLevel1() {
		int l = Level.getLevel(0);
		assertThat(l, is(1));
		l = Level.getLevel(10);
		assertThat(l, is(1));
		l = Level.getLevel(11);
		assertThat(l, not(1));
	}

	@Test
	void testGetLevel2() {
		int l = Level.getLevel(10);
		assertThat(l, not(2));
		l = Level.getLevel(11);
		assertThat(l, is(2));
		l = Level.getLevel(30);
		assertThat(l, is(2));
		l = Level.getLevel(31);
		assertThat(l, not(2));
	}

	@Test
	void testGetLevel3() {
		int l = Level.getLevel(30);
		assertThat(l, not(3));
		l = Level.getLevel(31);
		assertThat(l, is(3));
		l = Level.getLevel(60);
		assertThat(l, is(3));
		l = Level.getLevel(61);
		assertThat(l, not(3));
	}

	@Test
	void testGetLevel4() {
		int l = Level.getLevel(60);
		assertThat(l, not(4));
		l = Level.getLevel(61);
		assertThat(l, is(4));
		l = Level.getLevel(150);
		assertThat(l, is(4));
		l = Level.getLevel(151);
		assertThat(l, not(4));
	}
}

Lebel.java

package rpg;

public class Level {
	public static int getLevel(int exp) {
		if (exp > 150) return 5;
		if (exp > 60) return 4;
		if (exp > 30) return 3;
		if (exp > 10) return 2;
		return 1;
	}
}

FizzBuzz問題をTDDで実装する

FuzzBuzzクラスを作成する。

package hello;

public class FizzBuzz {
	public String answer(int i) {
		return null;
	}
}

FizzBuzzTest を作成する。

package hello;

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

import org.junit.jupiter.api.Test;

class FizzBuzzTest {

	@Test
	void testAnswer() {
		fail("まだ実装されていません");
	}

}

まず、1のときに文字列”1″が返されるという条件のテストを作成する。

package hello;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class FizzBuzzTest {

	@Test
	void testAnswer() {
		FizzBuzz fb = new FizzBuzz();
		String a = fb.answer(1);
		assertThat(a, is("1"));
	}

}

このテストにパスする最低限のコードを書く。
このような書き方を fake という。

package hello;

public class FizzBuzz {
	public String answer(int i) {
		return "1";
	}
}

fake でテストにパスしたので、テストを追加する。

package hello;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class FizzBuzzTest {

	@Test
	void testAnswer() {
		FizzBuzz fb = new FizzBuzz();
		String a = fb.answer(1);
		assertThat(a, is("1"));
		a = fb.answer(2);
		assertThat(a, is("2"));
	}

}

テストにパスするようにFizzBuzzを修正する。

package hello;

public class FizzBuzz {
	public String answer(int i) {
		if (i == 2) return "2";
		return "1";
	}
}

テストにパスしたので、テストを追加する。

package hello;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class FizzBuzzTest {

	@Test
	void testAnswer() {
		FizzBuzz fb = new FizzBuzz();
		String a = fb.answer(1);
		assertThat(a, is("1"));
		a = fb.answer(2);
		assertThat(a, is("2"));
		a = fb.answer(3);
		assertThat(a, is("Fizz"));
	}

}

テストにパスするようにFizzBuzzを修正する。

package hello;

public class FizzBuzz {
	public String answer(int i) {
		if (i == 3) return "Fizz";
		if (i == 2) return "2";
		return "1";
	}
}

テストにパスしたので、テストを追加する。

package hello;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class FizzBuzzTest {

	@Test
	void testAnswer() {
		FizzBuzz fb = new FizzBuzz();
		String a = fb.answer(1);
		assertThat(a, is("1"));
		a = fb.answer(2);
		assertThat(a, is("2"));
		a = fb.answer(3);
		assertThat(a, is("Fizz"));
		a = fb.answer(4);
		assertThat(a, is("4"));
	}

}

さすがにif文で対応すると重複した処理が増えるので、数値を文字列に変換する部分をまとめる。

package hello;

public class FizzBuzz {
	public String answer(int i) {
		if (i == 3) return "Fizz";
		return String.valueOf(i);
	}
}

5の場合は “Buzz”と返すテストを作成する。

package hello;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class FizzBuzzTest {

	@Test
	void testAnswer() {
		FizzBuzz fb = new FizzBuzz();
		String a = fb.answer(1);
		assertThat(a, is("1"));
		a = fb.answer(2);
		assertThat(a, is("2"));
		a = fb.answer(3);
		assertThat(a, is("Fizz"));
		a = fb.answer(4);
		assertThat(a, is("4"));
		a = fb.answer(5);
		assertThat(a, is("Buzz"));
	}

}

テストにパスするようにFizzBuzzを修正する。

package hello;

public class FizzBuzz {
	public String answer(int i) {
		if (i == 5) return "Buzz";
		if (i == 3) return "Fizz";
		return String.valueOf(i);
	}
}

6は3の倍数なので “Fizz” と返す。

package hello;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class FizzBuzzTest {

	@Test
	void testAnswer() {
		FizzBuzz fb = new FizzBuzz();
		String a = fb.answer(1);
		assertThat(a, is("1"));
		a = fb.answer(2);
		assertThat(a, is("2"));
		a = fb.answer(3);
		assertThat(a, is("Fizz"));
		a = fb.answer(4);
		assertThat(a, is("4"));
		a = fb.answer(5);
		assertThat(a, is("Buzz"));
		a = fb.answer(6);
		assertThat(a, is("Fizz"));
	}

}

3の倍数なら “Fizz” と返すようにする。

package hello;

public class FizzBuzz {
	public String answer(int i) {
		if (i == 5) return "Buzz";
		if (i % 3 == 0) return "Fizz";
		return String.valueOf(i);
	}
}

7・8・9はこのままで問題なさそうなので飛ばす。
10は5の倍数なので “Buzz” が返されるはず。

package hello;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class FizzBuzzTest {

	@Test
	void testAnswer() {
		FizzBuzz fb = new FizzBuzz();
		String a = fb.answer(1);
		assertThat(a, is("1"));
		a = fb.answer(2);
		assertThat(a, is("2"));
		a = fb.answer(3);
		assertThat(a, is("Fizz"));
		a = fb.answer(4);
		assertThat(a, is("4"));
		a = fb.answer(5);
		assertThat(a, is("Buzz"));
		a = fb.answer(6);
		assertThat(a, is("Fizz"));
		a = fb.answer(10);
		assertThat(a, is("Buzz"));
	}

}

3の倍数と同様に、5の倍数は “Buzz” を返すようにする。

package hello;

public class FizzBuzz {
	public String answer(int i) {
		if (i % 5 == 0) return "Buzz";
		if (i % 3 == 0) return "Fizz";
		return String.valueOf(i);
	}
}

11・12・13・14は問題なさそうなので飛ばす。
15の倍数の時は “FizzBuzz” となるので、テストを追加する。

package hello;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class FizzBuzzTest {

	@Test
	void testAnswer() {
		FizzBuzz fb = new FizzBuzz();
		String a = fb.answer(1);
		assertThat(a, is("1"));
		a = fb.answer(2);
		assertThat(a, is("2"));
		a = fb.answer(3);
		assertThat(a, is("Fizz"));
		a = fb.answer(4);
		assertThat(a, is("4"));
		a = fb.answer(5);
		assertThat(a, is("Buzz"));
		a = fb.answer(6);
		assertThat(a, is("Fizz"));
		a = fb.answer(10);
		assertThat(a, is("Buzz"));
		a = fb.answer(15);
		assertThat(a, is("FizzBuzz"));
	}

}

テストにパスするようにFizzBuzzを修正する。

package hello;

public class FizzBuzz {
	public String answer(int i) {
		if (i % 15 == 0) return "FizzBuzz";
		if (i % 5 == 0) return "Buzz";
		if (i % 3 == 0) return "Fizz";
		return String.valueOf(i);
	}
}

世界のナベアツをテスト駆動開発で実装する

対象となるクラス Nabeatsu を作成する。

package hello;

public class Nabeatsu {
	public String answer(int i) {
		return null;
	}
}

Junitテストケースを作成する。

package hello;

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

import org.junit.jupiter.api.Test;

class NabeatsuTest {

	@Test
	void testAnswer() {
		fail("まだ実装されていません");
	}

}

1から3までテストを書いていく。

package hello;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class NabeatsuTest {

	@Test
	void testAnswer() {
		Nabeatsu n = new Nabeatsu();
		String a = n.answer(1);
		assertThat(a, is("1"));
		a = n.answer(2);
		assertThat(a, is("2"));
		a = n.answer(3);
		assertThat(a, is("さぁ~ん!"));
	}

}

3の倍数はFizzBuzzと同じなので簡単にできる。

package hello;

public class Nabeatsu {
	public String answer(int i) {
		if (i % 3 == 0) return "さぁ~ん!";
		return String.valueOf(i);

	}
}

3の倍数ではないけど3が含まれるパターンに対応する。

package hello;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.jupiter.api.Test;

class NabeatsuTest {

	@Test
	void testAnswer() {
		Nabeatsu n = new Nabeatsu();
		String a = n.answer(1);
		assertThat(a, is("1"));
		a = n.answer(2);
		assertThat(a, is("2"));
		a = n.answer(3);
		assertThat(a, is("さぁ~ん!"));
		a = n.answer(13);
		assertThat(a, is("さぁ~ん!"));
	}

}

数値を String.valueOf() で文字列に変換し、その中に “3” が含まれるかどうかを調べる。

package hello;

public class Nabeatsu {
	public String answer(int i) {
		if (i % 3 == 0) return "さぁ~ん!";
		String s = String.valueOf(i);
		if (s.contains("3")) return "さぁ~ん!";
		return s;
	}
}

コメントを残す

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.