First steps with continuous integration

In this post, we are going to overview some tools to use continuous integration.

Continuous integration (CI) is a development practice that requires developers to integrate code into a shared repository several times a day. Each check-in is then verified by an automated build, allowing teams to detect problems early. CI originated from within the extreme programming paradigm, but the principles can be applied to any iterative programming model, such as agile programming.

There are many tools that we can use and one of the most famous is probably Jenkins, written in Java. But we are not going to talk about Jenkins in this post. Instead, we are going to generate a really small project with some other tools. For that, we need Git, Ruby, PHP, Composer, PHPUnit, PHP-CS-Fixer, GitHub, Travis, StyleCI and Codecov. We may think that is a lot of stuff, but there is no reason to be afraid.


First of all, a few and short definitions!


Git is a free and open source distributed version software for tracking changes in computer files and coordinating work on those files among multiple people. It was created by Linus Torvalds.


GitHub is a web-based Git that got a mascot called Octocat, a cat with five tentacles and a human-like face. It was created by Chris Wanstrath, PJ Hyett and Tom Preston-Werner.


A famous programming language. We will need it to install gems (Ruby Libraries).


Another famous programming language. We will create our project with it.


A dependency manager for PHP that was initially developed by Nils Adermann and Jordi Boggiano.


A framework for unit testing for PHP created by Sebastian Bergmann.__


A tool to automatically fix PHP coding standards issues.

Travis CI

A continuous integration service used to build and test software projects hosted at GitHub.


StyleCI makes sure that all code on our PHP project is written to a consistent standard.


Codecov provides metrics and insights into the results of tests through code coverage.

For the sake of this article, we are not going to discuss here about test driven development (TDD), how to write good and efficient tests and things like that. These are other subjects. The aim of this post is to see how to install and use all of those tools.



Installing Composer is really easy. We just have to go to and follow the instructions. On Windows, there is an installer.


Again, we have to go to and follow the instructions. On Windows, globally install PHPUnit is a bit trickier.


On a Linux system and on macOS, Ruby is already here. On Windows, we have to download the installer from


We just need to go here and follow the instructions.


On a Linux system and on macOS, we can globally install PHP-CS-Fixer by following the instructions written here

GitHub, Travis CI, StyleCI, Codecov

We just have to go on GitHub ( and create an account. We will then have access to Travis CI (, StyleCI ( and Codecov ( with that same account.

Travis gem

The gem can be install by doing the following command in the terminal:

gem install travis

Setting up the project

Now that we have all our new tools, we can move to the next step and set up our project.


The first thing we need to do is to create a composer.json file at the root of our project. We can create it manually or by doing the following command:

composer init


"name": "mlbors/simple-travis-codevoc-styleci",
"description": "Simple project using Composer, PHPUnit, Travis, Codecov, PHP-CS-Fixer and StyleCI",
"license": "MIT",
"require": {
"php": ">=5.6",
"ext-curl": "*",
"friendsofphp/php-cs-fixer": "2.0.0"
"require-dev": {
"phpunit/phpunit": "5.7.*",
"vlucas/phpdotenv": "^2.0"
"autoload": {
"psr-4": {
"mlbors\\SimpleApp\\": "app/"
"autoload-dev": {
"psr-4": {
"mlbors\\SimpleApp\\Tests\\": "tests/"
"homepage": "",
"authors": [
"name": "mlbors",
"email": "",
"homepage": ""

composer.json file

In the above example, in the require section, we say that we need PHP 5.6 or higher, Curl and PHP-CS-Fixer. In require-dev, we have PHPUnit and PHPDotEnv. In the autoload and autoload-dev sections, we say that we use the PSR-4 standard and how our namespaces will be.

It is time to do the following commands to install and generate the autoload:

composer install
composer dump‑autoload -o


First of all, we create two files: .gitignore and .gitattributes.


.gitignore file

/.gitattributes export-ignore  
/.gitignore export-ignore
/phpunit.xml export-ignore
/.env export-ignore
/.env.example export-ignore

.gitattributes file

Then, we go on GitHub and create a new repository. Then, on our system, at the root of our project, we do the following commands:

git init
git add .
git commit –m "First commit"
git remote add origin
git push –u origin master

Replace user and repository by your username and your repository

Now we can go on Travis CI, StyleCI and Codecov and link our repository to those services.


Now, at the root of our project, we create the styleci.yml that will tell StyleCI file which rules we use.

preset: psr1

.styleci.yml file

.env File

The .env file allows us to place some values that we do not want to appear in our code. In our example, we can load them with PHPDotEnv. The .env file will be ignored by Git but we can create a .envexample file with fake values just to tell the world that we need a .env file.


.env file

Travis CI

Now we can create the .travis file that will tell Travis CI what to do with our files. We can also include critical values in that file, for example, the ones that are in the .env file, by encrypting them like so:

travis encrypt SOMEVAR=secretvalue


language: php
- 5.6
- 7.0
- sudo pip install codecov
- composer self-update
- composer install --no-interaction
- bash <(curl -s
- vendor/bin/phpunit --coverage-clover=coverage.xml
- SIMPLE_KEY=someValue
email: false

.travis file

In the above example, we tell Travis CI a few things: we state that we use PHP and our app will have to work on PHP 5.6 and PHP 7. We also install the Python codecov package with pip for code coverage. Our dependencies will also be installed with Composer and PHPUnit will be executed. If everything is alright, we send the information to Codecov.

More information about how to customize the build are available here!


The .php_cs file tells PHP-CS-Fixer the rules that we use.

$rules = [
'@Symfony' => true
return PhpCsFixer\Config::create()

.php_cs file


We create a phpunit.xml to tell PHPUnit how to run our unit tests. We also set the processUncoveredFilesFromWhitelist attribute for code coverage.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
<testsuite name="SimpleApp Test Suite">
<directory suffix="Test.php">./tests/</directory>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">./app</directory>


In the above example, among other things, we tell PHPUnit where our test suite will be and how to compute the code coverage.


The file tells the world about our project. We can also include into it the badges that Travis CI, StyleCI and Codecov will generate.

[![Build Status](](
Simple project using Composer, PHPUnit, Travis, Codecov, PHP-CS-Fixer and StyleCI file

Let’s use all those tools


To use PHP-CS-Fixer, we can enter the following commands in our terminal:

$ php php-cs-fixer.phar fix /complete/path/to/dir
$ php php-cs-fixer.phar fix /complete/path/to/file

On Windows we can do it like so:

php path\to\project\vendor\friendsofphp\php-cs-fixer\php-cs-fixer fix path\to\fileordir


To run our tests, we just have to use


On Windows, we can do it like so:

php path\to\project\vendor\phpunit\phpunit\phpunit

And we push

It is time! Now we can do

git add .
git commit –m "This is a commit"
git push origin mybranch

If everything is alright, our files will be send to GitHub, then to Travis CI and StyleCI. Travis CI will do what we wrote in our .travis file then send coverage information to Codecov. And voilà!


Continuous integration advantages are several:

  • Integration bugs are detected early and are easy to track down
  • Constant availability of a “current” build for testing, demo, or release purposes
  • Frequent code check-in pushes developers to create modular, less complex code
  • Enforces discipline of frequent automated testing
  • Immediate feedback on system-wide impact of local changes

And so on. On the other hand, we can state that continuous integration requires a considerable amount of work and time. And 100% code coverage doesn’t mean that every execution path is tested and our software is bug free.

You can find the complete example on my GitHub (