{"id":739,"date":"2016-09-29T16:42:35","date_gmt":"2016-09-29T16:42:35","guid":{"rendered":"https:\/\/blogs.mathworks.com\/developer\/?p=739"},"modified":"2016-09-29T16:42:35","modified_gmt":"2016-09-29T16:42:35","slug":"tap-with-yaml","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/developer\/2016\/09\/29\/tap-with-yaml\/","title":{"rendered":"Turn on the YAML Channel!"},"content":{"rendered":"\r\n<div class=\"content\"><p>Diagnostics. They are the secret sauce of an effective test framework and we certainly take our job seriously at providing diagnostics that are not a little too hot or a little too cold, but juuuuusssst the right information to present, especially when encountering a failure. The reason this is so important is because good diagnostics can save human time, which is typically far more precious than computer time.<\/p><p>Indeed, this is one of the reasons why CI systems are so valuable. They take away the human time required to build, qualify, and deploy software and delegate that job to a machine rather than compromising your productivity. However, when a failure occurs you then rely on diagnostics from the failure to give you some hint as to what is going on.<\/p><p>Let me show you an example of this. I went and downloaded the <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/44125-digraph-datatype-with-vertex-labels\">digraph<\/a> file exchange submission to highlight this. Note, this submission has now been superseded by the <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/graph-and-network-algorithms.html\">fantastic graph functionality<\/a> included in R2015b and later, but if you are not yet on that release you can certainly check it out. However, one reason I am including that is because it has a nice test suite included with it that we can run from your CI system.<\/p><p>Not yet set up with a CI system? Take a look at some of <a href=\"https:\/\/blogs.mathworks.com\/developer\/category\/continuous-integration\/?s_tid=Blog_developer_Category\">these other posts<\/a> to get you going. If you haven't read them yet go from the bottom up on that category page.<\/p><p>Anyway, let's continue with Jenkins and show how the diagnostics currently show up with these diagraph tests. Here is the script I am asking MATLAB to run in the Jenkins project:<\/p><pre class=\"language-matlab\">\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\n<span class=\"keyword\">try<\/span>\r\n    suite = testsuite(<span class=\"string\">'unittest'<\/span>);\r\n    runner = TestRunner.withTextOutput(<span class=\"string\">'Verbosity'<\/span>,3);\r\n    <span class=\"comment\">% Add the TAP plugin<\/span>\r\n    tapFile = fullfile(getenv(<span class=\"string\">'WORKSPACE'<\/span>), <span class=\"string\">'testResults.tap'<\/span>);\r\n    \r\n    runner.addPlugin(TAPPlugin.producingOriginalFormat(ToFile(tapFile)));\r\n    results = runner.run(suite)\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>Does it pass? Well when we run this job on the digraph submission in Jenkins here is what we get:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2016_ExtendedView_OrigFormat.png\" alt=\"\"> <\/p><p>Alright. Not bad but it looks like we have a failure. Do we know why it failed? Not yet. For that, we need to drill into the <b>\"TAP Test Results\"<\/b> instead of the <b>\"Extended TAP Test Results\"<\/b> of the Jenkins TAP Plugin.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2016_NormalView_OrigFormat.png\" alt=\"\"> <\/p><p>Here, we can finally dig into the failing test by clicking on it and getting to this page, which shows the diagnostics:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2016_OriginalDiagnosticView.png\" alt=\"\"> <\/p><p>Whew. Alright it took us a couple clicks, but we made it. We can see pretty quickly that that test is validating against an incorrect error message id. Looking at the two ids, you can take a pretty good guess that this is probably not actually a real problem in the software, but may simply require a trivial test update since perhaps the id has changed across versions of MATLAB. No problem. Quick to find, quick to fix.<\/p><p>However, I think we can improve on how we got here. For one, there were just too many clicks needed. Also, there seems to be some whitespace formatting lost when the Jenkins plugin displayed the diagnostic values. In this case it may have just been easier to look at the tap file output directly:<\/p><pre>\r\n1..51\r\nnot ok 1 - digraphAPITest\/digraph\r\n# ================================================================================\r\n# Verification failed in digraphAPITest\/digraph.\r\n# \r\n#     ---------------------\r\n#     Framework Diagnostic:\r\n#     ---------------------\r\n#     verifyError failed.\r\n#     --&gt; The function threw the wrong exception.\r\n#         \r\n#         Actual Exception:\r\n#             'MATLAB:TooManyInputs'\r\n#         Expected Exception:\r\n#             'MATLAB:maxrhs'\r\n#     \r\n#     Actual Error Report:\r\n#         Error using digraph\r\n#         Too many input arguments.\r\n#         \r\n#         Error in digraphAPITest&gt;@()digraph('foo') (line 14)\r\n#                     testCase.verifyError(@()digraph('foo'),'MATLAB:maxrhs');\r\n#     Evaluated Function:\r\n#             @()digraph('foo')\r\n# \r\n#     ------------------\r\n#     Stack Information:\r\n#     ------------------\r\n#     In H:\\Documents\\MATLAB\\unittest\\digraphAPITest.m (digraphAPITest.digraph) at 14\r\n# ================================================================================\r\n# \r\nok 2 - digraphAPITest\/isempty_\r\nok 3 - digraphAPITest\/isEquivalent\r\nok 4 - digraphAPITest\/addVertex\r\nok 5 - digraphAPITest\/removeVertex\r\nok 6 - digraphAPITest\/hasVertex\r\nok 7 - digraphAPITest\/assertVertex\r\nok 8 - digraphAPITest\/addEdge\r\nok 9 - digraphAPITest\/removeEdge\r\nok 10 - digraphAPITest\/hasEdge\r\nok 11 - digraphAPITest\/findall\r\nok 12 - digraphAPITest\/hasCycle\r\nok 13 - digraphAPITest\/isComplete\r\nok 14 - digraphAPITest\/shortestPath\r\nok 15 - digraphAPITest\/subgraph\r\nok 16 - digraphAPITest\/minimalEdges\r\nok 17 - digraphAPITest\/transitiveClosure\r\nok 18 - digraphAPITest\/union\r\nok 19 - digraphAPITest\/intersect\r\nok 20 - digraphAPITest\/sort\r\nok 21 - digraphAPITest\/copy_\r\nok 22 - digraphAPITest\/reset\r\nok 23 - digraphAPITest\/spy\r\nok 24 - digraphFunctionalityTest\/Vertex\r\nok 25 - digraphFunctionalityTest\/Edge\r\nok 26 - digraphFunctionalityTest\/unionBasic\r\nok 27 - digraphFunctionalityTest\/unionAdvanced\r\nok 28 - digraphFunctionalityTest\/intersectBasic\r\nok 29 - digraphFunctionalityTest\/intersectAdvanced\r\nok 30 - digraphFunctionalityTest\/hasPath\r\nok 31 - digraphFunctionalityTest\/sort\r\nok 32 - digraphFunctionalityTest\/shortestPathBasic\r\nok 33 - digraphFunctionalityTest\/shortestPathAdvanced\r\nok 34 - digraphFunctionalityTest\/hasCycle\r\nok 35 - digraphFunctionalityTest\/CycleDoesNotTriggerInfiniteLoop\r\nok 36 - digraphFunctionalityTest\/findall\r\nok 37 - digraphFunctionalityTest\/subgraph\r\nok 38 - digraphFunctionalityTest\/isEquivalent\r\nok 39 - digraphFunctionalityTest\/copy_\r\nok 40 - digraphFunctionalityTest\/isComplete\r\nok 41 - digraphFunctionalityTest\/isempty_\r\nok 42 - digraphFunctionalityTest\/transitiveClosureBasic\r\nok 43 - digraphFunctionalityTest\/transitiveClosureAdvanced\r\nok 44 - digraphFunctionalityTest\/transitiveClosureCycleAndComplete\r\nok 45 - digraphFunctionalityTest\/minimalEdgesBasic\r\nok 46 - digraphFunctionalityTest\/minimalEdgesAdvanced\r\nok 47 - digraphFunctionalityTest\/minimalEdgesCycleAndComplete\r\nok 48 - digraphFunctionalityTest\/trivialgraph\r\nok 49 - digraphFunctionalityTest\/isEquivalentSubclass\r\nok 50 - digraphFunctionalityTest\/subclassesArePreserved\r\nok 51 - digraphFunctionalityTest\/spy\r\n<\/pre><p>Well with R2016b there's an even better way. Did you ever wonder why the MATLAB TAPPlugin is created using the a call like the following?<\/p><pre class=\"codeinput\">import <span class=\"string\">matlab.unittest.plugins.TAPPlugin<\/span>;\r\nplugin = TAPPlugin.producingOriginalFormat\r\n<\/pre><pre class=\"codeoutput\">\r\nplugin = \r\n\r\n  TAPOriginalFormatPlugin with properties:\r\n\r\n    IncludePassingDiagnostics: 0\r\n                    Verbosity: Terse\r\n     ExcludeLoggedDiagnostics: 0\r\n\r\n<\/pre><p>What is the deal with the original format? What other formats are there? Well, quick history lession, the <a href=\"http:\/\/testanything.org\/\">TAP format<\/a> was developed over a number of years by the Perl community, but the formal specification really began at what could be called version 12 (and what we have termed the original format since this version was the first with <a href=\"http:\/\/testanything.org\/tap-specification.html\">a documented specification<\/a>). Since then, there has also arisen a <a href=\"http:\/\/testanything.org\/tap-version-13-specification.html\">version 13 format<\/a>. Actually there is a group of people involved in the discussions who are discussing a version 14 as well but there has been no formal specification of that format yet. If you are interested, and if you want to join me in ensuring that any such format takes into account the needs of the MATLAB community, certainly do get involved. There is a <a href=\"https:\/\/github.com\/TestAnything\/Specification\">github project<\/a> and a <a href=\"https:\/\/testanything.slack.com\/\">slack channel<\/a> discussing the format that you can take part in.<\/p><p>Anyway, the news is that R2016b includes the option to produce the version 13 TAP format!<\/p><pre class=\"codeinput\">plugin = TAPPlugin.producingVersion13\r\n<\/pre><pre class=\"codeoutput\">\r\nplugin = \r\n\r\n  TAPVersion13Plugin with properties:\r\n\r\n    IncludePassingDiagnostics: 0\r\n                    Verbosity: Terse\r\n     ExcludeLoggedDiagnostics: 0\r\n\r\n<\/pre><p>The largest takeaway in this format is the fact that diagnostics can be included in YAML(ish) blocks in the tap stream. You may or may not be aware, but:<\/p><p><b>Y<\/b> AML<\/p><p><b>A<\/b> in't<\/p><p><b>M<\/b> arkup<\/p><p><b>L<\/b> anguage<\/p><p>We all know how programmers love recursive acronyms (e.g, <a href=\"https:\/\/en.wikipedia.org\/wiki\/GNU\">GNU<\/a>, <a href=\"https:\/\/en.wikipedia.org\/wiki\/Microsoft_XNA\">XNA<\/a>). What does this mean for us? A better diagnostics experience. Let's see this same test failure in our Jenkins job but instead using version 13 of the TAP protocol.<\/p><pre class=\"language-matlab\">\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\n<span class=\"keyword\">try<\/span>\r\n    suite = testsuite(<span class=\"string\">'unittest'<\/span>);\r\n    runner = TestRunner.withTextOutput(<span class=\"string\">'Verbosity'<\/span>,3);\r\n    <span class=\"comment\">% Add the TAP plugin<\/span>\r\n    tapFile = fullfile(getenv(<span class=\"string\">'WORKSPACE'<\/span>), <span class=\"string\">'testResults.tap'<\/span>);\r\n    \r\n    runner.addPlugin(TAPPlugin.producingVersion13(ToFile(tapFile)));\r\n    results = runner.run(suite)\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>Using this produces the following TAP Stream<\/p><pre>\r\nTAP version 13\r\n1..51\r\nnot ok 1 - digraphAPITest\/digraph\r\n    ---\r\n    Event:\r\n        Event Name: 'VerificationFailed'\r\n        Scope: 'digraphAPITest\/digraph'\r\n        Framework Diagnostic: |\r\n            verifyError failed.\r\n            --&gt; The function threw the wrong exception.\r\n                \r\n                Actual Exception:\r\n                    'MATLAB:TooManyInputs'\r\n                Expected Exception:\r\n                    'MATLAB:maxrhs'\r\n            \r\n            Actual Error Report:\r\n                Error using digraph\r\n                Too many input arguments.\r\n                \r\n                Error in digraphAPITest&gt;@()digraph('foo') (line 14)\r\n                            testCase.verifyError(@()digraph('foo'),'MATLAB:maxrhs');\r\n            Evaluated Function:\r\n                    @()digraph('foo')\r\n        Stack: |\r\n            In H:\\Documents\\MATLAB\\unittest\\digraphAPITest.m (digraphAPITest.digraph) at 14\r\n    ...\r\nok 2 - digraphAPITest\/isempty_\r\nok 3 - digraphAPITest\/isEquivalent\r\nok 4 - digraphAPITest\/addVertex\r\nok 5 - digraphAPITest\/removeVertex\r\nok 6 - digraphAPITest\/hasVertex\r\nok 7 - digraphAPITest\/assertVertex\r\nok 8 - digraphAPITest\/addEdge\r\nok 9 - digraphAPITest\/removeEdge\r\nok 10 - digraphAPITest\/hasEdge\r\nok 11 - digraphAPITest\/findall\r\nok 12 - digraphAPITest\/hasCycle\r\nok 13 - digraphAPITest\/isComplete\r\nok 14 - digraphAPITest\/shortestPath\r\nok 15 - digraphAPITest\/subgraph\r\nok 16 - digraphAPITest\/minimalEdges\r\nok 17 - digraphAPITest\/transitiveClosure\r\nok 18 - digraphAPITest\/union\r\nok 19 - digraphAPITest\/intersect\r\nok 20 - digraphAPITest\/sort\r\nok 21 - digraphAPITest\/copy_\r\nok 22 - digraphAPITest\/reset\r\nok 23 - digraphAPITest\/spy\r\nok 24 - digraphFunctionalityTest\/Vertex\r\nok 25 - digraphFunctionalityTest\/Edge\r\nok 26 - digraphFunctionalityTest\/unionBasic\r\nok 27 - digraphFunctionalityTest\/unionAdvanced\r\nok 28 - digraphFunctionalityTest\/intersectBasic\r\nok 29 - digraphFunctionalityTest\/intersectAdvanced\r\nok 30 - digraphFunctionalityTest\/hasPath\r\nok 31 - digraphFunctionalityTest\/sort\r\nok 32 - digraphFunctionalityTest\/shortestPathBasic\r\nok 33 - digraphFunctionalityTest\/shortestPathAdvanced\r\nok 34 - digraphFunctionalityTest\/hasCycle\r\nok 35 - digraphFunctionalityTest\/CycleDoesNotTriggerInfiniteLoop\r\nok 36 - digraphFunctionalityTest\/findall\r\nok 37 - digraphFunctionalityTest\/subgraph\r\nok 38 - digraphFunctionalityTest\/isEquivalent\r\nok 39 - digraphFunctionalityTest\/copy_\r\nok 40 - digraphFunctionalityTest\/isComplete\r\nok 41 - digraphFunctionalityTest\/isempty_\r\nok 42 - digraphFunctionalityTest\/transitiveClosureBasic\r\nok 43 - digraphFunctionalityTest\/transitiveClosureAdvanced\r\nok 44 - digraphFunctionalityTest\/transitiveClosureCycleAndComplete\r\nok 45 - digraphFunctionalityTest\/minimalEdgesBasic\r\nok 46 - digraphFunctionalityTest\/minimalEdgesAdvanced\r\nok 47 - digraphFunctionalityTest\/minimalEdgesCycleAndComplete\r\nok 48 - digraphFunctionalityTest\/trivialgraph\r\nok 49 - digraphFunctionalityTest\/isEquivalentSubclass\r\nok 50 - digraphFunctionalityTest\/subclassesArePreserved\r\nok 51 - digraphFunctionalityTest\/spy\r\n<\/pre><p>Very nice, we are in business with roughly the same failure diagnostics as the original format. However, the big win is that now that the diagnostics are in a structured format, other tools (like Jenkins) can represent them with much more flavor. This is now what the <b>\"TAP Extended Test Results\"<\/b> pages looks like in Jenkins.:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2016_ExtendedView_ExtendedFormat.png\" alt=\"\"> <\/p><p>Now we can see all of the failure diagnostics on a single test results page with much more clarity and structure. Pretty sweet.<\/p><p>Do you see yourself benefitting from the more structured diagnostics that we get with version 13 of the TAP format? Do you have any stories to tell where good diagnostics saved you a bunch of debugging time? Do tell!<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_a52b02c6bcc94d859735199955c532e0() {\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='a52b02c6bcc94d859735199955c532e0 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' a52b02c6bcc94d859735199955c532e0';\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 2016 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_a52b02c6bcc94d859735199955c532e0()\"><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; R2016b<br><\/p><\/div><!--\r\na52b02c6bcc94d859735199955c532e0 ##### SOURCE BEGIN #####\r\n%%\r\n%\r\n% Diagnostics. They are the secret sauce of an effective test framework and\r\n% we certainly take our job seriously at providing diagnostics that are not\r\n% a little too hot or a little too cold, but juuuuusssst the right\r\n% information to present, especially when encountering a failure. The\r\n% reason this is so important is because good diagnostics can save\r\n% human time, which is typically far more precious than computer time. \r\n%\r\n% Indeed, this is one of the reasons why CI systems are so valuable. They\r\n% take away the human time required to build, qualify, and deploy software\r\n% and delegate that job to a machine rather than compromising your\r\n% productivity. However, when a failure occurs you then rely on diagnostics\r\n% from the failure to give you some hint as to what is going on.\r\n%\r\n% Let me show you an example of this. I went and downloaded the\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/44125-digraph-datatype-with-vertex-labels\r\n% digraph> file exchange submission to highlight this. Note, this\r\n% submission has now been superseded by the\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/graph-and-network-algorithms.html\r\n% fantastic graph functionality> included in R2015b and later, but if you\r\n% are not yet on that release you can certainly check it out. However, one\r\n% reason I am including that is because it has a nice test suite included\r\n% with it that we can run from your CI system.\r\n%\r\n% Not yet set up with a CI system? Take a look at some of\r\n% <https:\/\/blogs.mathworks.com\/developer\/category\/continuous-integration\/?s_tid=Blog_developer_Category\r\n% these other posts> to get you going. If you haven't read them yet go from\r\n% the bottom up on that category page.\r\n%\r\n% Anyway, let's continue with Jenkins and show how the diagnostics currently\r\n% show up with these diagraph tests. Here is the script I am asking MATLAB\r\n% to run in the Jenkins project:\r\n%\r\n% <include>runALL_THE_TESTS.m<\/include>\r\n% \r\n% Does it pass? Well when we run this job on the digraph submission in\r\n% Jenkins here is what we get:\r\n%\r\n% <<y2016_ExtendedView_OrigFormat.png>>\r\n%\r\n% Alright. Not bad but it looks like we have a failure. Do we know why it\r\n% failed? Not yet. For that, we need to drill into the *\"TAP Test Results\"*\r\n% instead of the *\"Extended TAP Test Results\"* of the Jenkins TAP Plugin.\r\n%\r\n% <<y2016_NormalView_OrigFormat.png>>\r\n%\r\n% Here, we can finally dig into the failing test by clicking on it and\r\n% getting to this page, which shows the diagnostics:\r\n%\r\n% <<y2016_OriginalDiagnosticView.png>>\r\n%\r\n% Whew. Alright it took us a couple clicks, but we made it. We can see\r\n% pretty quickly that that test is validating against an incorrect error\r\n% message id. Looking at the two ids, you can take a pretty good guess that\r\n% this is probably not actually a real problem in the software, but may\r\n% simply require a trivial test update since perhaps the id has changed\r\n% across versions of MATLAB. No problem. Quick to find, quick to fix.\r\n%\r\n% However, I think we can improve on how we got here. For one, there were\r\n% just too many clicks needed. Also, there seems to be some whitespace\r\n% formatting lost when the Jenkins plugin displayed the diagnostic values.\r\n% In this case it may have just been easier to look at the tap file output\r\n% directly:\r\n%\r\n% <include>testResults.tap<\/include>\r\n% \r\n% Well with R2016b there's an even better way. Did you ever wonder why the\r\n% MATLAB TAPPlugin is created using the a call like the following?\r\n%\r\nimport matlab.unittest.plugins.TAPPlugin;\r\nplugin = TAPPlugin.producingOriginalFormat\r\n\r\n%%\r\n% What is the deal with the original format? What other formats are there?\r\n% Well, quick history lession, the <http:\/\/testanything.org\/ TAP format>\r\n% was developed over a number of years by the Perl community, but the\r\n% formal specification really began at what could be called version 12 (and\r\n% what we have termed the original format since this version was the first\r\n% with <http:\/\/testanything.org\/tap-specification.html a documented\r\n% specification>). Since then, there has also arisen a\r\n% <http:\/\/testanything.org\/tap-version-13-specification.html version 13\r\n% format>. Actually there is a group of people involved in the discussions\r\n% who are discussing a version 14 as well but there has been no formal\r\n% specification of that format yet. If you are interested, and if you want\r\n% to join me in ensuring that any such format takes into account the needs\r\n% of the MATLAB community, certainly do get involved. There is a\r\n% <https:\/\/github.com\/TestAnything\/Specification github project> and a\r\n% <https:\/\/testanything.slack.com\/ slack channel> discussing the format\r\n% that you can take part in.\r\n%\r\n% Anyway, the news is that R2016b includes the option to produce the\r\n% version 13 TAP format! \r\nplugin = TAPPlugin.producingVersion13\r\n\r\n%%\r\n% The largest takeaway in this format is the fact\r\n% that diagnostics can be included in YAML(ish) blocks in the tap stream.\r\n% You may or may not be aware, but:\r\n%\r\n% *Y* AML \r\n%\r\n% *A* in't\r\n%\r\n% *M* arkup\r\n%\r\n% *L* anguage\r\n%\r\n% We all know how programmers love recursive acronyms (e.g,\r\n% <https:\/\/en.wikipedia.org\/wiki\/GNU GNU>,\r\n% <https:\/\/en.wikipedia.org\/wiki\/Microsoft_XNA XNA>). What does this mean\r\n% for us? A better diagnostics experience. Let's see this same test failure\r\n% in our Jenkins job but instead using version 13 of the TAP protocol.\r\n%\r\n% <include>runALL_THE_TESTS_YAML.m<\/include>\r\n%\r\n% Using this produces the following TAP Stream\r\n%\r\n% <include>testResultsYAML.tap<\/include>\r\n%\r\n% Very nice, we are in business with roughly the same failure diagnostics\r\n% as the original format. However, the big win is that now that the\r\n% diagnostics are in a structured format, other tools (like Jenkins) can\r\n% represent them with much more flavor. This is now what the *\"TAP Extended\r\n% Test Results\"* pages looks like in Jenkins.:\r\n%\r\n% <<y2016_ExtendedView_ExtendedFormat.png>>\r\n%\r\n% Now we can see all of the failure diagnostics on a single test results\r\n% page with much more clarity and structure. Pretty sweet.\r\n%\r\n% Do you see yourself benefitting from the more structured diagnostics that\r\n% we get with version 13 of the TAP format? Do you have any stories to tell\r\n% where good diagnostics saved you a bunch of debugging time? Do tell!\r\n\r\n##### SOURCE END ##### a52b02c6bcc94d859735199955c532e0\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2016_ExtendedView_ExtendedFormat.png\" onError=\"this.style.display ='none';\" \/><\/div><p>\r\nDiagnostics. They are the secret sauce of an effective test framework and we certainly take our job seriously at providing diagnostics that are not a little too hot or a little too cold, but... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/developer\/2016\/09\/29\/tap-with-yaml\/\">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\/739"}],"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=739"}],"version-history":[{"count":5,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/739\/revisions"}],"predecessor-version":[{"id":748,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/739\/revisions\/748"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/media?parent=739"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/categories?post=739"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/tags?post=739"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}