mardi 4 août 2015

How to use Junit for testing long arrays?

I'm just starting out with unit tests (junit). I saw a couple of videos from Roy Osherove, where he talked about good practices. Since I'm pretty new to this subject, I feel totally lost. Below is a short example of my code, which is then followed by how I tested so far and how I would create a fitting junit test. In essence I'm creating a card deck with 52 cards. I want to test if the deck contains all 52 cards, when I create a new "deck" object.

I may have some errors in my code, but it's more about the logic (see the questions in the end).

The production code


Imagine I want to create a common card deck, which consists of 4 suits and 13 ranks. Let's also assume that I created a "card" class and a "deck" class, that contains an instance variable, that's an array consisting of 52 cards.

The "card" class:

public class card {

private String[] suits = {"h", "s", "c", "d"};
private String[] ranks = {"2","3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A"};

private String suit, rank;


public card (int rank, int suit) {
    this.suit = this.suits[suit];
    this.rank = this.ranks[rank];
}

public String getRank () {
    return rank;
}

public String getSuit () {
    return suit;
}
}

The "deck" class:

public class deck {

private card[] deckCards = new card[52];

public deck() {

    int i = 0;

    for(int suit = 0; suit<4; suit++) {
        for(int rank=0; rank<13; rank++) {
            this.deckCards[i] = new card(rank,suit);
            i = i+1;
        }
    }

}

public card[] getDeckCards() {
     return deckCards;
}
}

The Test


So, if I want to create a junit test, my test would look like the follow right?

public class Main {

public static void main(String[] args) {

    deck deck = new deck();
    int counter = 0;

    for (int i = 0; i<52; i++) {

        if (deck.deckCards[i] != null) counter++;


    }

    System.out.println("Cards in deck: " + counter);

    for (int i = 0; i<52; i++) {
        if (deck.deckCards[i] != null) System.out.println(deck.deckCards[i].getRank() + deck.deckCards[i].getSuit());
    }



}
}

As a result I would get something like this:

  • Cards in deck: 52
  • 2h,3h,4h,5h,6h,7h,8h,9h,Th,Jh,Qh,Kh,Ah, 2s,3s,4s,5s,6s,7s,8s,9s,Ts,Js,Qs,Ks,As, 2c,3c,4c,5c,6c,7c,8c,9c,Tc,Jc,Qc,Kc,Ac, 2d,3d,4d,5d,6d,7d,8d,9d,Td,Jd,Qd,Kd,Ad

Now I can look at all the cards and I would see that everything worked out like i wanted it. Obviously that's not how you test..

Now, if I wanted to create a Junit Test, I would do the following:

@Test
public void testDeck() {

    // create the expected value; which is 52 cards
    card[] expected = {new card(0,0),
                       new card(1,0),
                       new card(2,0),
                       ...          ,
                       new card(12,0),
                       new card(0,1),
                       ...          ,
                       new card(12,1),
                       new card(0,2),
                       ...          ,
                       new card(12,2),
                       new card(0,3),
                       ...          ,
                       new card(12,3)}



    // instantiate the deck
    deck carddeck = new deck();
    card[] actuals = carddeck.getCardDeck();

    //assert
    assertArrayEquals(expected, actuals);
}

Now, I have a few questions:

  1. Roy says that we shouldn't use ANY logic in a test method/case. Obviously I do use logic in to create my "expected", namely the constructor of the card class. But how can I use hard coded values? Easy when I do have string or a int as the expected, but what if I do have more complex structures, like this object?
  2. What if my card deck would have 1000 cards. Then it would be impossible to create an array with 1000 fields manually. But how could I test it otherwise?

Thanks so much for helping me :)

Aucun commentaire:

Enregistrer un commentaire