PHP Developers Network

A community of PHP developers offering assistance, advice, discussion, and friendship.
 
Loading
It is currently Mon May 22, 2017 4:19 pm

All times are UTC - 5 hours




Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: Thu Nov 08, 2012 4:19 pm 
Offline
The Ninja Space Mod
User avatar

Joined: Fri Aug 05, 2005 1:53 pm
Posts: 6424
Location: Paradise, CA
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?

Syntax: [ Download ] [ Hide ]
$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?


Top
 Profile  
 
PostPosted: Thu Nov 08, 2012 6:09 pm 
Online
Spammer :|
User avatar

Joined: Wed Oct 15, 2008 2:35 am
Posts: 6417
Location: WA, USA
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.
Syntax: [ Download ] [ Hide ]
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.


Top
 Profile  
 
PostPosted: Thu Nov 08, 2012 6:22 pm 
Offline
The Ninja Space Mod
User avatar

Joined: Fri Aug 05, 2005 1:53 pm
Posts: 6424
Location: Paradise, CA
Oooh I think I like your first idea. Thanks!


Top
 Profile  
 
PostPosted: Tue Jul 02, 2013 7:19 pm 
Offline
DevNet Master

Joined: Wed Feb 11, 2004 4:23 pm
Posts: 4872
Location: Palm beach, Florida
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.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB® Forum Software © phpBB Group