Using var_export to get Testing Data

When you’re working with legacy code some times you need to add testing to an additional piece of form processing that has no tests. I find it helpful to break out the form processing code into it’s own class so it’s easier to test but if you’re not lucky it could be a large complicated form with lots of options so setting up a test case can be difficult. var_export is an excellent solution to get the posted data out so you can use it.

What’s var_export

var_dump outputs information about a variable that are helpful for debugging but var_export outputs a parsable string of a variable so it can be reused in PHP.

<?php
$data = array(
    'test1' => 'test',
);

var_export($data);

Output:

array (
  'test1' => 'test',
)

Example

So how do we use this for testing?

Let’s look at this following example:

<?php
class ItemController extends Controller
{
    public function edit()
    {
        // permissions checks (hopefully)

        $item = new Item();
        $item
            ->setName($_POST['name'])
            ->setDescription($_POST['description'])
            ->save();

        // do something else with $item
    }
}

1. Create a Test

First things we want to do is create a test with a basic check to make sure we’re on the right path:

<?php
class ItemTest extends TestCase
{
    public function testCanProcessDataFromExistingForm()
    {
        $formProcessor = new ItemFormProcessorFromExistingForm();
    }
}

2. Generate Some Test Data

Next we need to generate some test data. I do this by filling out the form with every weird option that might exist. Then inside the controller I add three lines:

<?php
echo "<pre>"; // this makes the text easier to copy and paste directly from your browser
var_export($_POST); // export the data
exit; // stop processing so we can get what we want without side effects

In our example this looks like:

<?php
class ItemController extends Controller
{
    public function edit()
    {
        // permissions checks (hopefully)

        echo "<pre>";
        var_export($_POST);
        exit;

        $item = new Item();
        $item
            ->setName($_POST['name'])
            ->setDescription($_POST['description'])
            ->save();

        // do something else with $item
    }
}

Then we’ll copy and paste the output directly into our test:

<?php
class ItemTest extends TestCase
{
    public function testCanProcessDataFromExistingForm()
    {
        $formProcessor = new ItemFormProcessorFromExistingForm();

        $post = array (
            'test1' => 'test',
        );
    }
}

3. Break Out the Form Processing Logic

Next we need to create a new function in our ItemFormProcessorFromExistingForm class to process the data and insert it into the controller.

<?php
class ItemFormProcessorFromExistingForm
{
    public function processData($postData)
    {
        $item = new Item();
        $item
            ->setName($postData['name'])
            ->setDescription($postData['description'])
            ->save();
    }
}
<?php
class ItemController extends Controller
{
    public function edit()
    {
        // permissions checks (hopefully)

        $processor = new ItemFormProcessorFromExistingForm();
        $processor->processData($_POST);

        // do something else with $item
    }
}

4. Get Your Test Running

Now that we have the function broken it’s own function it’s important to make sure it the test is running. In a lot of cases you might need to setup instances of additional classes (maybe the logged in user?). The important thing is to get the test running

5. Make Sure You Aren’t Missing Any Critical Code

The next step is to generate a code coverage report on the tested function and verify you’re covering all the important parts. I try to get to at least 90% code coverage and make sure all the weird looking parts are covered.

5. Refactor

Now it’s time to clean up the legacy code!