4

I am writing an application using the PHP CodeIgniter Framework. I am trying to test the application using CI_Unit, by extension PHPUnit. To test a model, I am trying to load a YAML data provider as defined in the PHPUnit documentation, I receive an error. If I fudge the data provider object, I get another error. If I provide it a vanilla PHP array, it runs as expected.

What am I doing wrong? What is the correct way to do this? Below are my results:

If I return the object PHPUnit_Extensions_Database_DataSet_YamlDataSet of the Yaml file below, I get:

Data set "Clients" is invalid.

If I loop around the object returned by PHPUnit_Extensions_Database_DataSet_YamlDataSet and return that: I get this error:

PHPUnit_Framework_Exception: Neither "models.php" nor "models.php" could be opened. in /Users/eric/pear/share/pear/PHPUnit/Util/Skeleton/Test.php on line 100

If I provide it a vanilla PHP array, the tests run just fine. The command I use to run the tests is:

phpunit models

Below is an example of my YAML file.

Clients:
    1:
        client_id: 1
        client_information: "info number 1"
        client_key: 48fb10b15f3d44a09dc82d
    2:
        client_id: 2
        client_information: "info number 2"
        client_key: 48fb10b15f3d44addd

I am using PHP 5.3, PHPUnit 3.6.10, DBUnit 1.1.2, CodeIgniter 2.1.0, and CI_unit associated with CI 2.1.0.

Edit: Attached is my models/Test.php file:

/**
 * test_add_client
 * @dataProvider add_client_provider
 */
public function test_add_client($client_id,$company_id,$software_id,$client_information,$client_key)
{
    $data = array('software_id' => $software_id,
                  'client_information' => $client_information,
                  'client_key'         => $client_key);
    try {
        $id = $this->_m->add_client($company_id,$data);
        $this->assertEquals(true, is_int($id));
    } catch (Exception $e){
        $this->assertEquals(true,false);
    }
}

public function add_client_provider()
{
    $result = new PHPUnit_Extensions_Database_DataSet_YamlDataSet(
        dirname(__FILE__)."/../fixtures/Clients.yml");

    // Case #1 returns this $result
    //return $result;

    foreach($result as $key => $value){
        if($key == 'Clients'){
            $substructure = $value;
        }
    }

    // Case #2 return the inner structure that is the table
    return $substructure;

    // Case #3 return an array of arrays
    $data = array(
                array(1,1,1,'test','text 2'),
                array(1,2,1,'test 3', 'test 3'));
    return $data;
}
Eric Cope
  • 877
  • 1
  • 12
  • 25

2 Answers2

5

As described in the PHPUnit documentation on Data Providers:

A data provider method must be public and either return an array of arrays or an object that implements the Iterator interface and yields an array for each iteration step. For each array that is part of the collection the test method will be called with the contents of the array as its arguments.

Based on your Test.php source code, it seems you want something like this:

    /**
     * test_add_client
     * @dataProvider add_client_provider
     */
    public function test_add_client($data)
    {
        $company_id = 0;
        $id = $this->_m->add_client($company_id, $data);
        $this->assertEquals(true, is_int($id));
    }

    public function add_client_provider()
    {
        $result = new PHPUnit_Extensions_Database_DataSet_YamlDataSet(
            dirname(__FILE__)."/../fixtures/Clients.yml");          

        // Return the Clients data
        $clients = array();
        $tbl = $result->getTable('Clients');
        for ($i = 0; $i < $tbl->getRowCount(); $i++) {
            $clients[] = $tbl->getRow($i);
        }
        return $clients;
    }

Seems PHPUnit should provide a function to turn a dataset table directly in to an array of arrays, but I didn't see anything after a quick glance.

The phpunit.xml file is irrelevant, and can be removed from your question, as far as I can tell.

You also don't need the try/catch block in the PHPUnit test method - PHPUnit will take care of that for you.

Note that your $company_id wasn't defined, so I just set it to 0. Your method arguments & YAML data above don't seem to match up fully above either, but that should be easy to fix.

By passing an array in to the test function, which gets passed immediately to the add_client method, your code is a bit more DRY as well.

mkopala
  • 1,262
  • 3
  • 12
  • 15
  • Since `PHPUnit_Extensions_Database_DataSet_YamlDataSet` is supposed to implement an Iterator object, I'd like to know how to pass it directly, but this meets my needs. Thanks! – Eric Cope May 19 '12 at 04:07
  • 1
    The iterator object that it provides just lets you iterate over the tables in the dataset. This won't get you the data from the rows, which you appear to need. – mkopala May 19 '12 at 08:20
0

PHPUnit Provider Autoloader

Magic helper to autoload CSV, JSON, PHP, XML and YAML data provider in PHPUnit.

Instalation

composer require redaxmedia/phpunit-provider-autoloader

Usage

Create the TestCaseAbstract for your testing suite:

<?php
namespace ExampleProject\Tests;

use PHPUnitProviderAutoloader;

/**
 * TestCaseAbstract
 *
 * @since 2.0.0
 *
 * @package ExampleProject
 * @category Tests
 */

abstract class TestCaseAbstract extends PHPUnitProviderAutoloader\TestCaseAbstract
{
    /**
     * directory of the provider
     *
     * @var string
     */

    protected $_providerDirectory = 'tests' . DIRECTORY_SEPARATOR . 'provider';

    /**
     * namespace of the testing suite
     *
     * @var string
     */

    protected $_testNamespace = __NAMESPACE__;
}

Extend from TestCaseAbstract to autoload the ExampleTest{_testMethod}.{csv|json|php|xml|yml} file:

<?php
namespace ExampleProject\Tests;

/**
 * ExampleTest
 *
 * @since 2.0.0
 *
 * @package ExampleProject
 * @category Tests
 */

class ExampleTest extends TestCaseAbstract
{
    /**
     * testMethod
     *
     * @since 2.0.0
     *
     * @param string $expect
     *
     * @dataProvider providerAutoloader
     */

    public function testMethod(string $expect = null)
    {
        $this->assertEquals($expect, 'test');
    }
}

Read more

Related repository: https://github.com/redaxmedia/phpunit-provider-autoloader

Example integration: YAML test autoloads YAML class provider and YAML method provider

Henry Ruhs
  • 1,533
  • 1
  • 20
  • 32