In my Beyond Frameworks talk, I explained how a component-based architecture can help answer some of the important (i.e. expensive!) questions you might face when creating long-lived apps that rely on a PHP framework. In this series of blog posts, I’m going to look at how to go about creating and working with components.
I’m now going under the bonnet of our components, and looking at the different file roles that the PEAR installer expects to find when we distribute our component as a PEAR-compatible package. One of the most important file roles allows you to ship your tests with your package – and it’s vital that this is something that you get in the habit of doing routinely.
Test Your Code, And Ship Your Tests
If you want other developers to re-use your code in their projects, it is essential that you earn their trust. Trust has to be earned over time, by establishing a track record of dependability. There are many things you need to do to establish such a reputation, such as semantic versioning to flag backwards-compatibility breaks, and writing unit tests to prove that your code works as expected.
Although the PEAR Installer has long supported shipping unit test code, to date the PHP community hasn’t really embraced this, and it is still very rare for a PEAR package to include unit tests when downloaded. This is also compounded by unfortunate legacy choices in some Linux distributions (ubuntu bug, fedora bug), where unit test code currently ends up being installed under the same directory tree as the main code from the PEAR packages – something that only really matters since the PHP Community started to adopt PSR-0 as the standard for autoloading.
What Are PHP Tests?
PHP tests (the ‘test’ file role supported by the PEAR Installer) are executable tests. There is currently no formal standard for these tests; however, PHPUnit has emerged as the community’s de facto standard for unit tests, and is the approach that the PHP components skeleton supports out of the box to make life much easier for you.
Just as important as shipping tests is making sure that it is extremely easy for someone who knows nothing about your code to safely and reliably execute any tests that you ship. The components skeleton handles much of this for you, by including a PHPUnit bootstrap.php file, and a build.xml file with full instructions on how to execute the tests.
However, it is important that you write your tests in a way that doesn’t rely on anything that your users won’t have installed or configured.
Where Do Tests Go Inside Your Component’s Structure?
If we look at the CommandLineLibrary component, you’ll find that the unit test files live in the src/tests/unit-tests/ folder:
- The folder structure underneath src/tests/unit-tests exactly matches the folder structure for both PHP scripts and PHP files under the src/ folder.
- Each unit test script is designed for PSR-0 autoloading, just like the PHP scripts that they test.
- Each unit test script ends in the word ‘Test’. This is a convention that is supported in IDEs such as Netbeans.
Where Does The PEAR Installer Install The Tests?
When you use the PEAR installer to install your component:
$ pear install phix/CommandLineLib
all of the test files get installed into /usr/share/php/tests/<package-name> on your computer:
The PEAR installer’s behaviour here is different to both command-line scripts and PHP code; the installer creates a sub-folder with the name of your package, and then installs your test files into this sub-folder, and not into the main test_dir folder. This isn’t a problem in practice, as long as you are aware of the different behaviour here.
The test file src/php/unit-tests/Phix_Project/CommandLineLib/CommandLineParserTest.php therefore ends up installed onto your computer as /usr/share/php/tests/CommandLineLib/Phix_Project/CommandLineLib/CommandLineParserTest.php.
There’s always the possibility that some Linux distros (and Mac OS X) will install doc files into a different folder. You can see where the PEAR installer will put these files on your computer by running:
$ sudo pear config-show | grep test_dir PEAR test directory test_dir /usr/share/php/tests
What About Other Kinds Of Test Code?
In the PHP component skeleton, the src/tests/functional-tests folder is available for anyone who wants to add any automated testing to prove that their app works. Selenium is a tool that might help with this.
There’s also the src/tests/integration-tests folder available for anyone who wants to maintain a strict separation between unit tests (which, technically, should prove that a single class works as required) and integration tests (which, technically, should prove that a collection of classes work together as required, especially across system boundaries).
At the time of writing, the component skeleton doesn’t do anything with code inside these folders. Patches are most welcome!