It was pointed out to me [again] today that while it is easy-peasy for me to run SaunterPHP inside Jenkins CI it might not be so easy for those who have not been wiring them up for as long as I have. To remedy this situation, here is how I configure things (in a somewhat hand-wavy manner — I’ll be moving the examples I have into separate projects soon and then come back and edit this with more, specific details, pictures, heck maybe even a screencast!)
- On whatever machine you are going to be using as the ‘brains’ of the whole setup, install and start Jenkins. This, like any other bit of your environment should not be done by hand, but by a centralized configuration management tool like Puppet or Chef.
- Having just the single, local agent is the easiest thing to do so we’ll start there. Install whatever browsers you care about on the machine. Again, using a configuration management tool not by hand. (Also it can be useful to turn off whatever auto-update capabilities the browsers have so things don’t get ahead of you with versions.) Let’s pretend for this example it is Firefox.
- As with Jenkins itself, the Selenium Server should be installed and managed by a configuration management tool. And be running.
- Create a new free-style software project and name it ‘YourApplication – Firefox’ or something similar. Since you likely care about multiple browsers you could be tempted to do multi-configuration job — but resist; SaunterPHP does not really play nice in a share-a-config-across-multiple-nodes perspective
- Configure your repo information appropriately
- Add an Execute shell build step that will adjust the location of the PHPUnit Listener that comes with SaunterPHP
- Add an Execute shell build step to actually run SaunterPHP. For our first job let’s just run the shallow scripts.
- Run the job
- It failed. Why? Because you did not give it a conf/saunter.inc file yet. Recall that this file should not be commit to version control as it has environment specific stuff in it. Rename (or copy) conf/saunter.inc.default to saunter.inc and make any changes you need to (like base url, telling it you want Firefox, etc.)
- Run the job
- It ‘should’ have passed. Except that aside from the ball turning the right colour there is no feedback. For this we need to tell Jenkins where the results are kept which in terms of SaunterPHP is always logs/latest.xml. This is the non-standard standard Ant JUnit format file that PHPUnit produces. There are a couple different plugins that will read it, so pick the one you like best and point it at this file.
- Run the job. Twice. The plugins usually need two runs before they can start to show graphs of trends, etc.
This command is not destructive so can be run every time the build runs without fear
Once single browsers, single agent is working it is time to get a bit fancy by adding more agents to the mix. While you can have multiple agents per machine, I recommend just having a single one so that browsers do not fight with each other for window focus while doing native events.
- When you go to your node list, there will be a default one; Master. Add to it a label of ‘Firefox’
- Create a new node and in its configuration add ‘Chrome’
- On the remote machine, setup and start the Jenkins agent process. (Do I really need to say that this should be controlled by the central configuration management process?)
- The remote machine also needs the browser installed. In this case Chrome.
- And the Selenium Server
We now have two nodes things can run in.
- Go back to your Firefox job and restrict where this project can be run to the label you gave the Firefox node
- Do the same initial job steps as above, only for Chrome. Including the saunter.inc customizations.
- Restrict it to the Chome node
You now have two jobs and each is a separate pull from your repo which allows for easy debugging (just run a single job) and distribution of jobs between Selenium Servers behind the firewall and for ones outside like Sauce OnDemand — one of the goals of SaunterPHP was to have Sauce OnDemand integrated from the start. Jobs that are run on Sauce OnDemand can ignore the single-job-per-agent since all the work is being done in the cloud.
With the two jobs running successfully as independent jobs it is time to get clever doing things like Parallel Job Chains in Jenkins which is less a SaunterPHP thing and more of a Jenkins one.
And that is more-or-less it. No sweat, eh.