To begin I will talk about the directories and files you will need to have in your repository for your build to be successful, followed by a discussion of each of those files list, and then then I will cover the creation of your first job. But, first, I will provide the links to the downloads in this post, up front for convenience.

Downloads

For convenience, here are all of the downloads covered in this post, so you don’t need to ferret out the links.

Directory Structure and Files

Below is the minimal directory structure and files that you will need for the build script to work in Jenkins. StructureExample is the root folder for the repository (just think of it as the trunk folder in a subversion repository)

Directory structure and minimal files

From the above image you can see that there are two files “build.xml” and “phpunit.xml” in the root directory.

build.xml is an XML file that tells Ant what to do when performing a build.

phpunit.xml defines several parameters for PHPUnit to use during its portion of the build.

The location of these files are pretty standard; however, what is not so standard is that I have split the unit tests out into separate directories under the tests directory. This was done to keep all of the PHP Unit tests separate from the SimpleTest tests.

For convenience you download the above directory structure and files here. The download included several versions of build.xml (build.xml.both, build.xml.simpletest, build.xml.phpunit) so you can pick the appropriate version for your build by renaming the appropriate file to build.xml.

Build.xml

The build.xml file is the most important file in the directory; it tells ant what to do during execution. The file is a little long, roughly 178 lines and created the directory structure shown below. Since this file is so important I will cover the sections that will be used while performing a build on Jenkins.

The fist thing to do is to put the name of your project in the file, in the name attribute for this line:

<project name="your-project-name-here" default="build">

Note that the above line also sets the default target to perform “build”. This line;

phpunit –> Performs the tests located in tests/phpunit, and uses phpunit.xml for its configuration. After which it creates a report of the results

simpletest –> Performs the tests in the TestSuite defined in test/simpletest/TestSuite.php, and then creates a report of the results

phpcb –> Creates a browsable report of your code

Target Definitions

Prepare

The prepare target depends on the clean target, which removes all the directories under the build directory in the workspace. After which, the prepare target re-creates them. ${basedir} contains the path to the current projects (jobs) workspace. For example, if your job was called “example-job” is would contain the path /var/lib/jenkins/jobs/example-job/workspace.

Phploc

This uses PHP Loc to determine the size of the project. The constructed command looks like phploc –exclude ${basedir}/tests –log-csv ${basedir}/build/logs/phploc.csv ${basedir}.
This command tells phploc to look at the code in ${basedir} but exclude the tests directory and to publish the report to build/logs/phploc.csv

Phpmd-ci

This target uses PHP Mess Detector to check your code for common smells (indicators of possible bad coding or design). There are several rulesets you can use when checking your code: codesize, controversial, design, naming, and unusedcode. You can read about the rulesets here to figure out what each one covers.

You can also define your own rulesets of modify existing rulesets using an xml file. To learn more about there go here and checkout the menu on the right.

The current target configuration tells phpmd to create an xml report, using the codesize ruleset, and place the report in build/logs/pmd.xml. It should examine the current workspace and exclude the test directory.

Phpcs-ci

This target uses PHP CodeSniffer to check the code in the project, excluding the tests directory, for Zend coding standard violations. The results of the analysis are then put into a checkstyle report in build/logs/checkstyle.xml.

To learn about the available standards and functionality of PHP CodeSniffer, visit here

Phpunit

This target runs your unit tests using PHP Unit. By default, PHP Unit checks the current directory for a configuration xml file, which is our phpunit.xml file. Because we took this approach, there is not much in the definition of this target.

However, you can find plenty about what you can put in the configuration file here

Simpletest

This target defines how to perform our unit/functionality tests using SimpleTest. You’ll notice that this target definition is a little different than the others. The reason is, is that SimpleTest does not have a nice command line tool that takes parameters like the other tools we are using. To make SimpleTest work, we need to create a little inline bash script.

The one-liner bash script that we will use tells the shell to use php to run TestSuite.php file and then send its output to XML Lint for formatting and output into build/logs/simpletest-results.xml

phpunit.xml

For the over definition, we tell php unit to not backup and restore $GLOBALS or static attributes of user defined classes, to run in strict mode and have verbose output.

For our test suite settings, we set the name (which you should change) and tell php unit to run all of the tests in the php files in tests/phpunit.

Next for our logging settings, we tell PHP Unit to create a coverage report in build/coverage, with the title of your project (don’t forget to set this attribute value) and several other attributes. We also want a coverage-clover report in build/logs/clover.xml and a junit report in build/logs/junit.xml

TestSuite.php

This file defines out Test Suite for SimpleTest. For our test suite, we define the class MyTests and add the Test Files we want to run using the addFile method. Take note of the use of the magic word __DIR__. This is used so no matter where this file is being invoked from, we won’t have to worry about how the test files are included.

To run the tests in the test suite, a new instance of the class is made and then ran using the JUnitXMLReporter class, so we can jUnit and xUnit compatible output. I had noticed in some other blogs that there was a problem with the header and footer printing in non xml; however, this approach does not have that problem.

/**
* Include the simpletest file so we can extend TestSuite
*/
require_once 'simpletest/simpletest.php';
/**
* Include the JUnitXMLReporter class so the output is jUnit and xUnit compatible
*/
require_once 'simpletest/extensions/junit_xml_reporter.php';
class MyTests extends TestSuite
{
function __construct()
{
parent::__construct();
//add the files containing the tests we want to perform
//note the use of __DIR__ so we don't have to worry about file location
//when running the tests in Jenkins
$this->addFile(__DIR__.'/TemplateTest.php');
}
}
$test = new MyTests();
$test->run(new JUnitXMLReporter());

Example Test File – TemplateTest.php

I thought it might be pertinent to show an example test file for use with the Test Suite defined above. In the code below, you will notice that I never include simpletest/autorun.php, I only include simpletest/web_tester.php. This is because I want complete control over the running of the tests and their output.

Setting Up Your First Jenkins Job

This section will cover setting up your first job in jenkins using an existing template. The first thing you will need to do is add the job template to Jenkins.

Adding the job-template To Jenkins

There is a lot of configuration that needs to be done to use all the tools that we’ve installed and referenced in our build.xml file. So, let’s cut out a lot of the work and use an existing job template that has the majority of work done for us already.

I however am not sure if it is compatible with the Clover Coverage report generator. You could try having the results from SimpleTest be out to build/logs/clover.xml, but I don’t think that will do it.

Great guide but I’m having some problems with phpmd-ci and phpcs-ci. If I run them with the flags manually does everything work and they generate proper xml files also when being executed from Jenkins. But they always report failure to ant:

phpmd-ci:
[exec] Result: 2

phpcs-ci:
[exec] Result: 1

And thus my test fails with “Build step ‘Invoke Ant’ marked build as failure”. Does anyone have a suggestion on what to do? Jenkins is having TERM set to xterm so the terminal type shouldn’t be the problem.