{"id":301,"date":"2015-11-03T08:50:17","date_gmt":"2015-11-03T08:50:17","guid":{"rendered":"https:\/\/blogs.mathworks.com\/developer\/?p=301"},"modified":"2015-11-03T08:50:17","modified_gmt":"2015-11-03T08:50:17","slug":"tap-diagnostics-and-junit-xml","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/developer\/2015\/11\/03\/tap-diagnostics-and-junit-xml\/","title":{"rendered":"Format Sibling Rivalry"},"content":{"rendered":"\r\n<div class=\"content\"><!--introduction--><p>Goodness time flies! It has been a while since we've had a blog update, While I really would like to keep the conversation we have going on here moving, this is how I would like you to envision what I have been up to recently:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/2015CodeMonkey.gif\" alt=\"\"> <\/p><p>That's right...just think of me as your code monkey, tirelessly pushing forward developer oriented infrastructure (and blog topics). We do indeed have a lot of exciting things we are working on in MATLAB that we will definitely discuss here when the time comes. I can't wait.<\/p><p>However, there are already so many discussions to explore. Today I wanted to highlight another Continuous Integration workflow improvement that is available now that R2015b has been released.<\/p><!--\/introduction--><p><b>The Beauty is in the Details<\/b><\/p><p>If you <a href=\"https:\/\/blogs.mathworks.com\/developer\/2015\/01\/29\/tap-plugin\/\">remember<\/a>, MATLAB can connect to CI Systems like Jenkins&#8482; which can be configured to run your tests periodically and\/or whenever files are modified in your source control system. This is done using the <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/matlab.unittest.plugins.tapplugin-class.html\">TAPPlugin<\/a> for the MATLAB TestRunner. This plugin has been enhanced in R2015b to show the diagnostic information in the TAP stream for an improved display in the CI reports. For example, with absolutely no change in the script discussed in the earlier post, the Jenkins output now includes the diagnostics (we heard you <a href=\"https:\/\/blogs.mathworks.com\/developer\/2015\/01\/29\/tap-plugin\/#comment-24\">Aditya<\/a>!). So, for the following failing test:<\/p><pre class=\"language-matlab\">\r\n<span class=\"keyword\">classdef<\/span> NumericsTest &lt; matlab.unittest.TestCase\r\n    <span class=\"comment\">% Copyright 2012 The MathWorks, Inc.<\/span>\r\n    \r\n    <span class=\"keyword\">methods<\/span>(Test)\r\n        <span class=\"keyword\">function<\/span> shouldReallyBePi(testCase)\r\n            wannabePi = 22\/7;\r\n            testCase.verifyEqual(wannabePi, pi, <span class=\"string\">'RelTol'<\/span>, 1e-8, <span class=\"keyword\">...<\/span>\r\n                <span class=\"string\">'I am not gonna allow 22\/7 as a stand in for pi!'<\/span>);\r\n        <span class=\"keyword\">end<\/span>\r\n    <span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n\r\n<\/pre><p>We now see the helpful diagnostics right in the Jenkins reports.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/2015TAPDiagnostics.png\" alt=\"\"> <\/p><p>Of course this may differ depending on how your particular CI system presents the TAP output, but MATLAB is certainly providing a richer TAP stream to begin with.<\/p><p><b>A Horse of a Different Format<\/b><\/p><p>Speaking of different CI systems, while Jenkins is great to highlight because it is simple to show in a short blog post and is popular to boot, but there are of course many other CI systems out there. One of the reasons I am a supporter of the TAP format is because it aims to be language independent. However, unfortunately there are some CI systems that simply don't have the capability to process TAP streams. The de-facto JUnit XML format (which is in fact the xml output produced by the Apache Ant JUnit task) is very widespread and supported by some CI systems that do not support the TAP protocol. Once again, R2015b to the rescue because test results can now be exported to the JUnit format using the new <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/matlab.unittest.plugins.xmlplugin-class.html\">XMLPlugin<\/a>. This allows a few benefits:<\/p><div><ul><li>It can be used to integrate with CI systems that don't support the TAP protocol.<\/li><li>Being XML, one can apply XSLT transformations on the file to convert the results to another format if that's your kind of thing.<\/li><li>You can also benefit from other intangibles of using the popular format which I plan to demonstrate in a future post.<\/li><\/ul><\/div><p>Before that though, it would be great to have the same detailed diagnostics as the new version of the TAPPlugin and it does! To see this you can just install the MATLAB XMLPlugin onto the TestRunner as follows:<\/p><pre class=\"language-matlab\">\r\nimport <span class=\"string\">matlab.unittest.TestSuite<\/span>;\r\nimport <span class=\"string\">matlab.unittest.TestRunner<\/span>;\r\nimport <span class=\"string\">matlab.unittest.plugins.TAPPlugin<\/span>;\r\nimport <span class=\"string\">matlab.unittest.plugins.ToFile<\/span>;\r\n\r\nimport <span class=\"string\">matlab.unittest.plugins.XMLPlugin<\/span>;\r\n\r\n<span class=\"keyword\">try<\/span>\r\n    suite = TestSuite.fromPackage(<span class=\"string\">'testcases'<\/span>,<span class=\"string\">'IncludingSubpackages'<\/span>,true);\r\n    \r\n    runner = TestRunner.withTextOutput();\r\n    \r\n    <span class=\"comment\">% Add the JUnit XML plugin<\/span>\r\n    xmlFile = fullfile(getenv(<span class=\"string\">'WORKSPACE'<\/span>), <span class=\"string\">'testResults.xml'<\/span>);\r\n    runner.addPlugin(XMLPlugin.producingJUnitFormat(xmlFile));\r\n    \r\n    <span class=\"comment\">% Also add the TAP plugin because why not? <\/span>\r\n    tapFile = fullfile(getenv(<span class=\"string\">'WORKSPACE'<\/span>), <span class=\"string\">'testResults.tap'<\/span>);\r\n    runner.addPlugin(TAPPlugin.producingOriginalFormat(ToFile(tapFile)));\r\n        \r\n    results = runner.run(suite);\r\n    display(results);\r\n<span class=\"keyword\">catch<\/span> e\r\n    disp(getReport(e,<span class=\"string\">'extended'<\/span>));\r\n    exit(1);\r\n<span class=\"keyword\">end<\/span>\r\nexit;\r\n\r\n<\/pre><p>Then configure a post-build step in Jenkins to publish the \"JUnit\" results:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/2015AddJUnitResults.png\" alt=\"\"> <\/p><p>...and viola, we can see the diagnostics for the JUnit publishing step as well:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/2015XMLDiagnostics.png\" alt=\"\"> <\/p><p>So which output format is the favorite child? You tell me! Did you notice the improved diagnostics of the TAPPlugin? Can you benefit from the JUnit-style XML format? If so I'd love to hear some details!<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_53332ed94d9d41f6861480930bc6d960() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='53332ed94d9d41f6861480930bc6d960 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 53332ed94d9d41f6861480930bc6d960';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2015 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_53332ed94d9d41f6861480930bc6d960()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2015b<br><\/p><\/div><!--\r\n53332ed94d9d41f6861480930bc6d960 ##### SOURCE BEGIN #####\r\n%%\r\n%\r\n% Goodness time flies! It has been a while since we've had a blog update,\r\n% While I really would like to keep the conversation we have going on here\r\n% moving, this is how I would like you to envision what I have been up to\r\n% recently:\r\n%\r\n% <<2015CodeMonkey.gif>>\r\n%\r\n% That's right...just think of me as your code monkey, tirelessly pushing\r\n% forward developer oriented infrastructure (and blog topics). We do indeed\r\n% have a lot of exciting things we are working on in MATLAB that we will\r\n% definitely discuss here when the time comes. I can't wait.\r\n%\r\n%\r\n% However, there are already so many discussions to explore. Today I wanted\r\n% to highlight another Continuous Integration workflow improvement that is\r\n% available now that R2015b has been released.\r\n%\r\n%%\r\n% *The Beauty is in the Details*\r\n%\r\n% If you <https:\/\/blogs.mathworks.com\/developer\/2015\/01\/29\/tap-plugin\/\r\n% remember>, MATLAB can connect to CI Systems like Jenkins(TM) which can be\r\n% configured to run your tests periodically and\/or whenever files are\r\n% modified in your source control system. This is done using the\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/matlab.unittest.plugins.tapplugin-class.html\r\n% TAPPlugin> for the MATLAB TestRunner. This plugin has been enhanced in\r\n% R2015b to show the diagnostic information in the TAP stream for an\r\n% improved display in the CI reports. For example, with absolutely no\r\n% change in the script discussed in the earlier post, the Jenkins output\r\n% now includes the diagnostics (we heard you\r\n% <https:\/\/blogs.mathworks.com\/developer\/2015\/01\/29\/tap-plugin\/#comment-24\r\n% Aditya>!). So, for the following failing test:\r\n%\r\n% <include>NumericsTest.m<\/include>\r\n%\r\n% We now see the helpful diagnostics right in the Jenkins reports. \r\n%\r\n% <<2015TAPDiagnostics.png>>\r\n%\r\n% Of course this may differ depending on how your particular CI system\r\n% presents the TAP output, but MATLAB is certainly providing a richer TAP\r\n% stream to begin with.\r\n%\r\n%% \r\n% *A Horse of a Different Format*\r\n%\r\n% Speaking of different CI systems, while Jenkins is great to highlight\r\n% because it is simple to show in a short blog post and is popular to boot,\r\n% but there are of course many other CI systems out there. One of the\r\n% reasons I am a supporter of the TAP format is because it aims to be\r\n% language independent. However, unfortunately there are some CI systems\r\n% that simply don't have the capability to process TAP streams. The\r\n% de-facto JUnit XML format (which is in fact the xml output produced by\r\n% the Apache Ant JUnit task) is very widespread and supported by some CI\r\n% systems that do not support the TAP protocol. Once again, R2015b to the\r\n% rescue because test results can now be exported to the JUnit format using\r\n% the new\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/matlab.unittest.plugins.xmlplugin-class.html\r\n% XMLPlugin>. This allows a few benefits:\r\n%\r\n% * It can be used to integrate with CI systems that don't support the TAP\r\n% protocol.\r\n% * Being XML, one can apply XSLT transformations on the file to convert\r\n% the results to another format if that's your kind of thing.\r\n% * You can also benefit from other intangibles of using the popular\r\n% format which I plan to demonstrate in a future post.\r\n% \r\n% Before that though, it would be great to have the same detailed\r\n% diagnostics as the new version of the TAPPlugin and it does! To see this\r\n% you can just install the MATLAB XMLPlugin onto the TestRunner as follows:\r\n%\r\n% <include>runALL_THE_TESTS.m<\/include>\r\n%\r\n% Then configure a post-build step in Jenkins to publish the \"JUnit\" results:\r\n%\r\n% <<2015AddJUnitResults.png>>\r\n%\r\n% ...and viola, we can see the diagnostics for the JUnit publishing step as\r\n% well:\r\n%\r\n% <<2015XMLDiagnostics.png>>\r\n%\r\n% So which output format is the favorite child? You tell me! Did you notice\r\n% the improved diagnostics of the TAPPlugin? Can you benefit from the\r\n% JUnit-style XML format? If so I'd love to hear some details!\r\n\r\n\r\n\r\n\r\n\r\n##### SOURCE END ##### 53332ed94d9d41f6861480930bc6d960\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/2015AddJUnitResults.png\" onError=\"this.style.display ='none';\" \/><\/div><!--introduction--><p>Goodness time flies! It has been a while since we've had a blog update, While I really would like to keep the conversation we have going on here moving, this is how I would like you to envision what I have been up to recently:... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/developer\/2015\/11\/03\/tap-diagnostics-and-junit-xml\/\">read more >><\/a><\/p>","protected":false},"author":90,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/301"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/users\/90"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/comments?post=301"}],"version-history":[{"count":10,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/301\/revisions"}],"predecessor-version":[{"id":318,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/301\/revisions\/318"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/media?parent=301"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/categories?post=301"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/tags?post=301"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}