Travis-CI and a PHP library

Setting up a PHP library to work with Travis-CI Posted by Toby on Sun 12 Nov. 2017

In an act of foolishness I've decided to have a go a writing a Forth interpreter in PHP.

I prefer Python to PHP but I've had my head stuck in PHP for so long that my Python skills have atrophied and so I need to use PHP for now.

I can't program in Forth and, although I have an ex-library copy of Brodie's Starting Forth, I've yet to get my head to switch around to working out how a project hangs together (syntactically it's not too bad).

So I'm at least being good and using TDD and intending on using the book's examples to build the tests and make sure it works.

I have a vague idea that I'd write a game like Cossacks or Age Of Empires (with incredibly basic graphics and AI) but where you code the orders you give units in Forth. I suspect this won't be the project that makes me a million quid.

BUT ANYWAY...

I need to use TDD and experience at work suggests that you cannot trust everyone to run the tests before they commit ("I'll just make this trivial tweak and it won't have any knock-on effects") because tests are for other people.

Whilst working in London I worked with a rather wonderful manager who set up test passing and code coverage badges on Github and we used to actually enjoy making sure all the little icons were always green to show that everything was fine.

But that was in Django and I've never tried it with PHP so I thought I'd give it a go with Travis CI. It took me about a dozen commits to get it to work but I did and I'm going to share the end result which can been seen in my repo here: PHPForth with working Travis CI

Composer.json

I struggled to get this to work because of the autoloading. In fact the autoloading was the most troublesome part of this whole process.

My directory structure is essentially:

src/
Tests/
composer.json
phpunit.xml
.travis.yml

The composer.json file looks like this:

{
    "name": "tobyontour/php-forth",
    "description": "A Forth interpreter written in PHP",
    "type": "library",
    "require-dev": {
        "phpunit/phpunit": "^6.4",
        "squizlabs/php_codesniffer": "^3.1"
   },
    "autoload": {
        "psr-4": {
            "PHPForth\\": "src/"
        }
    }
}

phpunit.xml

I gave up on hand-crafting this in the end because, even though it worked perfectly locally, I had no end of trouble getting it to work on Travis.

The command-line to get composer to do this for you (prompting you where necessary) is:

phpunit --generate-configuration

And this generated:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/5.4/phpunit.xsd"
         bootstrap="vendor/autoload.php"
         backupGlobals="false"
         beStrictAboutCoversAnnotation="true"
         beStrictAboutOutputDuringTests="true"
         beStrictAboutTestsThatDoNotTestAnything="true"
         beStrictAboutTodoAnnotatedTests="true"
         verbose="true">
    <testsuite>
        <directory suffix="Test.php">Tests</directory>
    </testsuite>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">src</directory>
        </whitelist>
    </filter>
</phpunit>

travis.yml

It seems that Travis-CI doesn't do a composer install by default and so when you run phpunit it's not necessarily using the vendor/autoload.php file. So you have to run it yourself:

language: php
php:
    - 7.0
install: composer install

composer.lock

The composer.lock file is great when you have control over your environment in all places and are running the same version of PHP everywhere - it saves composer from having to do a complicated, slow, and memory hungry process of working out the magical combination of library versions that satisfy your requirements.

But if you're running one version of PHP and Travis is running another then the versions fixated in the composer.lock file will cause problems. The trick appears to be not to commit it.

Bit of a shame, but that was one thing that was causing issues.