Having a solid build process in place is generally viewed as a must for an application of any decent size, with any number of developers, to be a success. The process generally entails multiple steps, such as retrieving the code from the source repository of choice, compiling the code, executing unit tests, and generating documentation via comments found in the code. When setting up this process for a project written in PHP, there is no code compilation, meaning that all errors are found at run time. Personally I feel this makes unit testing even more important. While the end goal for this side project for the Eddy Framework is a completely automated build process, currently there is only a manual build process in place. This works quite well actually, and in this post I will describe how I set up a manual build process for PHP using PHPUnit and PHPDoc.
Getting PEAR Working With XAMPP
I wanted to use PEAR to retrieve both PHPUnit and PHPDoc, so after some very short googling I came across this blog article that describes the processing of getting PEAR and XAMPP working together properly.
Setting Up PHPDoc
The earlier in your project that you can start commenting your code, especially in a standard format such as that recognized by PHPDoc the easier it will be to reap the full benefit of documentation generators. By starting early, properly commenting your code will become second nature, and with each change to method signatures, each new clss that is added, your programs documentation can be automatically updated.
If you find yourself knee, waist or even neck deep in code that is not properly commented, it is still not too late. You can always start by commenting all new methods, or any method that you update, refactor, step through, you name it. Generally I find that when starting to comment an existing code base, it is also good practice to start with documenting your public interfaces, classes, methods and properties. The reason for this is two fold. For starters, this is the code that is more than likely being called from consumers of your application. The second reason is that this will allow you to take another look at your public access points, and really consider whether or not they actually need to be public. That however, is a topic for another posting.
For information on installing PHPDoc, there is an excellent quick start tutorial which can be found on the offical PHPDoc site. The installation process is a breeze, and the command line interface is very easy to use. PHPDoc is documented extremely well, after all how good would a documentation tool be if it was not properly documented? For more information on PHPDoc, the how to tutorial can be found here, also on the offical PHPDoc site.
Unit Testing with PHPUnit
Like proper code comments, the sooner you can start unit testing your application the better. Die hard unit testers live by the motto of "never write a line of code until you have a failing unit test first". Performing a deep dive into Unit Testing methodology is also a topic for another article, but in short you start off by writing a unit test. When the unit tests are run the new test will fail, since there is no corresponding code. At this point you write the code to fix the unit tests. Once the unit test pass, its time to write a new unit test for the next piece of functionality, the test fails, you implement the code, repeat. Don't forget to refactor the whole time.
Getting PHPUnit up and running was a little more difficult than PHPDoc. The actual installation was simple, as it is covered well on the PHPUnit site. The examples however seemed to be a little simplistic. They all assume that you will be running PHPUnit from within the same folder as the unit test. While this may be the case, it did not fit in well with my needs. After poking around in the documentation, I was able to resolve this issue, but it was not explained in the examples. This however is not a big deal, a little RTFM never hurt nobody.
After I had written by first unit test that passed, it was time to tie the unit tests and documentation together.
Creating build.php
The build.php file that ships with the Eddy Framework performs three main steps when run from the command line. First it executes the unit tests that ship with log4php, an excellent logging provider from apache. While the port from log4j is still an incubation project, log4php works very well, with 13 passing unit tests and 7 that are ignored at the time of writing.
The second step is to execute the unit tests for the individual pieces of the Eddy Framework. If build.php is run often and frequently, it will report when a unit test either passes or fails, which will let the developer know if a change they made broke any existing functionality. With a solid suite of unit tests, you can feel comfortable about making a change in the code, since you will know what was impacted as soon as build.php is run.
The last step in the manual build process is to kick of PHPDoc, which runs through the code base and generates full documentation for your program. Command line options are passed to PHPDoc to tell it what folders or files to ignore, what format to generate the documentation in (html with frames, html without frames, xml, chm, pdf are all supported), and finally where to place the generated files. For the Eddy Framework I chose HTML, and place the documentation on the public site. For me to real benefit to this is the generated documentation serves as the API Docs for the framework. No longer do I need to go back and constantly update static documentation with each change I make - PHPDoc handles that for me.
Calling build.php
Now that build.php is set up, all a developer needs to do is run the PHP script from the command line. The script takes one optional argument, which is the path that PHPDoc and PHPUnit were installed into by PEAR. If the folder is not in your PATH, then you can specify it to the build script. Once the build script runs, you will easily be able to tell if you latest change broke and existing unit tests, if your new unit tests ran successfull, and finally your documentation will be generated.
The full code to the most current version of build.php can be found here.
Conclusion
Having a build process, even if a manual one for starters can really bring a huge benefit to your project. With out much extra work you can catch bugs early and keep your documentation up to date. I always think of the analogy of carrying the food or carrying the trash on a 90 day hike. When you carry the food, sure you have a little more work up front, but as the hike goes on your job gets easier and easier. If you carry the trash, you can blaze down the trail for the first part of the hike, but as you get toward the end your job really gets hard when you are already tired and exhausted. Using unit tests and properly commenting your code is just like carrying the food - you do have to perform a little more work up front, but once the procedures are in place your job gets easier and easier. Without unit tests and code comments, you crank more code initially, but weeks or months into your project when you forget what a certain method does, or what the upstream and downstream consumers are - all the sudden you find yourself carrying the trash. You are never going to be quite sure of what your change is actually going to impact, and worse months later you will have even a greater risk of introducing a breaking change. |