Testing that array gets shuffled

Discussion of testing theory and practice, including methodologies (such as TDD, BDD, DDD, Agile, XP) and software - anything to do with testing goes here. (Formerly "The Testing Side of Development")

Moderator: General Moderators

Post Reply
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Testing that array gets shuffled

Post by Luke »

I really am rusty! Sheesh! I can't think of a good way to test this. Basically I have a deck of cards and I want to make sure that its shuffle() method shuffles the cards. The testing code doesn't have access to the internal array of the class though, so how do I test that the order isn't the same?

Code: Select all

$deck = new Cards\Deck;
$deck->shuffle(); // randomizes internal $deck->_cards;
// now how do I know it's shuffled?
I can't just test the top card, because it could, by chance, be the same card. And the class doesn't have any external access to the cards other than deal() which pops off the top card, so how do I test this? Should I add something like Cards\Deck::getCards() that returns the cards array?
User avatar
requinix
Spammer :|
Posts: 6617
Joined: Wed Oct 15, 2008 2:35 am
Location: WA, USA

Re: Testing that array gets shuffled

Post by requinix »

I keep bouncing between ideas but I know that I would try to avoid adding methods to the class just so you can write a more complete test suite.

Right now I'm thinking you can subclass Deck to provide the functionality you need specifically for testing.

Code: Select all

namespace Test\Cards;

class DeckTestHelper extends \Cards\Deck {
    public function getCards() {
        return $this->cards; // make sure $cards is protected
    }
}
Or even make the subclass be the test code itself.

My next choice would be to use existing functionality, even if the test code has to work a bit harder. Like if you still need a foreach on the Deck then you can build and compare an array of cards before and after the shuffle. But it's quite possible that you'll decide that foreaching (or otherwise iterating) over the cards in the deck doesn't make sense as an appropriate use case either - it's not like anyone should be able to thumb through the deck looking at what's there.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Re: Testing that array gets shuffled

Post by Luke »

Oooh I think I like your first idea. Thanks!
josh
DevNet Master
Posts: 4872
Joined: Wed Feb 11, 2004 3:23 pm
Location: Palm beach, Florida

Re: Testing that array gets shuffled

Post by josh »

You could serialize the results to a string and hash that. Shuffle & hash multiple times, then assert you have a minimum number of unique results. Regarding requinix's comment about avoiding a getCards() method on the class, there's nothing wrong with having that method. Why don't you want that method? If there's a temptation to get at some state during testing, there's probably a use to get at that state during production too. The need may not be immediate, but its often inevitable. e.g. maybe you need an audit feature for admins later on. Just like the test is auditing the cards, maybe an admin user needs to audit the cards after a game is played. Having the method doesn't hurt. Security concerns go in the controller, not the model which is the part you're testing.

Private state is a code smell IMO. Encapsulation isn't about disallowing the programmer from inspecting state. Its about allowing him to use the object without having to inspect the state.
Post Reply