Simple continuous integration with PHP and subversion (or any other version control system)

2 minutters læsning

I work on a project in a subversion repository. Because knowing is half the battle, I wanted some kind of continuous integration on the project. Earlier I explained how you can use cijoe with github projects, but that was not an option. I wanted something simple, and came up with the following solution.

I already had a development server set up, and the test suite was written in PHPUnit. I wanted the test suite to be run regularly and notify me, if the tests did not pass. I solved it by a cron job updating the subversion repository and running the test suite, and a test listener informing me about the result.

The test listener

First I wrote the test listener. I basically just count whether there is any errors and failures. If there is, it notifies me via, but you could also send an e-mail or anything similar.

<pre type="php"><?php
class TestListener implements PHPUnit_Framework_TestListener
    protected $errors;
    protected $error_count;

    public function addError(PHPUnit_Framework_Test $test, Exception $e, $time)

    public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time)

    public function addIncompleteTest(PHPUnit_Framework_Test $test,Exception $e,$time)

    public function addSkippedTest(PHPUnit_Framework_Test $test,Exception $e,$time)

    public function startTest(PHPUnit_Framework_Test $test)

    public function endTest(PHPUnit_Framework_Test $test, $time)

    public function startTestSuite(PHPUnit_Framework_TestSuite $suite)

    public function endTestSuite(PHPUnit_Framework_TestSuite $suite)

    public function __destruct()
        exec('svn info ' . dirname(__FILE__) . '/../', $output);
        $msg = 'Build had ' . $this->error_count . ' errors. Please fix them' . "\n\n";
        $msg .= implode("\n", $output);
        if ($this->error_count > 0){
            $this->notifo('project', 'Build failed', $msg, '', 'user', 'api_secret');

    function notifo($label, $title, $msg, $uri, $user, $pass)
        $opts = array(
            'http' => array(
                'method' => "POST",
                'header' => "Authorization: Basic ".base64_encode($user.":".$pass)."\r\n".
                    "Content-type: application/x-www-form-urlencoded\r\n",
                'content' => http_build_query(array('label' => $label, 'title' => $title, 'msg' => $msg, 'uri' => $uri))
        $context = stream_context_create($opts);
        file_get_contents('', false, $context);

To attach the listener to your test suite, I used the following XML-configuration:

<pre type="xml"><?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true">
    <listener class="TestListener" file="TestListener.php"></listener>

Now I am able to run the test suite from the command line with the following command:

$ phpunit .

Putting it all together

I wrote a bash script to update the repository and run the test suite. It is really simple:

<pre type="shell">#!/usr/bin/env bash
UPDATE=$(git pull origin master)
if ; then
    cd /home/intraface_test/intraface-git/tests
    phpunit --process-isolation --log-tap /home/intraface_test/ . > /dev/null
    cd /home/intraface_test

The script checks whether the repository has been updated. If it has, a local update is performed and the test suite is run. Now to make it continuous integration I just need to create a cronjob running the script on a regular basis.

<pre type="">MAILTO=""
*/15 * * * * sh


  • Make sure that new builds are run in order and does not interfere with previous builds.

Could it be more simple? What do you think of this approach?

Skriv en kommentar

Din e-mail bliver ikke offentliggjort. Obligatoriske felter er markeret *