Tuesday, December 01, 2015

Switching database ports on-the-fly for Artisan, PHPUnit

One of the minor (really minor) annoyances of using Artisan in a Homestead/Vagrant environment is having to remember to run commands that interact with a database on the server, since that's where the database lives. It's possible to run them in the host environment, but you have to switch the host port to the correct forwarded port (from 3306 to 33060 for MySql).

A few extra properties in .env, and a wee bit of code in the not-often-used 'port' entry does that switching in the database configuration file based on the $_SERVER['HOME'] entry, which is completely passive and doesn't require any special setup on the server. Works for PHPUnit tests too:

This solution may be a little hacky, but it works reliably. If there's a better way (there probably is), please let me know in the comments.

Also note the change from the default 'utf8' in 'charset' and 'collation'. This has nothing to do with port switching but has everything to do with MySql's handling of UTF8. There's a good writeup about it here, the gist of which is:
MySQL’s utf8 encoding is awkwardly named, as it’s different from proper UTF-8 encoding. It doesn’t offer full Unicode support.
Luckily, MySQL 5.5.3 (released in early 2010) introduced a new encoding called utf8mb4 which maps to proper UTF-8 and thus fully supports Unicode...

So I (we) should have been using MySQL 5.5.3 with that charset for at least the last 5 years.

Tuesday, November 24, 2015

Testing a New Artisan command in Laravel 5.1

It took me quite a while to figure this out today (and for sure there may be a better way), but there didn't seem to be a well-documented way to test Laravel 5.1 Artisan commands. The main reason that I want to do this is to be able to run some simple commands directly in an Artisan command without writing another class just to essentially act as a test harness. In the case I was working on, I'm adding a field to a database table that needs to be populated with an initial attribute in every row for ElasticSearch. This will normally happen when a record is upserted, but initially it'll run once for each row in a loop as part of a multi-system update. I thought I'd run it as an Artisan command, although realistically it'd be better run as a queue-able job.

I spent some time with Laracasts but the TDD tests were 1) based on Codeception (nice, but not what I wanted) and 2) were for Laravel 4. Directly using the Symfony console test methodology doesn't work with Laravel's IoC container in Laravel 5.1. Even the Laravel foundation tests don't specifically test each of the Artisan console commands. At least I couldn't find anything, although ultimately it was the way that Laravel instantiates Artisan that gave me a clue.

You can run an Artisan command in your tests, but what I really wanted to do was check the output to the terminal, which means capturing stdout while running a command, which the test-native Artisan command doesn't support.

In any event, this works well, and displays both ways of running an Artisan command in a test:

A blog post every couple of years seems to be about the right frequency. No?