{"id":1389,"date":"2012-12-05T21:45:03","date_gmt":"2012-12-05T21:45:03","guid":{"rendered":"http:\/\/www.robertprice.co.uk\/robblog\/?p=1389"},"modified":"2012-12-05T21:45:03","modified_gmt":"2012-12-05T21:45:03","slug":"unit-testing-javascript-with-qunit-and-phing","status":"publish","type":"post","link":"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/","title":{"rendered":"Unit Testing JavaScript With QUnit And Phing"},"content":{"rendered":"<p>Recently I&#8217;ve been using both Phing for my PHP builds, and QUnit for my JavaScript unit tests, so I&#8217;ve been looking for a way to run these QUnit tests when Phing builds my application.<\/p>\n<p>By default Phing can run PHPUnit tests, but not QUnit. However Martin Jonsson has come to the rescue with his <a href=\"https:\/\/github.com\/martinj\/phing-task-qunit\">Qunit Phing Task<\/a>.<\/p>\n<p>QUnit Phing Tasks lets QUnit tests be run during a build and Phing can either pass or fail based on these results. As QUnit is written in JavaScript, QUnit Phing Task runs PhantomJS to call a JavaScript wrapper that passes the output back to PHP and Phing. PhantomJS is a headless JavaScript browser that can excute on a command line.<\/p>\n<h2>Using QUnit Phing Task<\/h2>\n<p>To run the QUnit Phing Task you need to install <a href=\"https:\/\/github.com\/ariya\/phantomjs\">PhantomJS<\/a>. I downloaded a binary and placed it in <var>\/usr\/local\/bin<\/var> on my system.<\/p>\n<p>You need to download the <a href=\"https:\/\/github.com\/martinj\/phing-task-qunit\">QUnit Phing Task<\/a>. I placed the files in a local <var>.\/lib<\/var> directory in my project.<\/p>\n<p>You will also need to download <a href=\"https:\/\/github.com\/jquery\/qunit\">QUnit<\/a>. I placed the files in a local <var>.\/tests<\/var> directory in my project.<\/p>\n<p>In the <var>.\/tests<\/var> directory I created an HTML file called <var>runner.html<\/var>. This is the page we need to call to run our tests.<\/p>\n<pre class=\"lang:xhtml decode:true \" >&lt;!DOCTYPE html&gt;\n\n&lt;html&gt;\n        &lt;head&gt;\n                &lt;meta chatset=\"utf-8\" \/&gt;\n                &lt;title&gt;Qunit Tests&lt;\/title&gt;\n                &lt;link rel=\"stylesheet\" href=\".\/qunit.css\"&gt;\n                &lt;script src=\".\/qunit.js\"&gt;&lt;\/script&gt;\n                &lt;script src=\".\/test.js\"&gt;&lt;\/script&gt;\n        &lt;\/head&gt;\n\n        &lt;body&gt;\n                &lt;div id=\"qunit\"&gt;&lt;\/div&gt;\n        &lt;\/body&gt;\n&lt;\/html&gt;<\/pre>\n<p>I also create a JavaScript file called <var>.\/test.js<\/var> in <var>.\/tests<\/var> to hold my JavaScript tests in.<\/p>\n<pre class=\"lang:default decode:true \" >test(\"testing for true\", function() {\n        ok(true, \"true is true\");\n});<\/pre>\n<p>Finally, I create a <var>build.xml<\/var> for my Phing build.<\/p>\n<pre class=\"lang:default decode:true \" >&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;project name=\"qunit example\" basedir=\".\" default=\"qunit\"&gt;\n\n        &lt;path id=\"project.class.path\"&gt;\n                &lt;pathelement dir=\".\/lib\/\" \/&gt;\n        &lt;\/path&gt;\n\n        &lt;taskdef name=\"qunit\" classname=\"QunitTask\"&gt;\n                &lt;classpath refid=\"project.class.path\" \/&gt;\n        &lt;\/taskdef&gt;\n\n        &lt;target name=\"qunit\" description=\"JavaScript Unit Test\"&gt;\n                &lt;qunit executable=\"DISPLAY=:0 \/usr\/local\/bin\/phantomjs\" haltonfailure=\"true\" runner=\".\/lib\/run-qunit.js\"&gt;\n                        &lt;fileset dir=\".\"&gt;\n                                &lt;include name=\"tests\/runner.html\" \/&gt;\n                        &lt;\/fileset&gt;\n                &lt;\/qunit&gt;\n        &lt;\/target&gt;\n\n&lt;\/project&gt;<\/pre>\n<p>In this I am specifying a path to my <var>.\/lib<\/var> directory as this is where the QUnit Phing Task code is. The path is then used in the taskdeftask which is used to create the &lt;qunit&gt; task. Now when I call &lt;qunit&gt; in my qunit target I just pass in the location of the executable &#8211; in this case where PhantomJS is, whether Phing should halt if the QUnit tests fail, and where to find the the JavaScript that runs QUnit. Inside the task, we pass in where our runner pages are, as we only have the one in this example we include it by name <var>tests\/runner.html<\/var>.<\/p>\n<p>Running this gives us the following&#8230;<\/p>\n<pre class=\"lang:sh decode:true \" >rob@lamp ~\/qunitphing&gt; phing\nBuildfile: \/root\/qunitphing\/build.xml\n\nqunit example &gt; qunit:\n\n    [qunit] .\/tests\/runner.html: 1 tests of 1 passed, 0 failed\n\nBUILD FINISHED\n\nTotal time: 0.3275 seconds<\/pre>\n<p>So we can see our tests have passed. Let&#8217;s change our <var>test.js<\/var> so that it fails.<\/p>\n<pre class=\"lang:js decode:true \" title=\"A failing QUnit test\" >test(\"testing for true\", function() {\n        ok(true, \"true is true\");\n        ok(false, \"false is true\");\n});<\/pre>\n<p>This test should fail, as false is not true and will fail the <code>ok<\/code> assertion.<\/p>\n<pre class=\"lang:scheme decode:true \" >rob@lamp ~\/qunitphing&gt; phing\nBuildfile: \/root\/qunitphing\/build.xml\n\nqunit example &gt; qunit:\n\n    [qunit] 1 tests failed on: .\/tests\/runner.html\n    [qunit] Failed test: testing for true (1, 1, 2)\nExecution of target \"qunit\" failed for the following reason: \/root\/qunitphing\/build.xml:13:41: QUnit tests failed\n\nBUILD FAILED\n\/root\/qunitphing\/build.xml:13:41: QUnit tests failed\nTotal time: 0.3258 seconds\n<\/pre>\n<p>So we can see that Phing has failed our build due to the QUnit tests failing, which is what we want.<\/p>\n<h2>Summary<\/h2>\n<p>Although a very simple and contrived example, I hope this has shown you how to add JavaScript unit tests using QUnit to your Phing build.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently I&#8217;ve been using both Phing for my PHP builds, and QUnit for my JavaScript unit tests, so I&#8217;ve been looking for a way to run these QUnit tests when Phing builds my application. By default Phing can run PHPUnit tests, but not QUnit. However Martin Jonsson has come to the rescue with his Qunit &hellip; <a href=\"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Unit Testing JavaScript With QUnit And Phing&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[2],"tags":[31,49,50,54],"class_list":["post-1389","post","type-post","status-publish","format-standard","hentry","category-dev","tag-javascript","tag-phing","tag-php","tag-qunit"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Unit Testing JavaScript With QUnit And Phing - Robert Price<\/title>\n<meta name=\"description\" content=\"A short quide to adding QUnit JavaScript unit tests into a PHP Phing build.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Unit Testing JavaScript With QUnit And Phing - Robert Price\" \/>\n<meta property=\"og:description\" content=\"A short quide to adding QUnit JavaScript unit tests into a PHP Phing build.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/\" \/>\n<meta property=\"og:site_name\" content=\"Robert Price\" \/>\n<meta property=\"article:published_time\" content=\"2012-12-05T21:45:03+00:00\" \/>\n<meta name=\"author\" content=\"rob\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"rob\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/unit-testing-javascript-with-qunit-and-phing\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/unit-testing-javascript-with-qunit-and-phing\\\/\"},\"author\":{\"name\":\"rob\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#\\\/schema\\\/person\\\/fac6d5b076e0e14e1fb13e15b542a6c5\"},\"headline\":\"Unit Testing JavaScript With QUnit And Phing\",\"datePublished\":\"2012-12-05T21:45:03+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/unit-testing-javascript-with-qunit-and-phing\\\/\"},\"wordCount\":443,\"keywords\":[\"JavaScript\",\"Phing\",\"PHP\",\"qunit\"],\"articleSection\":[\"Dev\"],\"inLanguage\":\"en-GB\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/unit-testing-javascript-with-qunit-and-phing\\\/\",\"url\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/unit-testing-javascript-with-qunit-and-phing\\\/\",\"name\":\"Unit Testing JavaScript With QUnit And Phing - Robert Price\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#website\"},\"datePublished\":\"2012-12-05T21:45:03+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#\\\/schema\\\/person\\\/fac6d5b076e0e14e1fb13e15b542a6c5\"},\"description\":\"A short quide to adding QUnit JavaScript unit tests into a PHP Phing build.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/unit-testing-javascript-with-qunit-and-phing\\\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/unit-testing-javascript-with-qunit-and-phing\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/unit-testing-javascript-with-qunit-and-phing\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Unit Testing JavaScript With QUnit And Phing\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#website\",\"url\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/\",\"name\":\"Robert Price\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#\\\/schema\\\/person\\\/fac6d5b076e0e14e1fb13e15b542a6c5\",\"name\":\"rob\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g\",\"caption\":\"rob\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Unit Testing JavaScript With QUnit And Phing - Robert Price","description":"A short quide to adding QUnit JavaScript unit tests into a PHP Phing build.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/","og_locale":"en_GB","og_type":"article","og_title":"Unit Testing JavaScript With QUnit And Phing - Robert Price","og_description":"A short quide to adding QUnit JavaScript unit tests into a PHP Phing build.","og_url":"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/","og_site_name":"Robert Price","article_published_time":"2012-12-05T21:45:03+00:00","author":"rob","twitter_card":"summary_large_image","twitter_misc":{"Written by":"rob","Estimated reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/#article","isPartOf":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/"},"author":{"name":"rob","@id":"https:\/\/www.robertprice.co.uk\/robblog\/#\/schema\/person\/fac6d5b076e0e14e1fb13e15b542a6c5"},"headline":"Unit Testing JavaScript With QUnit And Phing","datePublished":"2012-12-05T21:45:03+00:00","mainEntityOfPage":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/"},"wordCount":443,"keywords":["JavaScript","Phing","PHP","qunit"],"articleSection":["Dev"],"inLanguage":"en-GB"},{"@type":"WebPage","@id":"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/","url":"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/","name":"Unit Testing JavaScript With QUnit And Phing - Robert Price","isPartOf":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/#website"},"datePublished":"2012-12-05T21:45:03+00:00","author":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/#\/schema\/person\/fac6d5b076e0e14e1fb13e15b542a6c5"},"description":"A short quide to adding QUnit JavaScript unit tests into a PHP Phing build.","breadcrumb":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.robertprice.co.uk\/robblog\/unit-testing-javascript-with-qunit-and-phing\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.robertprice.co.uk\/robblog\/"},{"@type":"ListItem","position":2,"name":"Unit Testing JavaScript With QUnit And Phing"}]},{"@type":"WebSite","@id":"https:\/\/www.robertprice.co.uk\/robblog\/#website","url":"https:\/\/www.robertprice.co.uk\/robblog\/","name":"Robert Price","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.robertprice.co.uk\/robblog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Person","@id":"https:\/\/www.robertprice.co.uk\/robblog\/#\/schema\/person\/fac6d5b076e0e14e1fb13e15b542a6c5","name":"rob","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/secure.gravatar.com\/avatar\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g","caption":"rob"}}]}},"_links":{"self":[{"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/posts\/1389","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/comments?post=1389"}],"version-history":[{"count":0,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/posts\/1389\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/media?parent=1389"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/categories?post=1389"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/tags?post=1389"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}