

CardDeckクラスを作ったのですが、それをjunit3でテストする課題が出ました。しかし、テストした12個のメソッドのうち8個が失敗（一つは失敗がかくれているようなので実質9個）になります。CardDeckクラス自体は問題なく動くのでテストの仕方に問題があると考えているのですが、わからないので教えてください。（プログラミング初心者です。下手なコードでごめんなさい）。  
ちなみにほかにCardクラスがあり、トランプを、スペードが０，ダイヤが１，ハートが２，クローバーが３として扱っていて、CardDeckクラスはCardクラスでのカードをデッキとしてリストに入れて扱うクラスです。

**↓CardDeckクラス**

[code]

    import java.util.Collections;
    import java.util.List;
    
    /**
     * カードデッキクラス． 
     * 
     * @author  
     */
    
    public class CardDeck {
        /**カードデッキ，カードを登録するリスト*/
        private ArrayList<Card> cards = new ArrayList<>();
        
        /**空のインスタンスを作る*/
        public CardDeck() {
            
        }
        
        /**フルデッキを作るメソッド*/
        public void createFullDeck() {
            int i,j;
            for(i=0;i<4;i++) {
                for(j=1;j<14;j++) {
                    Card card = new Card(i,j);
                    addCard(card);
                }
            }
        }
        
        /**ジョーカーを追加するメソッド*/
        public void addJoker() {
            Card card = new Card(-1,0);
            addCard(card);
        }
        
        /**デッキを空にするメソッド*/
        public void clear() {
            cards.clear();
        }
        
        /**デッキのカードをシャッフルするメソッド*/
        public void shuffle() {
            Collections.shuffle(cards);
        }
        
        /**デッキの最後にカードを追加するメソッド*/
        public void addCard(Card card) {
            cards.add(card);
        }
        
        /**指定された番号の場所にカードを追加するメソッド*/
        public void addCard(int i,Card card) {
            cards.add(i-1,card);
        }
        
        /**1番目のカードを取って返すメソッド*/
        public Card takeCard() {
            Card top = cards.get(0);
            cards.remove(0);
            return top;
        }
        
        /**指定された番号の場所のカードを取って返すメソッド*/
        public Card takeCard(int i) {
            Card trump = cards.get(i-1);
            cards.remove(i-1);
            return trump;
        }
        
        /**指定された番号の場所のカードの情報を返すメソッド*/
        public Card seeCard(int i) {
            Card trump = cards.get(i-1);
            return trump;
        }
        
        /**指定されたトランプがデッキの何番目にあるかを返すメソッド*/
        public int serchCard(int suit,int number) {
            Card card = new Card(suit,number);
            int num;
            if(cards.contains(card)) {
                num = cards.indexOf(card)+1;
            }else {
                num = 0;
            }
            return num;
        }
        
        /**デッキが空かどうかを確認するメソッド*/
        public boolean isEmpty() {
            boolean empty = cards.isEmpty();
            return empty;
        }
        
        /**デッキにあるカードの枚数を返すメソッド*/
        public int size() {
            int size = cards.size();
            return size;
        }
        
        /**デッキのカードの情報をすべて表示するメソッド*/
        public void showAllCards() {
            ArrayList<Integer> suit = new ArrayList<>();
            ArrayList<Integer> number = new ArrayList<>();
            int i;
            Card card;
            for(i=0;i<cards.size();i++) {
                card = cards.get(i);
                suit.add(card.getSuit());
                number.add(card.getNumber());
            }
            
            System.out.println("------------現在の山を表示します．-----------");
            int j;
            String trump;
            for(j=0;j<suit.size();j++) {
                System.out.print(j+1+"番目のカード：");
                trump = Card.getString(suit.get(j),number.get(j));
                System.out.println(trump);
            }
            System.out.println("------------ここまで-----------");
        }
        /**デッキのカード情報を返すメソッド*/
        public List<Card> getAllCards(){
            return cards;
        }
        
        /**
         * デッキを取得する
         * 
         * @return デッキ
         */
        public ArrayList<Card> getCards() {
            return cards;
        }
    
        /**
         * デッキをセットする
         * 
         * @param cards
         *            デッキ
         */
        public void setCards(ArrayList<Card> cards) {
            this.cards = cards;
        }
        
    }
    
[/code]

**↓Cardクラス**

[code]

    **
     * カードクラス．絵柄，数字を持つ， 
     * 
     * @author 
     */
    
    public class Card {
        
        /** 絵柄 */
        private int suit;
        /** 数字 */
        private int number;
        
        /**空のコンストラクタ*/
        public Card() {
            
        }
        
        /** 絵柄，数字を指定してインスタンスを作る */
        public Card(int suit,int number) {
            this.suit=suit;     
            this.number=number;
        }
        
        /**
         * 絵柄を取得する
         * 
         * @return 絵柄
         */
        public int getSuit() {
            return suit;
        }
        
        /**
         * 数字を取得する
         * 
         * @return 数字
         */
        public int getNumber() {
            return number;
        }
        
        /**
         * カードの整数表現を返すメソッド
         */
        public static int getIndex(int suit,int number) {
            int serialnumber=0;
            switch(suit) {
            case 0:serialnumber = number-1;break;
            case 1:serialnumber = number+12;break;
            case 2:serialnumber = number+25;break;
            case 3:serialnumber = number+38;break;
            case -1:serialnumber = -1;break;
            }
            return serialnumber;
        }
        
        /**
         * カードの文字列表現を返すメソッド
         */
        public static String getString(int suit,int number) {
            String stringsuit = null,stringnumber = null,stringtrump;
            switch(suit) {
            case 0:
                stringsuit = "スペード";
                break;
            case 1:
                stringsuit = "ダイヤ";
                break;
            case 2:
                stringsuit = "ハート";
                break;
            case 3:
                stringsuit = "クラブ";
                break;
            case -1:
                stringsuit = "ジョーカー";
                break;
            }
            
            if(number==1) {
                stringnumber = "A";
            }
            if(number==2) {
                stringnumber = "2";
            }
            if(number==3) {
                stringnumber = "3";
            }
            if(number==4) {
                stringnumber = "4";
            }
            if(number==5) {
                stringnumber = "5";
            }
            if(number==6) {
                stringnumber = "6";
            }
            if(number==7) {
                stringnumber = "7";
            }
            if(number==8) {
                stringnumber = "8";
            }
            if(number==9) {
                stringnumber = "9";
            }
            if(number==10) {
                stringnumber = "10";
            }
            if(number==11) {
                stringnumber = "J";
            }
            if(number==12) {
                stringnumber = "Q";
            }
            if(number==13) {
                stringnumber = "K";
            }
            if(number==0) {
                stringnumber = "";
            }
            
            stringtrump = stringsuit+stringnumber;
            
            return stringtrump;
        }
        
        /**
         * カード情報を整数表示に変換するメソッド 
         */
        public int toIndex() {
            int serialnumber = getIndex(suit,number);
            return serialnumber;
        }
        
        /**
         *  カード情報を文字列表示に変換するメソッド 
         */
        @Override
        public String toString() {
            String stringtrump = getString(suit,number);
            return stringtrump;
        }
        
        /**
         *  カード情報を画面に出力するメソッド
         */
        public void show() {
            System.out.println(toString());
        }
        
    }
    
[/code]

**↓テストクラス**

[code]

    import junit.framework.TestCase;
    
    /**カードデッキクラスのテストクラス*/
    public class CardDeckTest extends TestCase {
        // すべてのテストメソッドで用いるデッキのインスタンス
        private CardDeck deck,deck1,deck2,deckJ,deck4,deckEmpty;
        // すべてのテストメソッドで用いるカードのインスタンス
        private Card spadeA, diamond10, heartQ, clubK,joker;
    
        /**
         * 各テストメソッドの実行の前処理
         */
        protected void setUp() throws Exception {
            // いくつかテスト用のカードインスタンスを作っておく．
            spadeA = new Card(0, 1); 
            diamond10 = new Card(1, 10); 
            heartQ = new Card(2, 12); 
            clubK = new Card(3, 13);
            joker = new Card(-1,0);
            
            // いくつかテスト用のデッキインスタンスを作っておく．
            deckEmpty = new CardDeck();
            deck = new CardDeck();
            deck1 = new CardDeck();
            deck2 = new CardDeck();
            deckJ = new CardDeck();
            deck4 = new CardDeck();
            
            deck1.addCard(spadeA);
            deck1.addCard(diamond10);
            deck1.addCard(heartQ);
            deck1.addCard(clubK);
            
            deck2.addCard(spadeA);
            deck2.addCard(diamond10);
            deck2.addCard(clubK);
            
            deckJ.addCard(joker);
            
            deck4.addCard(spadeA);
            deck4.addCard(diamond10);
            deck4.addCard(heartQ);
            deck4.addCard(clubK);
            
            for(int i=0;i<4;i++) {
                for(int j=1;j<14;j++) {
                    Card card = new Card(i,j);
                    deck.addCard(card);
                }
            }
            
        }
    
        protected void tearDown() throws Exception {
            
        }
        
        public void testCreateFullDeck() {
            deckEmpty.createFullDeck();
            assertEquals(deck,deckEmpty);
        }
        
        public void testAddJoker() {
            deckEmpty.addJoker();
            assertEquals(deckJ,deckEmpty);
        }
        
        public void testClear() {
            deck1.clear();
            assertTrue(deckEmpty.equals(deck1));
        }
    
        public void testShuffle() {
            deck4.shuffle();
            assertNotSame(deck1, deck4);
        }
    
        public void testAddCardCard() {
            deckEmpty.addCard(joker);
            assertTrue(deckJ.equals(deckEmpty));
        }
    
        public void testAddCardIntCard() {
            deck2.addCard(3,heartQ);
            assertEquals(deck1,deck2);
        }
    
        public void testTakeCard() {
            assertEquals(deckEmpty,deckJ.takeCard());
        }
    
        public void testTakeCardInt() {
            assertEquals(deck2,deck1.takeCard(3));
        }
    
        public void testSeeCard() {
            assertEquals(joker,deckJ.seeCard(1));
            assertEquals(diamond10,deck1.seeCard(2));
        }
    
        public void testSerchCard() {
            assertEquals(1,deck1.serchCard(0, 1));
            
        }
    
        public void testIsEmpty() {
            assertEquals(true,deckEmpty.isEmpty());
            assertEquals(false,deck1.isEmpty());
        }
    
        public void testSize() {
            assertEquals(4,deck1.size());
        }
    
    }
    
    
[/code]


CC BY-SA 4.0
2022-07-18T21:27:27.090
90066
2022-07-18T23:40:28.890
2022-07-18T23:00:27.267
2808
53588
question
java junit
Javaのjunit3でのテストがうまくいかない。


> テストした12個のメソッドのうち8個が失敗（一つは失敗がかくれているようなので実質9個）になります。

がどれを指しているのか分かりませんでした(質問コードを実行すると **全て** 失敗します)が、質問コードは次の2点誤っています。  
これらを修正することでテストを通すことが出来ます。

1.  
テストコードでは `CardDeck` 及び `Card` を `equals`(`assertEquals`) で評価していますので、それぞれのクラスで
`equals`(及び `hashCode`)を override する必要があります。

次のコードは Eclipse の機能で自動生成したものです:

[code]

    public class CardDeck {
    
        // ...
    
        @Override
        public int hashCode() {
            return Objects.hash(cards);
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            CardDeck other = (CardDeck) obj;
            return Objects.equals(cards, other.cards);
        }
    }
    
[/code]

[code]

    public class Card {
    
        // ...
    
        @Override
        public int hashCode() {
            return Objects.hash(number, suit);
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Card other = (Card) obj;
            return number == other.number && suit == other.suit;
        }
    
    }
    
[/code]

  2. 

`testTakeCard` では `deckEmpty`(`CardDeck` 型) と `deckJ.takeCard()` の戻り値(`Card`
型) を比較していますので常にテストが失敗します。  
ここで比較したいのは、jokerカードではなく、jokerカードを抜き取ったデッキの方だと思いますので、テストコードは次のようになります:

[code]

        public void testTakeCard() {
            // joker だけが入った deck から 1枚抜き取る
            deckJ.takeCard();
            // 空の deck と比較
            assertEquals(deckEmpty, deckJ);
        }
    
[/code]

`testTakeCardInt` も同様です:

[code]

        public void testTakeCardInt() {
            deck1.takeCard(3);
            assertEquals(deck2, deck1);
        }
    
[/code]


CC BY-SA 4.0
2022-07-18T23:40:28.890
90070
2022-07-18T23:40:28.890
2808
90066
answer