Why Travis?

I recently gave a talk at a local PHP Meetup in Cape Town discussing the basics of using Travis CI and how to implement it in a laravel
project. I use Travis CI personally for my hobby projects as I found it is an indispensable tool to run your tests quickly and effectively.
I believe that Continuous Integration is a cornerstone of test-driven development as it ensures that upon each change to a codebase, your code does not
introduce bugs or technical debt. This short tutorial will cover how to implement Travis CI into your own laravel apps.

What is CI?

“A software development practice where members of a team integrate their work frequently … verified by an automated build (including tests) to detect integration errors”

When you combine the process of automated testing with a testing suite such as PHPUnit, PHPSpec, Codeception etc... then
the end result is that continuous integration can enable your code to be dependable as any bugs will fail the test suite.

What is Travis CI?

A hosted continuous integration platform that is free for all open source projects hosted on GitHub.

How do I implement it?

Simply by signing up to the website travis-ci.org (or travis-ci.com for private repos) and adding a .travis.yml file describing some details about your project, you can use travis
to trigger automated builds with every change to your codebase.

Why use Travis over another tool such as Jenkins?

  • Nothing to install, Travis has a web-based interface as opposed to a heavy java application that you have to host yourself.
  • Free to use for open-source projects!
  • Integrates nicely with GitHub without any developer effort!
  • Has a much shallower learning curve than it’s competitors.

How do I get started?

  1. Sign up with travis-ci.org using your GitHub Account.
  2. Enable the public repositories that you want Travis to build against.
Enabling Travis Repo Access

Setting up Travis with Laravel and PHPUnit

In order to use Travis with your laravel project, you will need to do a few steps to add travis to your current project. Please ensure you have Travis setup
as described in the previous step before proceeding. The testing database which I used was a MySQL database as you will see but you
could configure travis with MariaDB, SQLite or whatever tickles your fancy. (For the lazy out there, all the code for the described files below is provided in the GitHub link at the end of the post).

.travis.yml

The first step is to add a .travis.yml file to the root directory of your laravel application. The next step will be to configure .travis.yml (described below)
in order to tell Travis details about your project. In this example, I was using a PHP 7.1 / Laravel 5.4 application.

Below is my .travis.yml.

language: php

php:
- 7.0
- 7.1

services:
- mysql

before_script:
- cp .env.travis .env
- mysql -e 'create database testing;'
- composer self-update
- composer install --no-interaction
- php artisan key:generate
- php artisan migrate --seed

script:
    - vendor/bin/phpunit

notifications:
email:
    recipients:
        - youremail@x.com
    on_success: always
    on_failure: always

The .travis.yml configuration file tells travis a few details about the project namely what language we are using, what versions of the language do we support (Please change this if you are not running PHP 7.0 or PHP 7.1). It also details what services we are using (in this case MySQL but we could just as easily add Redis, Memcached etc...).

The meat of this configuration file is the before_script tag which details to travis what to do in the VM before the tests are run, in this case we are setting up our databases, composter and performing any needed migrations.

The next step is obviously script which will run our PHPUnit tests and actually perform the tests. Travis will give output based on whether or not the build passes or fails, we have enabled email notifications for this purpose so that we will receive an email after
Travis has finished executing the tests however you can also integrate in Slack, HipChat and others. If you want to know how to do this then RTFM:)

Setup .env.travis

The .travis.yml file detailed above has one interesting command namely:

cp .env.travis .env

This is used to copy our required config variables to travis so that travis can connect to the database. My .env.travis is as follows:

APP_ENV=testing
APP_KEY=SomeRandomString

DB_CONNECTION=testing
DB_TEST_DATABASE=testing_db
DB_TEST_USERNAME=root
DB_TEST_PASSWORD=

CACHE_DRIVER=array
SESSION_DRIVER=array
QUEUE_DRIVER=sync

Alter the config constants as needed per your setup.

Setup PHPUnit.xml

The next step is to setup PHPUnit to use the testing database connection (assuming you are using MySQL as this example utilizes). Also take note of
the test suite paths as that may differ based on your project setup. The important value here is that the application environment (APP_ENV) is set to testing and that PHPUnit
is configured to use the testing database (as noted in DB_CONNECTION).

    <?xml version="1.0" encoding="UTF-8"?>
    <phpunit backupGlobals="false"
     backupStaticAttributes="false"
     bootstrap="bootstrap/autoload.php"
     colors="true"
     convertErrorsToExceptions="true"
     convertNoticesToExceptions="true"
     convertWarningsToExceptions="true"
     processIsolation="false"
     stopOnFailure="false"
     syntaxCheck="false">
<testsuites>
    <testsuite name="Application Test Suite">
        <directory>./tests/</directory>
    </testsuite>
</testsuites>
<filter>
    <whitelist>
        <directory suffix=".php">app/</directory>
    </whitelist>
</filter>
<php>
    <env name="APP_ENV" value="testing"/>
    <env name="DB_CONNECTION" value="testing"/>
    <env name="CACHE_DRIVER" value="array"/>
    <env name="SESSION_DRIVER" value="array"/>
    <env name="QUEUE_DRIVER" value="sync"/>
</php>
</phpunit>

Add the testing database to your database config

The last step is to add the testing database we setup in PHPUnit and .env.travis to your config/database.php file. I simply added an extra parameter to the connections array as shown below.

'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', 'localhost'),
        'database' => env('DB_DATABASE', 'homestead'),
        'username' => env('DB_USERNAME', 'homestead'),
        'password' => env('DB_PASSWORD', 'secret'),
        'charset' => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix' => '',
        'strict' => false,
    ],
'testing' => [
        'driver' => 'mysql',
        'host' => env('DB_TEST_HOST', 'localhost'),
        'database' => env('DB_TEST_DATABASE', 'testing_db'),
        'username' => env('DB_TEST_USERNAME', 'root'),
        'password' => env('DB_TEST_PASSWORD', 'secret'),
        'charset' => 'utf8',
        'collation' => 'utf8_unicode_ci',
        'prefix' => '',
        'strict' => false,
    ],
],

Awesome!

Git pushing code

The final step after configuring PHPUnit, .travis.yml, database/config.php and .env.travis is simply to commit some code and push to master.
By default Travis runs your commits against every push to the master branch of your repo, however this can be setup in your travis project.

In the end you will see the output of the travis build after the completion of a test run.

Travis Test Result

And that's all there is to it, you now have travis setup with your laravel project.

If you want to see my slides from the talk or the code for the files described above - see the GitHub link here.

Happy Coding :)