-4

I'm writing a card game and have a Card class and a Playable class. Playables represent collections of cards that a player might choose to play for a given game state. I'm testing a function that gets a collection of legal Playables. My approach is to manually construct the correct answer and then assert that it is equal to the collection returned by my function.

Here's my setup function. cards is a private member of type List<Card>.

@Before
    public void setup() {
        cards = new ArrayList<Card>();
        cards.add(new Card(Suit.HEARTS, CardValue.ACE));
        cards.add(new Card(Suit.DIAMONDS, CardValue.ACE));
        cards.add(new Card(Suit.CLUBS, CardValue.ACE));
        cards.add(new Card(Suit.SPADES, CardValue.ACE));
        cards.add(new Card(Suit.CLUBS, CardValue.EIGHT));
        cards.add(new Card(Suit.HEARTS, CardValue.EIGHT));
        cards.add(new Card(Suit.SPADES, CardValue.EIGHT));
        cards.add(new Card(Suit.DIAMONDS, CardValue.SIX));
        cards.add(new Card(Suit.SPADES, CardValue.SIX));
        hand = new Hand(cards);
    }

Here's the test case.

@Test
public void testGetLegalDoubles() throws Exception {
    Card toBeat = new Card(Suit.CLUBS, CardValue.NINE);
    Set<Playable> correct = new HashSet<Playable>();
    Collection<Card> doubles1 = Arrays.asList(new Card[] {cards.get(0), cards.get(1)});
    Collection<Card> doubles2 = Arrays.asList(new Card[] {cards.get(0), cards.get(2)});
    Collection<Card> doubles3 = Arrays.asList(new Card[] {cards.get(0), cards.get(3)});
    Collection<Card> doubles4 = Arrays.asList(new Card[] {cards.get(1), cards.get(2)});
    Collection<Card> doubles5 = Arrays.asList(new Card[] {cards.get(1), cards.get(3)});
    Collection<Card> doubles6 = Arrays.asList(new Card[] {cards.get(2), cards.get(3)});
    Playable move1 = new Playable(doubles1, PlayMode.DOUBLES, cards.get(0));
    Playable move2 = new Playable(doubles2, PlayMode.DOUBLES, cards.get(0));
    Playable move3 = new Playable(doubles3, PlayMode.DOUBLES, cards.get(0));
    Playable move4 = new Playable(doubles4, PlayMode.DOUBLES, cards.get(1));
    Playable move5 = new Playable(doubles5, PlayMode.DOUBLES, cards.get(1));
    Playable move6 = new Playable(doubles6, PlayMode.DOUBLES, cards.get(2));
    correct.add(move1);
    correct.add(move2);
    correct.add(move3);
    correct.add(move4);
    correct.add(move5);
    correct.add(move6);
    Set<Playable> doubles = hand.getLegalNOfAKind(2, toBeat);
    assertEquals(doubles, correct);
}

This test case is failing, but I've tried printing out the contents of doubles and correct and they match - my toString() for Playable implementation shows all fields of these classes. I've also overridden equals() and hashCode() for Card and Playable as shown below (autogenerated by Eclipse).

Card:

    @Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((suit == null) ? 0 : suit.hashCode());
    result = prime * result + ((value == null) ? 0 : value.hashCode());
    return result;
}

@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;
    if (suit != other.suit)
        return false;
    if (value != other.value)
        return false;
    return true;
}

Playable:

    @Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((cards == null) ? 0 : cards.hashCode());
    result = prime * result + ((highCard == null) ? 0 : highCard.hashCode());
    result = prime * result + ((playmode == null) ? 0 : playmode.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Playable other = (Playable) obj;
    if (cards == null) {
        if (other.cards != null)
            return false;
    } else if (!cards.equals(other.cards))
        return false;
    if (highCard == null) {
        if (other.highCard != null)
            return false;
    } else if (!highCard.equals(other.highCard))
        return false;
    if (playmode != other.playmode)
        return false;
    return true;
}

My suspicion is that something is off with how I'm constructing correct - maybe how I'm referencing cards?

BobbyPin
  • 59
  • 6
  • 1
    Does `hand.getLegalNOfAKind()` use `List` for first parameter of `Playable` constructor or some other collection? Code of that method should be part of the question. – Jiri Tousek Jul 15 '17 at 14:13
  • 1
    Please provide a [mcve]. Note this does not mean to post all of your code. It means to post code which anyone can compile and get the same results which you are talking about. – Code-Apprentice Jul 15 '17 at 14:21
  • your `.equals()` method does nothing but compare object **identity**, you need to read up on the difference between `==` and `.equals()` they are **not** the same. The duplicates should explain the differences. –  Jul 15 '17 at 15:18
  • [What does your step debugger tell you?](http://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) –  Jul 15 '17 at 15:19
  • Please read [How do I ask a good question?](http://stackoverflow.com/help/how-to-ask) before attempting to ask more questions. [Your code is incomplete as there are classes being used that could be incorrect as well as all the incorrect code you have already posted.](https://stackoverflow.com/help/mcve) –  Jul 15 '17 at 15:20

1 Answers1

-2

It's tricky to get the full picture here as per other comments. As it looks like you are passing an array of cards into the Playable constructor, are you storing them in Playable as an array? If so this could be your problem in Playable.equals

} else if (!cards.equals(other.cards))
    return false;

will always be false (example);

final Integer[] is1 = new Integer[]{1};
final Integer[] is2 = new Integer[]{1};
Assert.assertFalse(is1.equals(is2));

Collections will save you some work here so you could store cards as an ArrayList in Playable;

public class Playable {
    List<Card> cards;

    public Playable (Card[] cards, other params....) {
        ....
        this.cards = new ArrayList();
        for (Card card : cards) { this.cards.add(card); }
    }

and in your equals have something like (you'll need to sort them first if you want to use .equals on a list):

    public boolean equals () {
       .....
       .....
       if (cards.containsAll(other.cards) && other.cards.containsAll(cards) {
           return true;

I would recommend a simple test case for your card.equals() to be double sure that works. As an observation, its not critical here as you are using enums but it's always a good idea to use .equals rather than ==

if (suit != other.suit)

would be better written as

if (!suit.equals(other.suit))

Hope this helps!

GrumpyWelshGit
  • 587
  • 4
  • 14
  • "As it looks like you are passing an array of cards into the Playable constructor" - false - they're using `Arrays.asList()` – Jiri Tousek Jul 15 '17 at 15:26