-
Notifications
You must be signed in to change notification settings - Fork 27
File Export
This is a tutorial for using the FileExport PHPUnit extension.
Unit testing can be painful. Building robust tests is time consuming, particularly when looking at large data structures. If you are validating large objects or arrays, this extension may help you. Rather than trying to break them down into small individual assert statements, you can simply make the call:
$this->assertExportCompare($someBigObjectOrArray);
This will compare the var_export of the element against a previously saved export file. These export files should be saved into your repository. They can be easily updated as your project changes. And you can reference the files to find exact output of methods in the future.
The file export PHPUnit extension is currently forked and awaiting merge into the master. To install now, the following parameters can be added to composer.json:
{
"repositories": [
{
"type": "git",
"url": "https://github.com/aiqui/phpunit-extensions"
}
]
"require": {
"etsy/phpunit-extensions": "dev-master"
}
}
Run composer install and be sure to include vendor/autoload.php in your PHP code to get the proper classes.
To use the file export class, extend the abstract class:
class ExampleTest extends \PHPUnit\Extensions\FileExport\TestCase {
public function test_getCaseOverview() {
$this->oSomeObj = new Whatever();
$this->assertExportCompare($this->oSomeObj->getCaseOverview());
}
}
This extension uses custom command-line options, but PHPUnit will throw an exception when encountering unknown options. So the options for this extension must be added at the end of the call, without any prefix hyphens.
There are two command-line options for saving the export files:
- save-exports - save the export files for one method
- save-all-exports - save all the export files for all methods
It's recommended that you use save-exports so that you can carefully compare you results, rather than saving all the exports at once via save-all-exports. Assuming your export files are saved in git, running git diff will quickly show you the changes.
The options must be placed after any standard PHPUnit options. For example:
phpunit --filter test_getCaseOverview Example.uut.php save-exports
The files are saved in a subdirectory named phpunit_exports in the same directory where phpunit is run. A subdirectory with name of the class is created inside of phpunit_exports. If the class uses PHP namespaces, the directory includes the namespaces separated by hyphens (to avoid problematic backslashes).
phpunit_exports/TopName-SubName-ExampleTest/test_getCaseOverview.1
The file simply contains the contents of var_export for that given variable. The file name has an index which will increment with each call to assertExportCompare in the same method (i.e. if you compare multiple structures, the same filename will be used, but the number will increment).
The export assertion takes the output of the variable via var_export, saving it to a temporary file, and comparing the output to the export file via a shell call to diff. When it fails, you would see something like this:
1) TopName\SubName\ExampleTest::test_getCaseOverview
Export file: phpunit_exports/TopName-SubName-ExampleTest/test_getCaseOverview.1
Differences found between exported file and variable
--- Exported file
+++ Actual variable
Extend your class like the example above, and build your test methods as normal. Whenever you hit a complicated structure, call assertExportCompare. Often there are dynamic elements to the structure that should be unset first, so that you are only comparing parts of the structure that will be the same with every call to phpunit.
Save your export files with either save-exports or save-all-exports. To be methodical, you normally would use the --filter option to select the method and save-exports at the end to save the export files.
This is the most critical step. Look carefully at the output of the exported file, and review every element. If there are any problems, fix your code and save again.
When you run phpunit normally, no export files will be saved, and it will compare against the existing saved export files.
If a difference is found and an exception is thrown, investigate the problem, fix your code and, if necessary, save your exported files again. Always carefully validate after saving.
When saving export files, if a difference is discovered between the old and new exports, the old export files are saved in a backup subdirectory that includes the date and time in the directory name. A message appears notifying the developer of the changes. If no differences are found, the backup export files are removed.
It's recommended that you save the export files under version control (e.g. git). Typically there is no need to save the backup directories; these should be removed after any changes have been investigated.
The export files can be used an documentation reference, providing developers with the exact output of a method.
Consistently validating complicated objects and arrays is easy with this extension. But that also removes the deliberate exercise of manually composing the assert statements for each value. Furthermore, developers can overlook problems if they are not paying attention to the differences in the export files. This can greatly reduced the time to build unit tests, but developers must diligently review any changed exports.