{"id":2792,"date":"2022-04-12T04:31:04","date_gmt":"2022-04-12T08:31:04","guid":{"rendered":"https:\/\/blogs.mathworks.com\/developer\/?p=2792"},"modified":"2022-04-12T04:31:04","modified_gmt":"2022-04-12T08:31:04","slug":"always-start-with-a-failing-test","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/developer\/2022\/04\/12\/always-start-with-a-failing-test\/","title":{"rendered":"Failure is the first step to trying"},"content":{"rendered":"<div class=\"content\"><!--introduction--><p>The official guidance on test-driven development is to follow the <a href=\"https:\/\/blog.cleancoder.com\/uncle-bob\/2014\/12\/17\/TheCyclesOfTDD.html\" target=\"_blank\">red-green-refactor<\/a> cycle:<\/p><!--\/introduction--><div><ol><li>Write a test that fails.<\/li><li>Make it pass.<\/li><li>Refactor.<\/li><\/ol><\/div><p>But what&#8217;s the point in starting with a test that fails? To make sure you&#8217;ve written the right test! I encountered some unexpected behaviour recently that highlighted this point.<\/p><p>Imagine you have a <tt>Library<\/tt> that aggregates <tt>Items<\/tt>. An <tt>Item<\/tt> can be either a <tt>Book<\/tt> or a <tt>Film<\/tt>, but not both at the same time. If we create a <tt>Library<\/tt> in \"book mode\", it should initially contain an empty <tt>Book<\/tt>. If we create it in \"film mode\", it should initially contain an empty <tt>Film<\/tt>. Let&#8217;s start by writing a test to capture the book mode behaviour:<\/p><pre class=\"language-matlab\">\n<span class=\"keyword\">classdef<\/span> tLibrary &lt; matlab.unittest.TestCase\n\n    <span class=\"keyword\">methods<\/span>(Test)\n\n        <span class=\"keyword\">function<\/span> bookModeInitialisesToEmptyBook(testCase)\n            \n            lib = Library(Mode=<span class=\"string\">\"book\"<\/span>);\n            \n            testCase.verifyEqual(lib.Items,Book.empty(1,0))\n            \n        <span class=\"keyword\">end<\/span>\n        \n    <span class=\"keyword\">end<\/span>\n\n<span class=\"keyword\">end<\/span>\n<\/pre><p>(The <tt>Name=value<\/tt> syntax for name-value pairs was <a href=\"https:\/\/uk.mathworks.com\/help\/matlab\/release-notes.html?category=language-programming&amp;rntext=&amp;startrelease=R2021a&amp;endrelease=R2021a&amp;groupby=release&amp;sortby=descending&amp;searchHighlight=\">introduced in R2021a<\/a>. It&#8217;s interchangeable with the classic <tt>(&#8230;,\"Name\",value)<\/tt> syntax.)<\/p><p>Let&#8217;s run the test. We expect it to fail because <tt>Library<\/tt> doesn&#8217;t exist.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2022_bookTestFail.png\" alt=\"\"> <\/p><p>We&#8217;ll skip over the steps of creating a blank class definition, the subsequent test failures due to a missing constructor with input arguments and a public <tt>Items<\/tt> property, and iteratively adding them in.<\/p><p>Instead, let's jump to the implementation of <tt>Library<\/tt> that makes our test pass:<\/p><pre class=\"language-matlab\">\n<span class=\"keyword\">classdef<\/span> Library\n    \n    <span class=\"keyword\">properties<\/span>\n        Items (1,:) Item = Book.empty\n    <span class=\"keyword\">end<\/span>\n    \n    <span class=\"keyword\">methods<\/span>\n        \n        <span class=\"keyword\">function<\/span> lib = Library(nvp)\n            \n            <span class=\"keyword\">arguments<\/span>\n                nvp.Mode (1,1) string {mustBeMember(nvp.Mode,[\"book\" \"film\"])} = <span class=\"string\">\"book\"<\/span>\n            <span class=\"keyword\">end<\/span>\n            \n        <span class=\"keyword\">end<\/span>\n        \n    <span class=\"keyword\">end<\/span>\n    \n<span class=\"keyword\">end<\/span>\n<\/pre><p>We run the test and see that it passes:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2022_bookTestPass.png\" alt=\"\"> <\/p><p>So far, so good. Now we write a test to capture film mode:<\/p><pre class=\"language-matlab\">\n<span class=\"keyword\">function<\/span> filmModeInitialisesToEmptyFilm(testCase)\n\n    lib = Library(Mode=<span class=\"string\">\"film\"<\/span>);\n\n    testCase.verifyEqual(lib.Items,Film.empty(1,0))\n\n<span class=\"keyword\">end<\/span>\n<\/pre><p>We run the test:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2022_filmTestPass.png\" alt=\"\"> <\/p><p>And&#8230; it passes!?<\/p><p>Why is it passing? We can use the debugger to inspect <tt>lib.Items<\/tt> manually and see that it&#8217;s an empty <tt>Book<\/tt> and not an empty <tt>Film<\/tt>. After some investigation, we find that <tt>verifyEqual<\/tt> relies on <tt>isequal<\/tt> and <tt>isequal<\/tt> considers two empties of different classes to be equal under some circumstances.<\/p><p>Whether or not this behaviour of <tt>isequal<\/tt> is correct, the important point for us is that we&#8217;ve written the wrong test! Our implementation could have been wrong and we wouldn&#8217;t have known. We would have achieved full <a href=\"https:\/\/uk.mathworks.com\/help\/matlab\/matlab_prog\/generate-code-coverage-report-in-html-format.html\">coverage<\/a> but our test would not have been contributing useful information.<\/p><p>We therefore need to rewrite our test to catch this issue:<\/p><pre class=\"language-matlab\">\n<span class=\"keyword\">function<\/span> filmModeInitialisesToEmptyFilm(testCase)\n\n    lib = Library(Mode=<span class=\"string\">\"film\"<\/span>);\n\n    testCase.verifyEmpty(lib.Items)\n    testCase.verifyClass(lib.Items,?Film)\n\n<span class=\"keyword\">end<\/span>\n<\/pre><p>Let&#8217;s run the updated test:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2022_filmTestFail.png\" alt=\"\"> <\/p><p>The test now fails and we can continue with our implementation, confident that our test will only pass when our implementation is correct.<\/p><script language=\"JavaScript\"> <!-- \n    function grabCode_c3f48b44881649dea40eb62153761b49() {\n        \/\/ Remember the title so we can use it in the new page\n        title = document.title;\n\n        \/\/ Break up these strings so that their presence\n        \/\/ in the Javascript doesn't mess up the search for\n        \/\/ the MATLAB code.\n        t1='c3f48b44881649dea40eb62153761b49 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\n        t2='##### ' + 'SOURCE END' + ' #####' + ' c3f48b44881649dea40eb62153761b49';\n    \n        b=document.getElementsByTagName('body')[0];\n        i1=b.innerHTML.indexOf(t1)+t1.length;\n        i2=b.innerHTML.indexOf(t2);\n \n        code_string = b.innerHTML.substring(i1, i2);\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\n\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \n        \/\/ in the XML parser.\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\n        \/\/ doesn't go ahead and substitute the less-than character. \n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\n\n        copyright = 'Copyright 2022 The MathWorks, Inc.';\n\n        w = window.open();\n        d = w.document;\n        d.write('<pre>\\n');\n        d.write(code_string);\n\n        \/\/ Add copyright line at the bottom if specified.\n        if (copyright.length > 0) {\n            d.writeln('');\n            d.writeln('%%');\n            if (copyright.length > 0) {\n                d.writeln('% _' + copyright + '_');\n            }\n        }\n\n        d.write('<\/pre>\\n');\n\n        d.title = title + ' (MATLAB code)';\n        d.close();\n    }   \n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_c3f48b44881649dea40eb62153761b49()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\n      Published with MATLAB&reg; R2022a<br><\/p><\/div><!--\nc3f48b44881649dea40eb62153761b49 ##### SOURCE BEGIN #####\n%% Failure is the first step to trying\n% The official guidance on test-driven development is to follow the <https:\/\/blog.cleancoder.com\/uncle-bob\/2014\/12\/17\/TheCyclesOfTDD.html \n% red-green-refactor> cycle:\n%% \n% # Write a test that fails.\n% # Make it pass.\n% # Refactor.\n%% \n% But what\u2019s the point in starting with a test that fails? To make sure you\u2019ve \n% written the right test! I encountered some unexpected behaviour recently that \n% highlighted this point.\n% \n% Imagine you have a |Library| that aggregates |Items|. An |Item| can be either \n% a |Book| or a |Film|, but not both at the same time. If we create a |Library| \n% in \"book mode\", it should initial contain an empty |Book|. If we create it in \n% \"film mode\", it should initially contain an empty |Film|. Let\u2019s start by writing \n% a test to capture the book mode behaviour:\n%% \n% <include>tLibrary_start.m<\/include>\n%%\n% (The |Name=value| syntax for name-value pairs was <https:\/\/uk.mathworks.com\/help\/matlab\/release-notes.html?category=language-programming&rntext=&startrelease=R2021a&endrelease=R2021a&groupby=release&sortby=descending&searchHighlight= \n% introduced in R2021a>. It\u2019s interchangeable with the classic |(\u2026,\"Name\",value)| \n% syntax.)\n% \n% Let\u2019s run the test. We expect it to fail because |Library| doesn\u2019t exist.\n% \n% <<y2022_bookTestFail.png>>\n% \n% We\u2019ll skip over the steps of creating a blank class definition, the subsequent \n% test failures due to a missing constructor with input arguments and a public \n% |Items| property, and iteratively adding them in. \n% \n% Instead, let's jump to the implementation of |Library| that makes our test \n% pass:\n%% \n% <include>Library.m<\/include>\n%%\n% We run the test and see that it passes:\n% \n% <<y2022_bookTestPass.png>>\n% \n% So far, so good. Now we write a test to capture film mode:\n%% \n% <include>tLibrary_film_start.m<\/include>\n%%\n% We run the test:\n% \n% <<y2022_filmTestPass.png>>\n% \n% And\u2026 it passes!?\n% \n% Why is it passing? We can use the debugger to inspect |lib.Items| manually \n% and see that it\u2019s an empty |Book| and not an empty |Film|. After some investigation, \n% we find that |verifyEqual| relies on |isequal| and |isequal| considers two empties \n% of different classes to be equal under some circumstances.<about:blank<#_msocom_4> \n% > \n% \n% Whether or not this behaviour of |isequal| is correct, the important point \n% for us is that we\u2019ve written the wrong test! Our implementation could have been \n% wrong and we wouldn\u2019t have known. We would have achieved full <https:\/\/uk.mathworks.com\/help\/matlab\/matlab_prog\/generate-code-coverage-report-in-html-format.html \n% coverage> but our test would not have been contributing useful information.\n% \n% We therefore need to rewrite our test to catch this issue:\n%% \n% <include>tLibrary_film_finish.m<\/include>\n%%\n% Let\u2019s run the updated test:\n% \n% <<y2022_filmTestFail.png>>\n% \n% The test now fails and we can continue with our implementation, confident \n% that our test will only pass when our implementation is correct.\n##### SOURCE END ##### c3f48b44881649dea40eb62153761b49\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img src=\"https:\/\/blogs.mathworks.com\/developer\/files\/y2022_filmTestFail.png\" class=\"img-responsive attachment-post-thumbnail size-post-thumbnail wp-post-image\" alt=\"\" decoding=\"async\" loading=\"lazy\" \/><\/div><!--introduction--><p>The official guidance on test-driven development is to follow the <a href=\"https:\/\/blog.cleancoder.com\/uncle-bob\/2014\/12\/17\/TheCyclesOfTDD.html\" target=\"_blank\">red-green-refactor<\/a> cycle:... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/developer\/2022\/04\/12\/always-start-with-a-failing-test\/\">read more >><\/a><\/p>","protected":false},"author":178,"featured_media":2801,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[7],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/2792"}],"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\/178"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/comments?post=2792"}],"version-history":[{"count":6,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/2792\/revisions"}],"predecessor-version":[{"id":2822,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/2792\/revisions\/2822"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/media\/2801"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/media?parent=2792"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/categories?post=2792"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/tags?post=2792"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}