Making guard-phpunit2 Realtime

I’ve been using guard and guard-phpunit2 for unit testing PHP code at work. (Hey, at least there are tests)

One of my main difficulties with it is that it did not show output in real-time. It ships with a really nice rspec inspired result printer, but unfortunately during a run of a large test-suite you can’t see any output until the entire thing is done.

guard-phpunit2 works by shelling out to phpunit and then parsing the subprocess’s output. This has the unfortunate side-effect of swallowing all of phpunit’s progress output until complete.

Real time output requires a different algorithm. Luckily, PHPUnit provides a few different logging options. Using --log-json file.json will write an event log of every test to file.json. Guard can then pick up that file and parse it, completely ignoring phpunit‘s STDOUT.

I forked the project and replaced the output parsing logic with a new parser that can process the --log-json file.

The only other thing to do is to use system instead of %x{ }.

system hooks the child process’s standard out to the parent process’s standard out. This allows everything printed by PHPUnit to immediately appear on the console.

%{ } is the same as back-ticks: it eats the standard output of the child process and returns it as a string.

I’ve got a PR put in, but the maintainer appears to be busy and hasn’t commented on it. Until its merged, you can point your Gemfile at my GitHub branch.

Gemfile
1
2
3
4
gem 'guard'
gem 'guard-phpunit2',
:git => 'https://github.com/akatakritos/guard-phpunit2',
:branch => 'realtime-optional'
Guardfile
1
2
3
4
5
6
7
8
# Add the :realtime => true option to use realtime outputting
#
guard 'PHPUnit2', :realtime => true do

watch(%r{^libraries/.+Test\.php$})
watch(%r{^libraries/es/(.+)\.php$}) { |m| "libraries/es/#{m[1]}_Test.php" }
watch(%r{^leads/(.+)\.php}) { |m| "libraries/leads/#{m[1]}_Test.php" }
end