Crafting Java with Test-Driven Development, Part 2: Testing Equality
All Things Tested Equally
In part 1 of this series, we created Deck and Card classes via tests. The starter test for the Deck class involved verifying that a deck contained 52 cards, and that the deck indeed contained each card as expected.
Listing 1 shows the test method from the DeckTest class we built last time. For each iteration through the dual-loop series, the test calls the contains method against the Deck object, passing in the current rank and suit.
Listing 1 testCreate method in DeckTest.
public void testCreate() { Deck deck = new Deck(); assertEquals(Deck.SIZE, deck.cardsRemaining()); for (Suit suit: Suit.values()) for (Rank rank: Rank.values()) assertTrue(deck.contains(rank, suit)); }
In the Deck class, the contains method simply loops through the ArrayList of cards, looking for a match on rank and suit, as shown in Listing 2.
Listing 2 Current version of Deck.
public class Deck { ... private List<Card> cards = new ArrayList<Card> (); public Deck() { for (Suit suit: Suit.values()) for (Rank rank: Rank.values()) cards.add(new Card(rank, suit)); } ... public boolean contains(Rank rank, Suit suit) { for (Card card: cards) if (rank == card.getRank() "" suit == card.getSuit()) return true; return false; } }
A better solution would be to implement the equals method on the Card class. Once we define equality for two cards, we can have the contains method simply delegate to the cards’ ArrayList.
We’ll tackle creating the equality method in two parts. In the first part, we’ll build the equality method incrementally by virtue of simple, sensible assertions. In the second part, we’ll ensure that it adheres to the contract for equality, as laid out in the Javadoc for the Object method equals.