psmail's avatar

Testing: How to test the contents of a dataset for presence / absence of records

Hi. I hope this is not a naff question - here goes.

I know that testing apps like Codeception allow the functional testing of records in a database using command like seeRecord.

I have also seen example of integration and functional testing of the certain attributes of a recordset, such as first record, last record and record count.

But I don't think I have seen examples of tests for the entire contents of a dataset that might be returned by, say, a repo. Let's say a test dataset is 10 records long, how can I get a test (integration or functional, I imagine) to go through each of the 10 records in the dataset to check if a certain value is present (or absent)?

Thanks for reading.

0 likes
5 replies
thepsion5's avatar

This seems like a good case for using Codeception's helper classes. Basically, any functions you define in the relevant helper will be added to the Guy/Tester class when you run the build command, so you could define something like this in your helper:

public function seeAllRecordsInTheDatabaseHaveValue($table, $key, $value)
{
    $db = $this->getModule('Db')->driver; //I believe this is a PDO instance
    $query = "SELECT COUNT(*) AS count FROM $table WHERE $key = $value"
    //execute the query, get the count
    $fullQuery = "SELECT COUNT(*) AS count FROM $table";
    //get the full count, compare the two
    $this->assertEqual($fullQuery, $query, "The total rows in $table with $key matching $value is not equal to the total number of rows in the table.");
}

Next, run the build command, and in your cept file you should be able to do this:

$I->seeAllRecordsInTheDatabaseHaveValue('table, 'column', 'value');
1 like
psmail's avatar

Hi @thepsion5.

This is great, super useful. Before I mark it as the answer - does this mean that testing a recordset is not possible?

I ask because if testing a repo, it will return a recordset. If that recordset is deliberatley limited by, say, role or tenancy then it would be nice to test the nature and effectiveness of that limitation.

Your approach - which is great and I will use if there is not a recordset approach - tests the data in the database and not the repo result. So the repo is not so much tested ... it is more a parallel of test what the repo should do.

As always, thanks heaps.

1 like
thepsion5's avatar
Level 25

Oh, in that case I'd use an integration test. I have something similar set up for my big project at work. Obviously I've left out a lot of code but you should be able to get an idea of how it works.

class DatabaseVoterImportRepoTest extends GvtIntegrationTestCase
{
    public function _before()
    {
        $this->repo = \App::make('Gvt\Infrastructure\Voters\Repos\DatabaseVoterImportRepo');
        \DB::table('voters')->truncate();
    }

    /**
     * @test
     */
    public function it_finds_a_voter_based_on_import_id()
    {
        //helper method that generates and saves it to the repository with some default values
        $this->createVoter('name', 'TEST-IMPORT-1');

        $found = $this->repo->findByImportId('N-TEST-IMPORT-1');

        $this->assertNotNull($found);
    }

psmail's avatar

@nfauchelle - yeah, that's not it. I want to test a dataset returned by a repo, not a database.

@thepsion5 - mate, you've done it again :) And when I looked at it I went 'ahhhhh ...'. Much more simple than I thought. Thanks yet again.

Please or to participate in this conversation.