    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Testing Times (Part 2)</title>
        <link>https://members.accu.org/index.php/articles/2480</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Process Topics + CVu Journal Vol 30, #1 - March 2018</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c221/">Process</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c383/">301</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c221-383/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c221+383/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Testing Times (Part 2)</h1>
<p><strong>Author:</strong>&nbsp;Bob Schmidt</p>
<p>
<strong>Date:</strong> 08 March 2018 17:14:48 +00:00 or Thu, 08 March 2018 17:14:48 +00:00</p>
<p><strong>Summary:</strong>&nbsp;Pete Goodliffe continues the journey into software testing.</p>
<p><strong>Body:</strong>&nbsp;<p class="quote">If you donâ€™t care about quality, you can meet any other requirement.<br />~ Gerald M. Weinberg</p>

<p>In the previous column, we started a journey into the world of software testing; we considered why itâ€™s important, why it should be automated, and who should be doing this. We looked at the types of test we perform, when we <em>write</em> them, and when we <em>run</em> them.</p>

<p>So, letâ€™s round this off by looking at what should be tested, and what good tests look like.</p>

<h2>What to test</h2>

<p>Test whatever is important in your application. What are your requirements?</p>

<p>Your tests must, naturally, test that each code unit behaves as required, returning accurate results. However, if performance is an important requirement for your application, then you should have tests in place to monitor the codeâ€™s performance. If your server must answer queries within a certain time frame, include tests for this condition.</p>

<p>You may want to consider the <em>coverage</em> of your production code that the test cases execute. You can run tools to determine this. However, this tends to be an awful metric to chase after. It can be a huge distraction to write test code that tries to laboriously cover every production line; itâ€™s more important to focus on the most important behaviours and system characteristics.</p>

<h2>Good tests</h2>

<p>Writing good tests requires practice and experience; it is perfectly possible to write bad tests. Donâ€™t be overly worried about this at first â€“ itâ€™s most important to actually <em>start</em> writing tests than to be paralysed by fear that your tests are rubbish. Start writing tests and youâ€™ll start to learn.</p>

<p>Bad tests become baggage: a liability rather than an asset. They can slow down code development if they take ages to run. They can make code modification difficult if a simple code change breaks many hard-to-read tests.</p>

<p>The longer your tests take to run, the less frequently youâ€™ll run them, the less youâ€™ll use them, the less feedback youâ€™ll get from them. The less value they provide.</p>

<p>I once inherited a codebase that had a large suite of unit tests; this seemed a great sign. Sadly, those tests were effectively worse <em>legacy code</em> than the production code. Any code modification we made caused several test failures in hundreds-of-lines-long test methods that were intractable, dense, and hard to understand. Thankfully, this is not a common experience.</p>

<p class="lesson">Bad tests can be a liability. They can impede effective development.</p>

<p>These are the characteristics of a good test:</p>

<ul>
	<li>Short, clear name, so when it fails you can easily determine what the problem is (e.g., <em>new list is empty</em>)</li>
	
	<li>Maintainable: it is easy to write, easy to read, and easy to modify</li>
	
	<li>Runs quickly</li>
	
	<li>Up-to-date</li>
	
	<li>Runs without any prior machine configuration (e.g., you donâ€™t have to prepare your filesystem paths or configure a database before running it)</li>
	
	<li>Does not depend on any other tests that have run before or after it; there is no reliance on external state, or on any shared variables in the code</li>
	
	<li>Tests the <em>actual</em> production code (Iâ€™ve seen â€˜unit testsâ€™ that worked on a <em>copy</em> of the production code â€“ a copy that was out of date. Not useful. Iâ€™ve also seen special â€˜testingâ€™ behaviour added to the SUT in test builds; this, too, is not a test of the real production code.)</li>
</ul>

<p>These are some common descriptions of badly constructed tests:</p>

<ul>
	<li>Tests that sometimes run, sometimes fail (often this is caused by the use of threads, or racy code that relies on specific timing, by reliance on external dependencies, the order of tests being run in the test suite, or on shared state)</li>
	
	<li>Tests that look awful and are hard to read or modify</li>
	
	<li>Tests that are too large (large tests are hard to understand, and the SUT clearly isnâ€™t very isolatable if it takes hundreds of lines to set up)</li>
	
	<li>Tests that exercise more than one thing in a single test case (a â€˜test caseâ€™ is a <em>singular</em> thing)</li>
	
	<li>Tests that attack a class API function by function, rather than addressing individual behaviours</li>
	
	<li>Tests for third-party code that you didnâ€™t write (there is no need to do that unless you have a good reason to distrust it)</li>
	
	<li>Tests that donâ€™t actually cover the main functionality or behaviour of a class, but that hide this behind a raft of tests for less important things (if you can do this, your class is probably too large)</li>
	
	<li>Tests that cover pointless things in excruciating detail (e.g., property getters and setters)</li>
	
	<li>Tests that rely on â€˜white-boxâ€™ knowledge of the internal implementation details of the SUT (this means you canâ€™t change the implementation without changing all the tests)</li>
	
	<li>Tests that work on only one machine</li>
</ul>

<p>Sometimes a bad test smell indicates not (only) a bad test, but also bad code under test. These smells should be observed, and used to drive the design of your code.</p>

<h2>What does a test look like?</h2>

<p>The test framework you use will determine the shape of your test code. It may provide a structured set-up, and tear-down facility, and a way to group individual tests into larger <em>fixtures</em>.</p>

<p>Conventionally, in each test there will be some preparation, you then perform an operation, and finally validate the result of that operation. This is commonly known as the <em>arrange-act-assert</em> pattern. For unit tests, at the assert stage we typically aim for a single check â€“ if you need to write multiple assertions then your test may not be performing a single test case.</p>

<p>Listing 1 is an example Java unit test method that follows this pattern, and the key stages are:</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
@Test
public void stringsCanBeCapitalised()
{
  String input = &quot;This string should be uppercase.&quot;; &lt;1&gt;
  String expected = &quot;THIS STRING SHOULD BE UPPERCASE.&quot;;

  String result = input.toUpperCase();               &lt;2&gt;

  assertEquals(result, expected);                    &lt;3&gt;
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<ul>
	<li><code>&lt;1&gt;</code> Arrange: we prepare the input</li>
	<li><code>&lt;2&gt;</code> Act: we perform the operation</li>
	<li><code>&lt;3&gt;</code> Assert: we validate the results of that operation</li>
</ul>

<p>Maintaining this pattern helps keep tests focused and readable.</p>

<p>Of course, this test alone does not cover all of the potential ways to use and abuse <code>String</code> capitalisation. We need more tests to cover other inputs and expectations. Each test should be added as a new test method, not placed into this one.</p>

<h3>Test names</h3>

<p>Focused tests have very clear names that read as simple sentences. If you canâ€™t easily name a test case, then your requirement is probably ambiguous, or you are attempting to test multiple things. </p>

<p>The fact that the test method <em>is</em> a test is usually implicit (because of an attribute like the <code>@Test</code> we saw earlier), so you neednâ€™t add the word <code>test</code> to the name. The preceding example need not be called <code>testThatStringsCanBeCapitalised</code>.</p>

<p>Imagine that your tests are read as specifications for your code; each test name is a statement about what the SUT does, a single fact. Avoid ambiguous words like â€˜shouldâ€™, or words that donâ€™t add value like â€˜mustâ€™. Just as when we create names in our production code, avoid redundancy and unnecessary length.</p>

<p>Test names need not follow the same style conventions as production code; they effectively form their own domain-specific language. Itâ€™s common to see much longer method names and the liberal use of underscores, even in languages like C# and Java where they are not idiomatic (the argument being <code>strings_can_be_capitalised</code> requires less squinting to read).</p>

<h2>The structure of tests</h2>

<p>Ensure that your test suite covers the important functionality of your code. Consider the â€˜normalâ€™ input cases. Consider also the common â€˜failure casesâ€™. Consider what happens at boundary values, including the empty or zero state. Itâ€™s a laudable goal to aim to cover all requirements and all the functionality of your entire system with system and integration tests, and cover all code with unit tests. However, that can require some serious effort.</p>

<p>Do not duplicate tests: it adds effort, confusion, and maintenance cost. Each test case you write verifies one fact; that fact does not need to be verified again, either in a second test, or as part of the test for something else. If your first test case checks a precondition after constructing an object, then you can assume that this precondition holds in every other test case you write â€“ there is no need to reproduce the check every time you construct an object.</p>

<p>A common mistake is to see a class with five methods, and think that you need five tests, one to exercise each method. This is an understandable (but naÃ¯ve) approach. Function-based tests are rarely useful, as you cannot generally test a single method in isolation. After calling it, youâ€™ll need to use other methods to inspect the objectâ€™s state.</p>

<p>Instead, write tests that go through the specific behaviours of the code. This leads to a far more cohesive and clear set of tests.</p>

<h3>Maintain the tests</h3>

<p>Your test code is as important as the production code, so consider its shape and structure. If things get messy, clean it, and refactor it.</p>

<p>If you change the behaviour of a class so its tests fail, donâ€™t just comment out the tests and run away. Maintain the tests. It can be tempting to â€˜save timeâ€™ near deadlines by skipping test cleanliness. But rushed carelessness here <em>will</em> come back to bite you.</p>

<p>On one project, I received an email from a colleague: <em>I was working on your XYZ class, and the unit tests stopped working, so I had to remove them all</em>. I was rather surprised by this, and looked at what tests had been removed. Sadly, these were important test cases that were clearly pointing out a fundamental problem with the new code. So I restored the test code and â€˜fixedâ€™ the bug by backing out the change. We then worked together to craft a new test case for the required functionality, and then reimplemented a version that satisfied the old tests and the new.</p>

<p class="lesson">Maintain your test suite, and listen to it when it talks to you.</p>

<h3>Picking a test framework</h3>

<p>The unit or integration test framework you use shapes your tests, dictating the style of assertions and checks you can use, and the structure of your test code (e.g., are the test cases written in free functions, or as methods within a test fixture class?).</p>

<p>So itâ€™s important to pick a good unit test framework. It doesnâ€™t need to be complex or heavyweight. Indeed, itâ€™s preferable to not choose an unwieldy tool. Remember, you can get very, very far with the humble <code>assert</code>. I often start testing new prototype code with just a <code>main</code> method and a series of <code>assert</code>s.</p>

<p>Most test frameworks follow the â€˜xUnitâ€™ model which came from Kent Beckâ€™s original <em>Smalltalk SUnit</em>. This model was ported and popularised with JUnit (for Java) although there are broadly equivalent implementations in most every languageâ€”for example, <em>NUnit</em> (C#) and <em>CppUnit</em> (C++). This kind of framework is not always ideal; xUnit style testing leads to non-idiomatic code in some languages (in C++, for example, itâ€™s rather clumsy and anachronistic; other test frameworks can work betterâ€”check out <em>Catch</em> as a great alternative <a href="#[1]">[1]</a>).</p>

<p>Some frameworks provide pretty GUIs with red and green bars to clearly indicate success or failure. That might make you happy, but Iâ€™m not a big fan. I think you shouldnâ€™t need a separate UI or a different execution step for development tests. They should ideally be baked right into your build system. The feedback should be reported instantly like any other code error.</p>

<p>System tests tend to use a different form of framework, where we see the use of tools like Fit <a href="#[2]">[2]</a> and Cucumber <a href="#[3]">[3]</a>. These tools attempt to define tests in a more humane, less programmatic manner, allowing non-programmers to participate in the test/specification-wring process.</p>

<h2>No code is an island</h2>

<p>When writing unit tests, we aim to place truly <em>isolated</em> units of code into the â€˜system under testâ€™. These units can be instantiated without the rest of the system being present.</p>

<p>A unitâ€™s interaction with the outside world is expressed through two contracts: the interface it provides, and the interfaces it expects. The unit must not depend on anything else â€“ specifically not on any shared global state or singleton objects.</p>

<p class="lesson">Global variables and singleton objects are anathema to reliable testing. You canâ€™t easily test a unit with hidden dependencies.</p>

<p>The interface that a unit of code <em>provides</em> is simply the methods, functions, events, and properties in its API. Perhaps it also provides some kind of callback interface.</p>

<p>The interfaces it <em>expects</em> are determined by the objects it collaborates with through its API. These are the parameter types in its public methods or any messages it subscribes to. For example, an <code>Invoice</code> class that requires a <code>Date</code> parameter relies on the dateâ€™s interface.</p>

<p>The objects that a class collaborates with should be passed in as constructor parameters, a practice known as <em>parameterise from above</em>. This allows your class to eschew hard-wired internal dependencies on other code, instead having the link configured by its owner. If the collaborators are described by an <em>interface</em> rather than a concrete type, then we have a seam through which we can perform our tests; we have the ability to provide alternative test implementations. </p>

<p>This is an example of how tests tend to lead to better factored code. It forces your code to have fewer hardwired connections and internal assumptions. Itâ€™s also good practice to rely on a minimal interface that describes a specific collaboration, rather than on an entire class that may provide much more than the simple interface required.</p>

<p class="lesson">Factoring your code to make it â€˜testableâ€™ leads to better code design.</p>

<p>When you test an object that relies on an external interface, you can provide a â€˜dummyâ€™ version of that interface in the test case. Terms vary in testing circles, but often these are called <em>test doubles</em>. There are various forms of doubles, but we most commonly use:</p>

<ul>
	<li>Dummies
		<p>Dummy objects are usually empty husks â€“ the test will not invoke them, but they exist to satisfy parameter lists.</p></li>
		
	<li>Stubs
		<p>Stub objects are simplistic implementations of an interface, usually returning a canned answer, perhaps also recording information about the calls into it.</p></li>
	
	<li>Mocks
		<p>Mock objects are the kings of test double land, a facility provided by a number of different mocking libraries. A mock object can be created automatically from a named interface, and then told up-front about how the SUT will use it. A SUT test operation is performed, and then you can inspect the mock object to verify the behaviour was as expected.</p>
		
		<p>Different languages have different support for mocking frameworks. Itâ€™s easiest to synthesize mocks in languages with reflection.</p>
		
		<p>Sensible use of mock objects can make tests simpler and clearer. But, of course, you can have too much of a good thing. Tests that are encumbered by complex use of many mock objects can become very tricky to reason about, and hard to maintain. <em>Mock mania</em> is another common smell of bad test code, and may highlight that the structure of the SUT is not correct.</p></li>
</ul>

<h2>Conclusion</h2>

<p>Tests help us to write our code. They help us to write <em>good</em> code. They help maintain the <em>quality</em> of our code. They can <em>drive</em> the code design, and serve to document how to use it. But tests donâ€™t solve all problems with software development. Edsger Dijkstra said: <em>Program testing can be used to show the presence of bugs, but never to show their absence.</em></p>

<p>No test is perfect, but the existence of tests serves to increase confidence in the code you write, and in the code you maintain. The effort you put into developer testing is a trade-off; how much effort do you want to invest in writing tests to gain confidence? Remember that your test suite is only as good as the tests you have in it. It is perfectly possible to miss an important case; you can deploy into production and still let a problem slip through. For this reason, test code should be reviewed as carefully as production code.</p>

<p>Nonetheless, the punchline is simple: if code is important enough to be written, it is important enough to be tested. So write development tests for your production code. Use them to <em>drive</em> the design of your code. Write the tests <em>as</em> you write the production code. And automate the running of those tests.</p>

<p>Shorten the feedback loop.</p>

<p>Testing is fundamental and important. This chapter can only really scratch the surface, encourage you to test, and prompt you to find out more about good testing techniques.</p>

<h2>Questions</h2>

<ul>
	<li>How can you best introduce test-driven development into a codebase that has never received automated testing? What kind of problems would you encounter?</li>
	
	<li>Investigate <em>behaviour-driven development</em>. How does it differ from â€˜traditionalâ€™ TDD? What problems does it solve? Does it complement or replace TDD? Is this a direction you should move your testing in?</li>
	
	<li>If you donâ€™t already, start to write unit tests for your code today. If you already use tests, pay attention to how they inform and drive your code design.</li>
</ul>

<h2>References</h2>

<p class="bibliomixed"><a id="[1]"></a>[1]	The Catch unit test framework (available from <a href="http://github.com/philsquared/Catch">http://github.com/philsquared/Catch</a>).</p>

<p class="bibliomixed"><a id="[2]"></a>[2]	Fit: <a href="http://fit.c2.com/">http://fit.c2.com/</a></p>

<p class="bibliomixed"><a id="[3]"></a>[3]	Cucumber: <a href="http://cukes.info">http://cukes.info</a></p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
