Saturday, September 5, 2009

Continuous Integration with Symfony, PHPUnit, CruiseControl and Selenium

Wow, that's a mouthful. Basically, we want to unit test our Symfony application with PHPUnit driving the nuts and bolts rather than completely using the built in lime tester. We also want to be lazy, I sure don't have the time to test my apps work in 8+ browsers now do I, isn't this smart?

I see lime as the unit tests for your controllers and views rather than a "functional" test. To me, a functional test is not complete until it is run in a browser. We also want to unit test our Doctrine or Propel child classes.

Setting up the entire process is beyond the scope of this blog, perhaps a small book? So, I'm just going to go into some of the finer points.

1) First install sfPHPUnitPlugin, this is the first step in getting your lib classes and tasks setup. This will create the phpunit task group and allow you to enter the following command

./symfony phpunit:create frontend -type=doctrine

This checks the lib/model/doctrine directory for your child classes with new methods to test.

2) Hold on running this quite yet, theres an interesting fork at:

http://github.com/maxim-oleinik/sfPhpunitPlugin/commits/patched


This fork by Maxim Oleinik, which I ran into on the PHPUnit mailing list, creates the functional tests correctly to be run with phpunit. There's still some work to be done, but it gets the job done for now. It's a very nice addition to the plugin.

3) Change your templates for sfPHPUnitPlugin these are in the plugin's data/ dir. If your like me, remove all the requires and includes and let php/symfony autoload them for you. Saves a bunch of headaches.

4) run the ./symfony phpunit:testall command

5) If you have a working version, you should have a lot of I's - get cracking on that test code.

6) Moving into CI first start with your Ant build file, create tasks for phpunit:testall, ./symfony cc, php -l, etc. Selenium integration will come.

If you can run through your symfony tasks with ant, this is the basis for integrating phpunit with cruisecontrol and starting your continuous integration.

7) Follow the instructions to install CruiseControl. You may even want to setup cruise control as a daemon. Theres a nice .sh here http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseCruiseControl

8) Add your project to Cruise control, setup svn/csv checkouts w/ ssh keys

9) Replace your build.xml file default with the one you had been using in step 6 , follow steps to add a svn/csv checkout with ssh keys etc.. to your ant build file.

10) Test that CruiseControl will now run through your build process, clear caches, run phpunit:testall and display the proper messages. This is the part I am not sure of yet, Personally I have had phpunit and CC setup to run selenium and other unit tests. I do not know yet what command phpunit:testall runs and whether or not you can get code coverage output for example. Will update this blog with my findings.

11) Install Selenium Grid http://selenium-grid.seleniumhq.org/ and get a few VMware boxes running your favorite (or not so favorite) browsers and selenium RC servers.

12) Create a bootstrap.php file and a browser configuration file. This page is indispensable for phpunit config file questions http://www.phpunit.de/manual/3.3/en/appendixes.configuration.html

13) Point your browser config at the selenium hub, register your RC servers with the hub, pray to the Elephpant, and add the phpunit commands to your ant build file.

./phpunit --bootstrap bootstrap.php --configuration all_browsers.xml AllTests.php

I prefer a separate bootstrap and browser file that is not config'd in the configuration file for good reason, I usually want to override it.


At this point, hopefully, and with some encouragement, CC should be testing your application from end to end every time new code enters the repository (if the settings are low enough), or at least everytime you feel comfortable with it. This is essential for Agile development using Test Driven Developement (TDD), or Behavior Driven Development (BDD) or any other Agile Methods.

1 comment: