I recently set out to update my Laravel nullable fields package to support empty arrays. As part of this work, I wanted to introduce unit tests to the package as well as having compatibility with all versions of Laravel 5.*.

Setting up the dependencies in my composer.json was simple and there was nothing out of the ordinary in that regard:

"require": {
    "php": ">=5.4",
    "illuminate/database": "~5.0",
    "illuminate/events": "~5.0"
}

We want at least PHP 5.4 (the minimum required for Laravel 5.0), as well as the corresponding illuminate/database and illuminate/events packages for the different versions of Laravel 5.*.

The next step was to write the necessary tests describing my desired inputs and outputs. Locally, I was testing using Illuminate 5.1 components, but wanted to ensure that the package would also work with 5.0, 5.2, and any future versions.

Luckily, Travis provides some functionality to facilitate this behaviour.

In essence, we configure Travis - via the .travis.yml file - to install specific versions of Illuminate components, depending on the version of PHP being used.

env:
  - ILLUMINATE_VERSION=5.0.*

matrix:
  include:
    - php: 5.5.9
      env: ILLUMINATE_VERSION=5.1.*
    - php: 5.5.9
      env: ILLUMINATE_VERSION=5.2.*
    - php: 5.6
      env: ILLUMINATE_VERSION=5.1.*
    - php: 5.6
      env: ILLUMINATE_VERSION=5.2.*
    - php: 7.0
      env: ILLUMINATE_VERSION=5.1.*
    - php: 7.0
      env: ILLUMINATE_VERSION=5.2.*
    - php: nightly
      env: ILLUMINATE_VERSION=5.1.*
    - php: nightly
      env: ILLUMINATE_VERSION=5.2.*

What this does, is tell Travis that for every version of PHP being tested to use the default ILLUMINATE_VERSION environment variable of 5.0.* - to use the latest 5.0 release - as well as additional versions, depending on the PHP version being used.

To simplify;

  • When testing in PHP 5.4, use Illuminate 5.0.* components only
  • When testing in PHP 5.5.9, use Illuminate 5.0.*, 5.1.*, and 5.2.*
  • When testing in PHP 5.6, use Illuminate 5.0.*, 5.1.*, and 5.2.*
  • When testing in PHP 7.0, use Illuminate 5.0.*, 5.1.*, and 5.2.*
  • When testing in PHP nightly builds, use Illuminate 5.0.*, 5.1.*, and 5.2.*

We then tell Travis to install specific dependency versions before running the install step, telling composer to not update dependencies. This means that we can specifically install illuminate/database:5.0.* and illuminate/events:5.0.* and have composer not subsequently update these dependencies when running composer update in the install step.

before_install:
  - composer require "illuminate/database:${ILLUMINATE_VERSION}" --no-update
  - composer require "illuminate/events:${ILLUMINATE_VERSION}" --no-update

install: composer update --prefer-source --no-interaction --dev

In doing so, it is now possible to test that the single package will work across different versions of the same component. This means that those using Laravel 5.0 will get the exact same functionality from your package as those using Laravel 5.2.

Screen Shot 2016-01-28 at 11.29.58 AM.png

Running tests in this way allowed me to fix issues I wouldn't have otherwise found, where later versions of Laravel implemented new functionality to achieve the same results. For example, 5.0 used json_decode directly for cast attributes, whereas >= 5.1 uses a fromJson method on the base model.