{"id":210,"date":"2007-07-02T22:02:16","date_gmt":"2007-07-02T22:02:16","guid":{"rendered":"https:\/\/virtualchaos.co.uk\/blog\/2007\/07\/02\/continuous-integration-with-php\/"},"modified":"2007-07-02T22:03:15","modified_gmt":"2007-07-02T22:03:15","slug":"continuous-integration-with-php","status":"publish","type":"post","link":"https:\/\/virtualchaos.co.uk\/blog\/2007\/07\/02\/continuous-integration-with-php\/","title":{"rendered":"Continuous Integration with PHP"},"content":{"rendered":"<p>\nI&#8217;m in the process of setting up a continuous integration environment for a new PHP project I&#8217;m starting. On our previous project, which was Java based, we used the following tools to support similar requirements on that project in order to allow us to implement the project using a test driven approach and automate build generation:<\/p>\n<ul>\n<li><a href=\"http:\/\/cruisecontrol.sourceforge.net\/\">Cruise Control<\/a> &#8211; For setting up a Continuous Build process.<\/li>\n<li><a href=\"http:\/\/ant.apache.org\/\">Ant<\/a> &#8211; A Java based build tool.<\/li>\n<li><a href=\"http:\/\/www.junit.org\/index.htm\">JUnit<\/a> &#8211; A Java Based xunit testing framework<\/li>\n<li><a href=\"http:\/\/pmd.sourceforge.net\/\">PMD<\/a> &#8211; A tool that checks for common coding standards violations.<\/li>\n<li><a href=\"http:\/\/cobertura.sourceforge.net\/\">Corbetura<\/a> &#8211; A Java based code coverage too that calculates the percentage of code accessed by unit tests<\/li>\n<\/ul>\n<p>\nI&#8217;ve managed to set up an analogous process for our PHP project using the following tools:<\/p>\n<ul>\n<li><a href=\"http:\/\/cruisecontrol.sourceforge.net\/\">Cruise Control<\/a> &#8211; For setting up a Continuous Build process.<\/li>\n<li><a href=\"http:\/\/ant.apache.org\/\">Ant<\/a> &#8211; A Java based build tool.<\/li>\n<li><a href=\"http:\/\/www.phpunit.de\/\">PHPUnit<\/a> &#8211; An Xunit testing framework for PHP<\/li>\n<li><a href=\"http:\/\/pear.php.net\/package\/PHP_CodeSniffer\">PHP_CodeSniffer<\/a> &#8211; A PHP tool that checks for common coding standards violations.<\/li>\n<li><a href=\"http:\/\/xdebug.org\/\">Xdebug<\/a> &#8211; Debugging tool, which when combined with PHPUnit, can provide Code Coverage Metrics<\/li>\n<\/ul>\n<p>\nIt seems to work quite well, here&#8217;s the relatively simple ant build script that controls it all.<\/p>\n<div class=\"dean_ch\" style=\"white-space: wrap;\">\n<ol>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp;<\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\"><span class=\"sc3\"><span class=\"re1\">&lt;?xml<\/span> <span class=\"re0\">version<\/span>=<span class=\"st0\">&quot;1.0&quot;<\/span> <span class=\"re0\">encoding<\/span>=<span class=\"st0\">&quot;UTF-8&quot;<\/span><span class=\"re2\">?&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\"><span class=\"sc3\"><span class=\"re1\">&lt;project<\/span> <span class=\"re0\">default<\/span>=<span class=\"st0\">&quot;all&quot;<\/span> <span class=\"re0\">name<\/span>=<span class=\"st0\">&quot;DummyProject&quot;<\/span> <span class=\"re0\">basedir<\/span>=<span class=\"st0\">&quot;.&quot;<\/span><span class=\"re2\">&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;target<\/span> <span class=\"re0\">name<\/span>=<span class=\"st0\">&quot;all&quot;<\/span> <span class=\"re0\">depends<\/span>=<span class=\"st0\">&quot;clean, init, test, sniff&quot;<\/span> <span class=\"re2\">\/&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li2\">\n<div class=\"de2\">&nbsp;<\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;target<\/span> <span class=\"re0\">name<\/span>=<span class=\"st0\">&quot;clean&quot;<\/span><span class=\"re2\">&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;delete<\/span> <span class=\"re0\">dir<\/span>=<span class=\"st0\">&quot;doc\/CodeCoverage&quot;<\/span> <span class=\"re2\">\/&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;delete<\/span> <span class=\"re0\">dir<\/span>=<span class=\"st0\">&quot;doc\/UnitTestReport&quot;<\/span> <span class=\"re2\">\/&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/target<span class=\"re2\">&gt;<\/span><\/span><\/span><\/div>\n<\/li>\n<li class=\"li2\">\n<div class=\"de2\">&nbsp;<\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;target<\/span> <span class=\"re0\">name<\/span>=<span class=\"st0\">&quot;init&quot;<\/span><span class=\"re2\">&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;mkdir<\/span> <span class=\"re0\">dir<\/span>=<span class=\"st0\">&quot;doc\/CodeCoverage&quot;<\/span> <span class=\"re2\">\/&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;mkdir<\/span> <span class=\"re0\">dir<\/span>=<span class=\"st0\">&quot;doc\/UnitTestReport&quot;<\/span> <span class=\"re2\">\/&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/target<span class=\"re2\">&gt;<\/span><\/span><\/span><\/div>\n<\/li>\n<li class=\"li2\">\n<div class=\"de2\">&nbsp;<\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;target<\/span> <span class=\"re0\">name<\/span>=<span class=\"st0\">&quot;test&quot;<\/span> <span class=\"re0\">description<\/span>=<span class=\"st0\">&quot;Run PHPUnit tests&quot;<\/span><span class=\"re2\">&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;exec<\/span> <span class=\"re0\">dir<\/span>=<span class=\"st0\">&quot;.\/&quot;<\/span> <span class=\"re0\">executable<\/span>=<span class=\"st0\">&quot;TestRunner.bat&quot;<\/span> <span class=\"re0\">failonerror<\/span>=<span class=\"st0\">&quot;true&quot;<\/span><span class=\"re2\">&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/exec<span class=\"re2\">&gt;<\/span><\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/target<span class=\"re2\">&gt;<\/span><\/span><\/span><\/div>\n<\/li>\n<li class=\"li2\">\n<div class=\"de2\">&nbsp; &nbsp; <\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;target<\/span> <span class=\"re0\">name<\/span>=<span class=\"st0\">&quot;sniff&quot;<\/span> <span class=\"re0\">description<\/span>=<span class=\"st0\">&quot;&quot;<\/span><span class=\"re2\">&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;exec<\/span> <span class=\"re0\">dir<\/span>=<span class=\"st0\">&quot;.\/&quot;<\/span> <span class=\"re0\">executable<\/span>=<span class=\"st0\">&quot;Sniffer.bat&quot;<\/span> <span class=\"re0\">failonerror<\/span>=<span class=\"st0\">&quot;true&quot;<\/span><span class=\"re2\">&gt;<\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/exec<span class=\"re2\">&gt;<\/span><\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/target<span class=\"re2\">&gt;<\/span><\/span><\/span><\/div>\n<\/li>\n<li class=\"li2\">\n<div class=\"de2\"><span class=\"sc3\"><span class=\"re1\">&lt;\/project<span class=\"re2\">&gt;<\/span><\/span><\/span><\/div>\n<\/li>\n<li class=\"li1\">\n<div class=\"de1\">&nbsp;<\/div>\n<\/li>\n<\/ol>\n<\/div>\n<p>I&#8217;m currently running this on a windows machine although it&#8217;s trivial to change it work in an *ix based environment which I&#8217;ll probably configure in the next day or so. I had a couple of problems installing PHP_CodeSniffer  although it was because I hadn&#8217;t installed PEAR properly. If you have any problems installing PHP_CodeSniffer under Windows then follow these instructions:<\/p>\n<p>\nTo install PEAR under windows do the following, which assumes you have PHP5.2x installed in c:\\php :<\/p>\n<pre>\r\n  cd c:\\\\php\r\n  go-pear.bat\r\n<\/pre>\n<p>The interactive installer presents you with some options, if you follow the defaults you should be fine.<br \/>\nOnce PEAR has installed you can install PHP_CodeSniffer like this:<\/p>\n<pre>\r\n  cd c:\\\\php\r\n  pear install PHP_CodeSniffer-beta\r\n<\/pre>\n<p>This will download the PHP_CodeSniffer package and install into into your php\/PEAR folder.<\/p>\n<p>Once this is done you can check to see if it has installed by calling phpcs with -h flag which will produce the following:<\/p>\n<pre>\r\nC:\\\\php>phpcs -h\r\nUsage: phpcs [-nlvi] [--report=<report>] [--standard=<standard>]\r\n    [--generator=<generator>] [--extensions=<extensions>] <file> ...\r\n        -n           Do not print warnings\r\n        -l           Local directory only, no recursion\r\n        -v[v][v]     Print verbose output\r\n        -i           Show a list of installed coding standards\r\n        --help       Print this help message\r\n        --version    Print version information\r\n        <file>       One or more files and\/or directories to check\r\n        <extensions> A comma separated list of file extensions to check\r\n                     (only valid if checking a directory)\r\n        <standard>   The name of the coding standard to use\r\n        <generator>  The name of a doc genertor to use\r\n                     (forces doc generation instead of checking)\r\n        <report>     Print either the \"full\" or \"summary\" report\r\n<\/pre>\n<p>Now try it out &#8230;<\/p>\n<pre>\r\nC:\\\\php>phpcs C:\\\\Projects\\\\dummyproject\\\\test\\\\\r\n\r\nFILE: C:\\\\Projects\\\\dummyproject\\\\test\\\\AllTests.php\r\n--------------------------------------------------------------------------------\r\nFOUND 7 ERROR(S) AND 0 WARNING(S) AFFECTING 7 LINE(S)\r\n--------------------------------------------------------------------------------\r\n  1 | ERROR | End of line character is invalid; expected \"\\n\" but found \"\\r\\n\"\r\n  2 | ERROR | Missing file doc comment\r\n  3 | ERROR | Constants must be uppercase; expected 'PHPUNIT_MAIN_METHOD' but\r\n    |       | found 'PHPUnit_MAIN_METHOD'\r\n 12 | ERROR | Missing class doc comment\r\n 14 | ERROR | Missing function doc comment\r\n 19 | ERROR | Missing function doc comment\r\n 30 | ERROR | Constants must be uppercase; expected PHPUNIT_MAIN_METHOD but\r\n    |       | found PHPUnit_MAIN_METHOD\r\n--------------------------------------------------------------------------------\r\n<\/pre>\n<p>Check the documentation for what the various command line switches do, but you can generate summary reports as well on an entire directory tree:<\/p>\n<pre>\r\nC:\\\\php>phpcs --report=summary --standard=Squiz C:\\\\Projects\\\\dummyproject\\\\test\\\\\r\n\r\nPHP CODE SNIFFER REPORT SUMMARY\r\n--------------------------------------------------------------------------------\r\nFILE                                                            ERRORS  WARNINGS\r\n--------------------------------------------------------------------------------\r\nC:\\\\Projects\\\\dummyproject\\\\test\\\\AllTests.php                  24      0\r\nC:\\\\Projects\\\\dummyproject\\\\test\\\\NodeTest.php                  10      0\r\nC:\\\\Projects\\\\dummyproject\\\\test\\\\NodeTypeTest.php              11      0\r\n--------------------------------------------------------------------------------\r\nA TOTAL OF 45 ERROR(S) AND 0 WARNING(S) WERE FOUND IN 3 FILE(S)\r\n--------------------------------------------------------------------------------\r\n<\/pre>\n<\/p>\n<p> &#8230; <\/p>\n<p>Overall I&#8217;m quite happy with this set up which for the most part was pretty straight forward. I have no doubt it will evolve over time but I think it&#8217;s a good foundation on which to build upon.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m in the process of setting up a continuous integration environment for a new PHP project I&#8217;m starting. On our previous project, which was Java based, we used the following tools to support similar requirements on that project in order &hellip; <a href=\"https:\/\/virtualchaos.co.uk\/blog\/2007\/07\/02\/continuous-integration-with-php\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[391,392,125,124,126,399],"class_list":["post-210","post","type-post","status-publish","format-standard","hentry","category-continuous-integration","tag-agile","tag-continuous-integration","tag-pear","tag-php","tag-phpunit","tag-talis"],"_links":{"self":[{"href":"https:\/\/virtualchaos.co.uk\/blog\/wp-json\/wp\/v2\/posts\/210","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/virtualchaos.co.uk\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/virtualchaos.co.uk\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/virtualchaos.co.uk\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/virtualchaos.co.uk\/blog\/wp-json\/wp\/v2\/comments?post=210"}],"version-history":[{"count":0,"href":"https:\/\/virtualchaos.co.uk\/blog\/wp-json\/wp\/v2\/posts\/210\/revisions"}],"wp:attachment":[{"href":"https:\/\/virtualchaos.co.uk\/blog\/wp-json\/wp\/v2\/media?parent=210"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/virtualchaos.co.uk\/blog\/wp-json\/wp\/v2\/categories?post=210"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/virtualchaos.co.uk\/blog\/wp-json\/wp\/v2\/tags?post=210"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}