canadianlover's avatar

PHPUnit test dealing 14 unique playing cards

So I have been stumped by this problem for a while now. I am creating a Pai Gow Poker website (for those of you who don't know what Pai Gow is, it's a game where two combined decks are shuffled. Seven cards are dealt to the player and seven for the dealer. The player and dealer make a high and low hand (the high out of 5 cards and the low 2), For more details look on the game's Wikipedia page.

I am writing a PHPUnit test which ensures that the 14 cards dealt are unique and all cards dealt for both hands contain no duplicates. When I run my PHHPUnit test in my Vagrantvo, I get the following error:

``

  1. Tests\Feature\GameTest::test_both_hands_have_unique_cards ErrorException: Object of class Closure could not be converted to string

/home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Support/Str.php:300 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Support/Str.php:281 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/QueryException.php:56 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/QueryException.php:39 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Connection.php:648 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Connection.php:607 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Connection.php:450 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Connection.php:404 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Query/Processors/Processor.php:32 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:2131 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:1236 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:677 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:642 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:511 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:148 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Support/Collection.php:260 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:149 /home/vagrant/Code/bitpaigow/vendor/laravel/framework/src/Illuminate/Database/Eloquent/FactoryBuilder.php:131 /home/vagrant/Code/bitpaigow/tests/Feature/GameTest.php:32``

I am using a ```for loop incrementing by 2 to select every second card dealt by the model factory. I elected to use this method because only from what I know so far, only 1 method can be used to generate models. I used static variables in the method, but I am not sure if this is the best way to go. I tried using faker to generate random playing cards, but PHPUnit said the maximum amount of retries exceeded and no unique cards were found. Here is the current code I have

GameTest.php


namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class GameTest extends TestCase
{
    use DatabaseMigrations;
    /**
     * A basic test example.
     *
     * @return void
     */
    public function setUp() {

        parent::setUp();

        $this->game = factory('App\Game')->create();
        $this->user = factory('App\User')->create();
        $this->hand = factory('App\Hand')->create(['player' => 1, 'user_id' =>  $this->user->id]);


    }

   public function test_both_hands_have_unique_cards()
   {

       $cards = factory('App\Card', 14)->create(['game_id' => $this->game->id, 'hand_id' => $this->hand->id]);

       for($i =0; $i <= 13; $i+=2) {
           $this->assertTrue(($cards[$i]->suite == $cards[$i++]->suite) && ($cards[$i]->value == $cards[$i++]->value));
       }


   }





}

ModelFactory.php



/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| Here you may define all of your model factories. Model factories give
| you a convenient way to create models for testing and seeding your
| database. Just tell the factory how a default model should look.
|
*/

/** @var \Illuminate\Database\Eloquent\Factory $factory */
$factory->define(App\User::class, function (Faker\Generator $faker) {
    static $password;

    return [
        'id' => $faker->randomNumber(3),
        'name' => $faker->name,
        'email' => $faker->unique()->safeEmail,
        'password' => $password ?: $password = bcrypt('secret'),
        'remember_token' => str_random(10),
    ];
});

$factory->define(App\Hand::class, function(Faker\Generator $faker) {

    return [

        'user_id' => function() {
            return factory('App\User')->create()->id;
        },
        'game_id' => function() {

            return factory('App\Game')->create()->id;

        },





    ];
});

$factory->define(App\Game::class, function(Faker\Generator $faker) {
    return ['user_id' => function () {
        return factory('App\User')->create()->id;

    }];
});

$factory->define(App\Card::class, function(Faker\Generator $faker) {
    static $cards = null;

    $cards = ['H' => range(1,13),
    'D' => range(1,13),
    'S' => range(1,13),
    'C' => range(1,13)];

    $pick_suite = ['H', 'D', 'S', 'C'];
    $selected_suite = $pick_suite[rand(1,3)];
    $selected_value = rand(0, count($cards[$selected_suite]));

    // select card

    $selected_card = $cards[$selected_suite][$selected_value];

    // unset form array

    unset($cards[$selected_suite][$selected_value]);



   return ['player_hand' =>
        ['hand_id' => function () {
           return factory('App\Hand')->create()->id();
       },
       'suite' => $selected_suite,


       'value' => $selected_value,

            'player' => function() {
                static $player = false;
                if($player) {
                    $player = false;
                    return true;
                } else {
                    $player = true;
                    return false;
                }

            },

]];
    });

0 likes
0 replies

Please or to participate in this conversation.