古いコードは別ページへ
はじめに定数を収めるクラスを定義する。
package test;
public class Constant {
public final static double err = 0.00001;
public final static boolean debug = false;
public static final int TESTLENGTH = 100;
}
さて、テストにおいては、リスト内のオブジェクトの振る舞いに関するものが多い。 繰り返し文で処理するとループ変数の値の確認など、障害を直感的に把握しづ らい。 そのため、ストラテジデザインパターンを使い、リストの各オブジェクトに関 して、処理するアルゴリズムを示すオブジェクトを与え、 処理関数で、リスト要素に対して、そのオブジェクトのアルゴリズムを適用し て結果を配列化する。 例えば、 TestIntMethod インターフェイスは perform メソッドで Card オブジェクト に対して何らかの整数値を得るものである。 これを利用して toIntArray スタティックメソッドは、Card のサブクラスの Collection と、その TestIntMethod を実装したクラスのインスタンスを引数 にして、各 Collection の内容に対して値を計算して、整数配列に結果を収め る。
package test;
import java.util.Collection;
import card.Card;
public class CommonCardTest {
protected interface TestIntMethod{
int perform(Card e);
}
private static final int len = 10;
protected static String[] randomStringArray(int n){
String[] result = new String[n];
for(int i=0; i<n; i++){
StringBuilder sb = new StringBuilder();
for(int j=0; j<len; j++){
sb.append('A'+Math.random()*('Z'-'A'+1));
}
result[i]=sb.toString();
}
return result;
}
protected static int[] toIntArray(Collection<? extends Card> arg, TestIntMethod b){
int[] result = new int[arg.size()];
int i=0;
for(Card e : arg){
result[i++]=b.perform(e);
}
return result;
}
protected class Id implements TestIntMethod {
@Override
public int perform(Card e) {
return e.id();
}
}
protected class Rate implements TestIntMethod {
@Override
public int perform(Card e) {
return e.rate();
}
}
protected interface TestObjectMethod<F> {
F perform(Card e);
}
protected static <F> F[] toObjectArray(Collection<? extends Card> arg, TestObjectMethod<F> b){
@SuppressWarnings("unchecked")
F[] result = (F[]) new Object[arg.size()];
int i=0;
for(Card e : arg){
result[i++]=b.perform(e);
}
return result;
}
protected class ToString implements TestObjectMethod<String>{
@Override
public String perform(Card e) {
return e.toString();
}
}
protected class Name implements TestObjectMethod<String>{
@Override
public String perform(Card e) {
return e.name();
}
}
static int[] getIntArray(int start, int size) {
int[] result = new int[size];
int j=start;
for(int i=0; i<size; i++){
result[i]=j++;
}
return result;
}
}
また、似たようなものに対して同じようなシナリオでテストするため、シナリ オを抽象化する。 カードのリストに関して、各カードへの true, false の判定と、 compareTo の判定の抽象化をしている。
package test;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import java.util.List;
import card.Card;
public class CardTestScenario<E extends Card> {
protected List<E> list;
private Tester<E> tester;
protected static interface Tester<E> {
boolean check(E card);
}
public CardTestScenario(List<E> list1) {
list = list1;
}
public void execCheck() {
int i=0;
for(E card: list){
assertThat("index="+i, tester.check(card), is(true));
i++;
}
}
public void setTest(Tester<E> tester) {
this.tester = tester;
}
public void testCompareTo() {
for(Card c1 : list){
for(Card c2 :list){
int result = c1.compareTo(c2);
String message = c1+"compareTo"+c2;
if(c1.id()==c2.id()) assertThat(message,result,is(0));
else if(c1.id() < c2.id()) assertThat(message,result<0,is(true));
else if(c1.id() > c2.id()) assertThat(message,result>0,is(true));
}
}
}
}
これを利用したのが ZakoTest と RareTest である。
package test;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import card.Card;
import card.CardFactory;
import card.Zako;
public class ZakoTest extends CommonCardTest {
private static final String[] zako1name = {"Aka","Ao","Kuro"};
private String[] zako2name;
private List<Card> zako1;
private List<Card> zako2;
private CardFactory factory1;
private CardFactory factory2;
private CardTestScenario<Card> cardTestScenario1;
private CardTestScenario<Card> cardTestScenario2;
@Before
public void setup(){
factory1 = new CardFactory(0,zako1name, new Zako());
zako2name = randomStringArray(Constant.TESTLENGTH);
factory2 = new CardFactory(10,zako2name, new Zako());
zako1 = factory1.getList();
zako2 = factory2.getList();
cardTestScenario1 = new CardTestScenario<Card>(zako1);
cardTestScenario2 = new CardTestScenario<Card>(zako2);
}
private static class ZakoClassTest implements CardTestScenario.Tester<Card>{
@Override
public boolean check(Card card) {
return card instanceof Zako;
}
}
@Test
public void testClass(){
cardTestScenario1.setTest(new ZakoClassTest());
cardTestScenario1.execCheck();
cardTestScenario2.setTest(new ZakoClassTest());
cardTestScenario2.execCheck();
}
@Test
public void testRate() {
int[] exp1 = new int[zako1name.length];
Arrays.fill(exp1, 1);
assertArrayEquals(exp1, toIntArray(zako1,new Rate()));
int[] exp2 = new int[zako2name.length];
Arrays.fill(exp2, 1);
assertArrayEquals(exp2, toIntArray(zako2,new Rate()));
}
@Test
public void testToString(){
assertArrayEquals(zako1name, toObjectArray(zako1,new ToString()));
assertArrayEquals(zako2name, toObjectArray(zako2,new ToString()));
}
@Test
public void testName(){
assertArrayEquals(zako1name, toObjectArray(zako1,new Name()));
assertArrayEquals(zako2name, toObjectArray(zako2,new Name()));
}
@Test
public void testOrder() {
int[] exp1 = CommonCardTest.getIntArray(0,zako1name.length);
assertArrayEquals(exp1, toIntArray(zako1,new Id()));
int[] exp2 = CommonCardTest.getIntArray(10,zako2name.length);
assertArrayEquals(exp2, toIntArray(zako2,new Id()));
}
@Test
public void testCompareTo() {
cardTestScenario1.testCompareTo();
cardTestScenario2.testCompareTo();
}
}
package test;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import card.Card;
import card.CardFactory;
import card.Rare;
public class RareTest extends CommonCardTest {
private static final String[] name1 = {"RareAka","RareAo","RareKuro"};
private String[] name2;
private List<Card> list1;
private List<Card> list2;
private CardFactory factory1;
private CardFactory factory2;
private CardTestScenario<Card> cardTestScenario1;
private CardTestScenario<Card> cardTestScenario2;
@Before
public void setup(){
name2 = randomStringArray(Constant.TESTLENGTH);
factory1 = new CardFactory(10,name1,new Rare());
factory2 = new CardFactory(110,name2,new Rare());
list1 = factory1.getList();
list2 = factory2.getList();
cardTestScenario1 = new CardTestScenario<Card>(list1);
cardTestScenario2 = new CardTestScenario<Card>(list2);
}
private static class RareClassTest implements CardTestScenario.Tester<Card>{
@Override
public boolean check(Card card) {
return card instanceof Rare;
}
}
@Test
public void testClass(){
cardTestScenario1.setTest(new RareClassTest());
cardTestScenario1.execCheck();
cardTestScenario2.setTest(new RareClassTest());
cardTestScenario2.execCheck();
}
@Test
public void testRate() {
int[] exp1 = new int[name1.length];
Arrays.fill(exp1, 100);
assertArrayEquals(exp1, toIntArray(list1,new Rate()));
int[] exp2 = new int[name2.length];
Arrays.fill(exp2, 100);
assertArrayEquals(exp2, toIntArray(list2,new Rate()));
}
@Test
public void testToString(){
assertArrayEquals(name1, toObjectArray(list1,new ToString()));
assertArrayEquals(name2, toObjectArray(list2,new ToString()));
}
@Test
public void testName(){
assertArrayEquals(name1, toObjectArray(list1,new Name()));
assertArrayEquals(name2, toObjectArray(list2,new Name()));
}
@Test
public void testOrder() {
int[] exp1 = CommonCardTest.getIntArray(10,list1.size());
assertArrayEquals(exp1, toIntArray(list1,new Id()));
int[] exp2 = CommonCardTest.getIntArray(110,list2.size());
assertArrayEquals(exp2, toIntArray(list2,new Id()));
}
@Test
public void testCompareTo() {
cardTestScenario1.testCompareTo();
cardTestScenario2.testCompareTo();
}
}
さらに SuperRareScenario を作成して SuperRareTest を作成した。 SupereRareScenario は CardTestScenario を継承していて、さらに確率の変 化するカードのテストのシナリオを抽象化している。
package test;
import static org.junit.Assert.*;
import java.util.List;
import player.CardCollection;
import kotae.SuperRare;
import static test.CommonCardTest.*;
public class SuperRareScenario extends CardTestScenario<SuperRare>{
protected CardCollection cc;
protected boolean[] compArray;
public SuperRareScenario(List<SuperRare> list1, CardCollection cc1) {
super(list1);
this.cc=cc1;
compArray = new boolean[list1.size()];
int i=0;
for(SuperRare card : list1){
compArray[i++]=cc1.contains(card);
}
}
public void drawCard(int j){
compArray[j] = true;
cc.add(list.get(j));
}
public void testVariableRate(int[] expected) {
assertArrayEquals(expected,toIntArray(list, new Rate()));
}
}
package test;
import static org.junit.Assert.*;
import java.util.List;
import kotae.SuperRare;
import org.junit.Before;
import org.junit.Test;
import player.CardCollection;
import card.SuperRareFactory;
public class SuperRareTest extends CommonCardTest {
private CardCollection cc1;
private CardCollection cc2;
private static final String[] name1 = {"SuperRareAka","SuperRareAo","SuperRareKuro"};
private static final String[] name2 = {"SuperRareA","SuperRareB","SuperRareC","SuperRareD"};
private List<SuperRare> list1;
private List<SuperRare> list2;
private SuperRareFactory factory1;
private SuperRareFactory factory2;
private SuperRareScenario cardTestScenario1;
private SuperRareScenario cardTestScenario2;
@Before
public void setup(){
cc1 = new CardCollection();
cc2 = new CardCollection();
factory1 = new SuperRareFactory(20,name1);
factory2 = new SuperRareFactory(30,name2);
list1 = factory1.getList(cc1);
list2 = factory2.getList(cc2);
cardTestScenario1 = new SuperRareScenario(list1,cc1);
cardTestScenario2 = new SuperRareScenario(list2,cc2);
}
private static class SuperRareClassTest implements CardTestScenario.Tester<SuperRare>{
@Override
public boolean check(SuperRare card) {
return card instanceof SuperRare;
}
}
@Test
public void testClass(){
cardTestScenario1.setTest(new SuperRareClassTest());
cardTestScenario1.execCheck();
cardTestScenario2.setTest(new SuperRareClassTest());
cardTestScenario2.execCheck();
}
@Test
public void testVariableRate1(){
cardTestScenario1.testVariableRate(new int[]{100,100,100});
cardTestScenario1.drawCard(1);
cardTestScenario1.testVariableRate(new int[]{1000,100,1000});
cardTestScenario1.drawCard(1);
cardTestScenario1.testVariableRate(new int[]{1000,100,1000});
cardTestScenario1.drawCard(2);
cardTestScenario1.testVariableRate(new int[]{10000,100,100});
cardTestScenario1.drawCard(1);
cardTestScenario1.testVariableRate(new int[]{10000,100,100});
cardTestScenario1.drawCard(0);
cardTestScenario1.testVariableRate(new int[]{100,100,100});
}
@Test
public void testVariableRate2(){
cardTestScenario2.testVariableRate(new int[]{100,100,100,100});
cardTestScenario2.drawCard(1);
cardTestScenario2.testVariableRate(new int[]{100,100,100,100});
cardTestScenario2.drawCard(1);
cardTestScenario2.testVariableRate(new int[]{100,100,100,100});
cardTestScenario2.drawCard(2);
cardTestScenario2.testVariableRate(new int[]{1000,100,100,1000});
cardTestScenario2.drawCard(1);
cardTestScenario2.testVariableRate(new int[]{1000,100,100,1000});
cardTestScenario2.drawCard(0);
cardTestScenario2.testVariableRate(new int[]{100,100,100,10000});
cardTestScenario2.drawCard(3);
cardTestScenario2.testVariableRate(new int[]{100,100,100,100});
}
@Test
public void testMultiplayer(){
CardCollection cc12 = new CardCollection();
List<SuperRare> list12 = factory1.getList(cc12);
SuperRareScenario cardTestScenario12 = new SuperRareScenario(list12,cc12);
cardTestScenario1.testVariableRate(new int[]{100,100,100});
cardTestScenario12.testVariableRate(new int[]{100,100,100});
cardTestScenario1.drawCard(0);
cardTestScenario1.testVariableRate(new int[]{100,1000,1000});
cardTestScenario12.testVariableRate(new int[]{100,100,100});
cardTestScenario12.drawCard(1);
cardTestScenario1.testVariableRate(new int[]{100,1000,1000});
cardTestScenario12.testVariableRate(new int[]{1000,100,1000});
cardTestScenario12.drawCard(2);
cardTestScenario1.testVariableRate(new int[]{100,1000,1000});
cardTestScenario12.testVariableRate(new int[]{10000,100,100});
cardTestScenario12.drawCard(0);
cardTestScenario1.testVariableRate(new int[]{100,1000,1000});
cardTestScenario12.testVariableRate(new int[]{100,100,100});
cardTestScenario1.drawCard(1);
cardTestScenario1.testVariableRate(new int[]{100,100,10000});
cardTestScenario12.testVariableRate(new int[]{100,100,100});
cardTestScenario12.drawCard(0);
cardTestScenario1.testVariableRate(new int[]{100,100,10000});
cardTestScenario12.testVariableRate(new int[]{100,100,100});
}
@Test
public void testToString(){
assertArrayEquals(name1, toObjectArray(list1,new ToString()));
assertArrayEquals(name2, toObjectArray(list2,new ToString()));
}
@Test
public void testName(){
assertArrayEquals(name1, toObjectArray(list1,new Name()));
assertArrayEquals(name2, toObjectArray(list2,new Name()));
}
@Test
public void testOrder() {
int[] exp1 = {20,21,22};
assertArrayEquals(exp1, toIntArray(list1,new Id()));
int[] exp2 = {30,31,32,33};
assertArrayEquals(exp2, toIntArray(list2,new Id()));
}
@Test
public void testCompareTo() {
cardTestScenario1.testCompareTo();
cardTestScenario2.testCompareTo();
}
}
また、 Deck の各クラスのテストに関しても同じテクニックを使っている。
package test;
import gacha.AbstractDeck;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import card.Card;
public class CommonDeckTest {
protected interface TestDoubleMethod<E> {
double perform(E e);
}
protected static <E> double[] toDoubleArray(Collection<E> arg, TestDoubleMethod<E> b){
double[] result = new double[arg.size()];
int i=0;
for(E e : arg){
result[i++]=b.perform(e);
}
return result;
}
protected class GetKey implements TestDoubleMethod<Entry<Double,Card>> {
@Override
public double perform(Entry<Double, Card> e) {
return e.getKey();
}
}
protected class GetCardRate implements TestDoubleMethod<Card> {
private AbstractDeck deck;
public GetCardRate(AbstractDeck deck) {
super();
this.deck = deck;
}
@Override
public double perform(Card card) {
return deck.getCardRate(card);
}
}
protected int[] toIdArray(List<Card> list) {
int[] result = new int[list.size()];
int i=0;
for(Card card : list){
result[i++]=card.id();
}
return result;
}
}
package test;
import static org.junit.Assert.*;
import java.util.List;
import kotae.Deck2;
import gacha.Deck1;
import org.junit.Before;
import org.junit.Test;
import card.Card;
import card.Zako;
public class Deck1Test extends CommonDeckTest {
private Deck1 deck;
private List<Card> list;
@Before
public void setUp() throws Exception {
deck=new Deck1();
list = Deck1.getList();
}
@Test
public void testTotal() {
assertEquals(3.0,deck.total(),Constant.err);
}
@Test
public void testGetCardRate() {
double[] rate = new double[]{1.0,1.0,1.0};
assertArrayEquals(rate, toDoubleArray(list,new GetCardRate(deck)), Constant.err);
}
@Test
public void testCalcMap() {
double[] dist = new double[]{0.0, 0.33333, 0.66667};
assertArrayEquals(dist, toDoubleArray(deck.calcMap().entrySet(),new GetKey()), Constant.err);
}
@Test
public void testList() {
assertEquals("[Aka, Ao, Kuro]",list.toString());
}
@Test
public void testGetList() {
assertEquals("[Aka, Ao, Kuro]",Deck1.getList().toString());
}
@Test
public void testGetListId() {
int[] ids={0,1,2};
assertArrayEquals(ids,toIdArray(Deck1.getList()));
}
@Test
public void testToString() {
assertEquals("[Aka, Ao, Kuro]",deck.toString());
}
@Test
public void testDraw() {
Card c = deck.draw();
assertTrue(c instanceof Zako);
}
}
package test;
import static org.junit.Assert.*;
import gacha.Deck1;
import java.util.List;
import kotae.Deck2;
import org.junit.Before;
import org.junit.Test;
import card.Card;
public class Deck2Test extends CommonDeckTest {
private Deck2 deck;
private List<Card> list;
@Before
public void setUp() throws Exception {
deck=new Deck2();
list = Deck2.getList();
}
@Test
public void testTotal() {
assertEquals(3.03,deck.total(),Constant.err);
}
@Test
public void testGetCardRate() {
double[] rate = new double[]{1.0,1.0,1.0,0.01,0.01,0.01};
assertArrayEquals(rate, toDoubleArray(list,new GetCardRate(deck)), Constant.err);
}
@Test
public void testCalcMap() {
double[] dist = new double[]{0.0, 0.33003, 0.660067, 0.99010, 0.99340, 0.99670};
assertArrayEquals(dist, toDoubleArray(deck.calcMap().entrySet(),new GetKey()), Constant.err);
}
@Test
public void testList() {
assertEquals("[Aka, Ao, Kuro, RareAka, RareAo, RareKuro]",list.toString());
}
@Test
public void testGetList() {
assertEquals("[Aka, Ao, Kuro, RareAka, RareAo, RareKuro]",Deck2.getList().toString());
}
@Test
public void testGetListId() {
int[] ids={0,1,2,10,11,12};
assertArrayEquals(ids,toIdArray(Deck2.getList()));
}
@Test
public void testToString() {
assertEquals("[Aka, Ao, Kuro, RareAka, RareAo, RareKuro]",deck.toString());
}
}
package test;
import static org.junit.Assert.*;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import kotae.Deck2;
import gacha.Deck3;
import org.junit.Before;
import org.junit.Test;
import card.Card;
import player.CardCollection;
public class Deck3Test extends CommonDeckTest {
private CardCollection cc;
private Deck3 deck;
private List<Card> list;
@Before
public void setUp() throws Exception {
cc = new CardCollection();
deck = new Deck3(cc);
list = Deck3.getList(cc);
}
@Test
public void testTotal() {
assertEquals(3.03,deck.total(),Constant.err);
}
@Test
public void testGetCardRate0() {
double[] rate = new double[]{1.0,1.0,1.0,0.01,0.01,0.01};
assertArrayEquals(rate, toDoubleArray(list,new GetCardRate(deck)), Constant.err);
}
@Test
public void testGetCardRate1() {
double[] rate = new double[]{1.0,1.0,1.0,0.01,0.001,0.001};
cc.add(list.get(3));
assertArrayEquals(rate, toDoubleArray(list,new GetCardRate(deck)), Constant.err);
}
@Test
public void testGetCardRate2() {
double[] rate = new double[]{1.0,1.0,1.0,0.01,0.001,0.001};
cc.add(list.get(3));
cc.add(list.get(3));
assertArrayEquals(rate, toDoubleArray(list,new GetCardRate(deck)), Constant.err);
}
@Test
public void testGetCardRate3() {
double[] rate = new double[]{1.0,1.0,1.0,0.01,0.01,0.0001};
cc.add(list.get(3));
cc.add(list.get(3));
cc.add(list.get(4));
assertArrayEquals(rate, toDoubleArray(list,new GetCardRate(deck)), Constant.err);
}
@Test
public void testCalcMap0() {
double[] dist = new double[]{0.0, 0.33003, 0.66007, 0.99010, 0.99340, 0.99670};
assertArrayEquals(dist, toDoubleArray(deck.calcMap().entrySet(),new GetKey()), Constant.err);
}
@Test
public void testCalcMap1() {
double[] dist = new double[]{0.0, 0.332005, 0.66401, 0.99602, 0.99934, 0.99967};
cc.add(list.get(3));
assertArrayEquals(dist, toDoubleArray(deck.calcMap().entrySet(),new GetKey()), Constant.err);
}
@Test
public void testCalcMap2() {
double[] dist = new double[]{0.0, 0.332005, 0.66401, 0.99602, 0.99934, 0.99967};
cc.add(list.get(3));
cc.add(list.get(3));
assertArrayEquals(dist, toDoubleArray(deck.calcMap().entrySet(),new GetKey()), Constant.err);
Iterator<Entry<Double, Card>> iterator = deck.calcMap().entrySet().iterator();
int i=0;
while(iterator.hasNext()){
Entry<Double, Card> e = iterator.next();
assertEquals(dist[i++],e.getKey(),Constant.err);
}
}
@Test
public void testCalcMap3() {
double[] prob = new double[]{0.0, 0.33111, 0.66223, 0.99334, 0.99666, 0.99997};
cc.add(list.get(3));
cc.add(list.get(3));
cc.add(list.get(4));
assertArrayEquals(prob, toDoubleArray(deck.calcMap().entrySet(),new GetKey()), Constant.err);
}
@Test
public void testList() {
assertEquals("[Aka, Ao, Kuro, SuperRareAka, SuperRareAo, SuperRareKuro]",list.toString());
}
@Test
public void testToString() {
assertEquals("[Aka, Ao, Kuro, SuperRareAka, SuperRareAo, SuperRareKuro]",deck.toString());
}
@Test
public void testGetList() {
assertEquals("[Aka, Ao, Kuro, SuperRareAka, SuperRareAo, SuperRareKuro]",Deck3.getList(cc).toString());
}
@Test
public void testGetListId() {
int[] ids={0,1,2,20,21,22};
assertArrayEquals(ids,toIdArray(Deck3.getList(cc)));
}
}
最後に、CardCollection クラスのテストクラスを示す。
package test;
import static org.junit.Assert.*;
import java.util.HashSet;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import card.Card;
import card.CardFactory;
import card.Zako;
import player.CardCollection;
public class CardCollectionTest {
private CardCollection c;
private static final String[] zako1name = {"Aka","Ao","Kuro"};
private CardFactory factory1;
@Before
public void setUp() throws Exception {
c = new CardCollection();
factory1 = new CardFactory(0,zako1name,new Zako());
for(Card card : factory1.getList()){
c.add(card);
}
}
@Test
public void testToString() {
CardCollection c = new CardCollection();
Card[] card = factory1.getList().toArray(new Card[0]);
c.add(card[0]);
c.add(card[1]);
c.add(card[1]);
assertEquals("1 Aka(s) and 2 Ao(s)",c.toString());
}
@Test
public void testContains(){
for(Card card : factory1.getList()){
assertTrue(c.contains(card));
}
}
@Test
public void testCompletes2(){
Set<Integer> watch = new HashSet<Integer>();
CardCollection c = new CardCollection();
assertTrue(c.completes(watch));
for(Card card : factory1.getList()){
c.add(card);
assertTrue(c.completes(watch));
}
}
@Test
public void testCompletes(){
Set<Integer> watch = new HashSet<Integer>();
watch.add(0);
watch.add(1);
watch.add(2);
CardCollection c = new CardCollection();
Card[] card = factory1.getList().toArray(new Card[0]);
assertFalse(c.completes(watch));
c.add(card[0]);
assertFalse(c.completes(watch));
c.add(card[1]);
assertFalse(c.completes(watch));
c.add(card[1]);
assertFalse(c.completes(watch));
c.add(card[2]);
assertTrue(c.completes(watch));
}
}