Continuous Testing in PHP 
True North PHP 2014 
Eric Hogue 
@ehogue 
erichogue.ca
Continuous Testing
Wikipedia 
a software development practice that extends 
test-driven development by means of automatic 
test execution in the background. 
http://en.wikipedia.org/wiki/Continuous_test-driven_development
How I Discovered it
Test Driven Development
Repetitive ...
Code Kata
Eureka!
Automate the Automated Tests
Searching
autotest
AutoPHPUnit
Watchr
Guard
Plugins
Installation - Settings
Ruby
Install Ruby With RVM 
$ curl -sSL https://get.rvm.io | bash 
-s stable --ruby 
$ ruby -v 
ruby 2.1.3p242 (2014-09-19 revision 
47630) [x86_64-linux]
RubyGems + Bundler
Gemfile 
source 'https://rubygems.org' 
group :development do 
gem 'guard' 
end
bundle install 
$ bundle install 
Fetching gem metadata from https: 
//rubygems.org/........... 
... 
Installing guard 2.6.1 
Your bundle is complete!
Running Guard 
$ bundle exec guard 
00:53:09 - ERROR - No Guardfile found, 
please create one with `guard init`.
Guardfile
Project root - Guardfile
Home folder - .Guardfile
Home folder - .guard.rb
Guardfile 
notification :off
Guardfile 
notification :off 
guard 'guardname' do 
end
Guardfile 
notification :off 
guard 'guardname', :option => value do 
end
Guardfile 
notification :off 
guard 'guardname', :option => value do 
watch(%r{^regex$}) 
end
Notifications
System Notification
Gemfile 
group :development do 
gem 'libnotify' #Linux 
gem 'growl' #Mac OS 
gem 'rb-notifu' #Windows 
end
Guardfile 
notification :libnotify #Linux 
notification :growl #Mac OS 
notification :notifu #Windows
Terminal Title
Guardfile 
notification :terminal_title
tmux
Guardfile 
notification :tmux, 
display_message: true
No Notifications 
notification :off
PHP Guards
Guard::PHPUnit2
Gemfile 
group :development do 
... 
gem 'guard-phpunit2', :git => 
"https://github.com/EricHogue/guard-phpunit2. 
git" 
end
Guardfile 
guard 'phpunit2', :cli => '--colors', 
:tests_path => 'tests' do 
watch(%r{^tests/.+Test.php$}) 
end
Guardfile 
guard 'phpunit2', :cli => '--colors', 
:tests_path => 'tests' do 
watch(%r{^tests/.+Test.php$}) 
end
Guardfile 
guard 'phpunit2', :cli => '--colors', 
:tests_path => 'tests' do 
watch(%r{^tests/.+Test.php$}) 
end
Guardfile 
guard 'phpunit2', :cli => '--colors', 
:tests_path => 'tests' do 
watch(%r{^tests/.+Test.php$}) 
end
bundle exec guard
Guardfile 
… 
watch(%r{^src/(.+).php$}) { |m| 
"tests/#{m[1]}Test.php" 
}
%r{^src/(.+).php$} 
src/TDD/Factorial.php 
"tests/#{m[1]}Test.php" 
phpunit tests/TDD/FactorialTest.php
:all_on_start 
guard 'phpunit2', :all_on_start => 
true do 
end 
default => true
:tests_path 
guard 'phpunit2', :tests_path => 
'path/to/tests' do 
end 
default => pwd
:all_after_pass 
guard 'phpunit2', :all_after_pass => 
true do 
end 
default => true
:keep_failed 
guard 'phpunit2', :keep_failed => 
true do 
end 
default => true
:command 
guard 'phpunit2', :command => 
'./vendor/bin/phpunit' do 
end 
default => phpunit
:cli 
guard 'phpunit2', 
:cli => '--colors' do 
end 
default => nil
Guard::PHPCS
Gemfile 
group :development do 
... 
gem 'guard-phpcs' 
end
Guardfile 
guard 'phpcs', :standard => 'PSR2', 
:executable => "./vendor/bin/phpcs" 
do 
watch(%r{.*.php$}) 
end
Guardfile 
guard 'phpcs', :standard => 'PSR2', 
:executable => "./vendor/bin/phpcs" 
do 
watch(%r{.*.php$}) 
end
Guardfile 
guard 'phpcs', :standard => 'PSR2', 
:executable => "./vendor/bin/phpcs" 
do 
watch(%r{.*.php$}) 
end
Guardfile 
guard 'phpcs', :standard => 'PSR2', 
:executable => "./vendor/bin/phpcs" 
do 
watch(%r{.*.php$}) 
end
PHPCS - PSR2
Guard::PHPMD
Gemfile 
group :development do 
... 
gem 'guard-phpmd' 
end
Guardfile 
guard 'phpmd', 
:executable => './vendor/bin/phpmd', 
:rules => 'pmd-rules.xml' do 
watch(%r{.*.php$}) 
end
Guardfile 
guard 'phpmd', 
:executable => './vendor/bin/phpmd', 
:rules => 'pmd-rules.xml' do 
watch(%r{.*.php$}) 
end
Guardfile 
guard 'phpmd', 
:executable => './vendor/bin/phpmd', 
:rules => 'pmd-rules.xml' do 
watch(%r{.*.php$}) 
end
pmd-rules.xml 
... 
<rule ref="rulesets/codesize.xml" /> 
<rule ref="rulesets/design.xml" /> 
<rule ref="rulesets/naming.xml" /> 
<rule ref="rulesets/unusedcode.xml" /> 
<rule ref="rulesets/controversial.xml" /> 
...
Guardfile 
guard 'phpmd', 
:executable => './vendor/bin/phpmd', 
:rules => 'pmd-rules.xml' do 
watch(%r{.*.php$}) 
end
PHPMD
Other Guards
More 
More than 200 plugins
JavaScript
Gemfile 
group :development do 
... 
gem 'guard-jasmine' 
end
Guardfile 
guard 'jasmine', :jasmine_url => 'http: 
//localhost:8000/SpecRunner.html' 
... 
end
Guardfile 
guard 'jasmine', :jasmine_url => '', 
:server => :none do 
watch(%r{spec/.+Spec.js$}) 
end
Guardfile 
guard 'jasmine', :jasmine_url => '', 
:server => :none do 
watch(%r{spec/.+Spec.js$}) 
end
Guard::Jasmine
LiveReload
LiveReload
Gemfile 
group :development do 
... 
gem 'guard-livereload' 
end
Guardfile 
guard 'livereload' do 
watch(%r{public/.+.(css|js|html)}) 
end
Guard::Bundler
Gemfile 
group :development do 
... 
gem 'guard-bundler' 
end
Guardfile 
guard :bundler do 
watch('Gemfile') 
end
Guard::Bundler
Guard::Shell
Gemfile 
group :development do 
... 
gem 'guard-shell' 
end
Guardfile 
guard 'shell' do 
watch(%r{^.+.php$}) do |m| 
`php -l #{m[0]}` 
true 
end 
end
Lint check
Guardfile 
`php -l #{m[0]}` 
if ($?.success?) 
n "#{m[0]} correct",'Syntax',:success 
else 
n "#{m[0]} incorrect",'Syntax',:failed 
end
Composer
Guardfile 
guard 'shell' do 
watch("composer.lock") do |m| 
p "Running composer install" 
`composer install` 
… 
end 
end
Composer
Inline Guard
Guardfile 
require 'guard/plugin' 
module ::Guard 
class BehatGuard < ::Guard::Plugin 
end 
end
Guardfile 
def start 
puts 'Run all Behat tests' 
puts `./vendor/bin/behat` 
end
Guardfile 
def run_on_changes(paths) 
paths.each do |file| 
puts `./vendor/bin/behat #{file}` 
end 
end
Guardfile 
guard 'BehatGuard' do 
watch(%r{^features/.+.feature$}) 
end
Behat
PHPUnit 
PHPCS 
PHPMD 
php -l 
composer install 
Jasmine 
LiveReload 
Behat
Automate Your Automated Test
Questions? 
PHP Mentoring: http://phpmentoring.org/ 
Comments: https://joind.in/12709 
twitter: @ehogue 
Blog: http://erichogue.ca/
EndlessTunnel.jpg - Trey Ratcliff - https://www.flickr.com/photos/stuckincustoms/4539732832 
History.jpg - Morten Diesen - http://www.flickr.com/photos/mortendiesen/8091682612 
StreetLights.jpg - William Warby - http://www.flickr.com/photos/wwarby/2460655511 
FadeToGrey.jpg - Andreas Levers - https://www.flickr.com/photos/96dpi/2571056264 
Kata.jpg - ser... ser... - http://www.flickr.com/photos/el_ser_lomo/3267627038 
Archimedes.jpg - Sputnik Beanburger III - https://www.flickr.com/photos/sputnikbeanburgeriii/4690475562/in/photostream/ 
GearWork2.jpg - Curious Expeditions - https://www.flickr.com/photos/curiousexpeditions/489992128 
SARHelicopter.jpg - UK Ministry of Defence - https://www.flickr.com/photos/defenceimages/8695434365 
RelayBox.jpg - Ed Hunsinger - https://www.flickr.com/photos/edrabbit/4698481573 
Ruby.jpg - Joren De Groof - https://www.flickr.com/photos/jorendegroof/4470431763 
RubyGems.png - Linux Screenshots - https://www.flickr.com/photos/xmodulo/14652484443 
Files.jpg - Travis Wise - https://www.flickr.com/photos/photographingtravis/14745936519 
Root.jpg - きうこ - https://www.flickr.com/photos/kiuko/9112281601 
Home.jpg - Warren - https://www.flickr.com/photos/jety/3277812553 
Alarm.jpg - Fabian - https://www.flickr.com/photos/snapsi42/3436162040 
Containers.jpg - www.GlynLowe.com - https://www.flickr.com/photos/glynlowe/10921733615 
Mess.jpg - Moyan Brenn - https://www.flickr.com/photos/aigle_dore/5481297641 
Shells.jpg - Bemep - https://www.flickr.com/photos/40626436@N00/40822551 
DoItYourself.jpg - Vlasta Juricek - https://www.flickr.com/photos/vlastula/3229196769 
Languages.jpg - Valerie Everett - https://www.flickr.com/photos/valeriebb/3008977110 
Javascript.jpg - Nathan Smith - https://www.flickr.com/photos/nathansmith/4704268314 
Stacks.jpg - Roman Boed - https://www.flickr.com/photos/romanboed/13356494013 
js.png - Chris Williams - https://github.com/voodootikigod/logo.js 
AssemblyLine.jpg - Fiat Chrysler Automobiles: Corporate - https://www.flickr.com/photos/chryslergroup/13194222244 
CarCrash.jpg - JaseMan - http://www.flickr.com/photos/bargas/3695903512/

Continuous testing In PHP