continuous testing in php
DESCRIPTION
Talk I've given at True North PHP 2014. TDD (Test Driven Development) is getting more and more popular. But what can you do to take it to the next level? What if you could know if your tests are passing every time you save a file without taking your hands off the keyboard. This is what continuous testing gives you. In this session, we will cover how you can continuously test your PHP application. We will cover Installation and configuration Running the tests Running static analysers Executing tools that can make your life easierTRANSCRIPT
Continuous Testing in PHPTrue 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
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
Guardfile
Notifications
System Notification
group :development do
gem 'libnotify' #Linux
gem 'growl' #Mac OS
gem 'rb-notifu' #Windows
end
Gemfile
notification :libnotify #Linux
notification :growl #Mac OS
notification :notifu #Windows
Guardfile
Terminal Title
notification :terminal_title
Guardfile
tmux
notification :tmux,
display_message: true
Guardfile
notification :off
No Notifications
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/12709twitter: @ehogueBlog: 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/