<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>I.M. Testy &#187; Code Coverage</title>
	<atom:link href="http://www.testingmentor.com/imtesty/tag/code-coverage/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.testingmentor.com/imtesty</link>
	<description>Treatises on the practice of software testing</description>
	<lastBuildDate>Thu, 01 Jul 2010 17:10:28 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Code Coverage: More Than Just a Number</title>
		<link>http://www.testingmentor.com/imtesty/2010/01/21/code-coverage-more-than-just-a-number/</link>
		<comments>http://www.testingmentor.com/imtesty/2010/01/21/code-coverage-more-than-just-a-number/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 02:09:22 +0000</pubDate>
		<dc:creator>Bj Rollison</dc:creator>
				<category><![CDATA[General Testing Topics]]></category>
		<category><![CDATA[Testing Practices]]></category>
		<category><![CDATA[Code Coverage]]></category>
		<category><![CDATA[Metrics & Measures]]></category>

		<guid isPermaLink="false">http://www.testingmentor.com/imtesty/2010/01/21/code-coverage-more-than-just-a-number/</guid>
		<description><![CDATA[When I was growing up I would sometimes go down into my grandfather’s basement. He had amassed a variety of tools during his lifetime and he was an excellent wood craftsman. I wasn’t allowed to touch any of the power tools, because his rule was, “if you don’t know how to use a tool properly [...]]]></description>
			<content:encoded><![CDATA[<p>When I was growing up I would sometimes go down into my grandfather’s basement. He had amassed a variety of tools during his lifetime and he was an excellent wood craftsman. I wasn’t allowed to touch any of the power tools, because his rule was, “<strong><em>if you don’t know how to use a tool properly then you shouldn’t play with it</em></strong>.”</p>
<p>Of course, I am a bit of a hard head (even back then) and one day I started playing with the wood lathe while my grandfather was upstairs. Everything seemed to be going pretty well until I pushed the chisel in too far too fast and the wood split and went flying. One piece shattered the overhead light and the other piece ricocheted off the back of my hand leaving an nice gash. I shut off the machine and ran upstairs. After my grandmother cleaned and wrapped my hand, my grandfather made me go back downstairs and clean up the mess and stood over me with a stern look of disapproval making sure I wiped up my blood trail. After that incident, I heeded my grandfather’s advice, at least in his basement shop.</p>
<p>Anyway, with the recent discussions of code coverage around the testing blogosphere I started thinking about what was really being discussed. The discussions (as is the case with most discussions about code coverage) were not actually about the application code coverage as a tool, but more about the code coverage metric. And more specifically the discussions were about how not to assume a high measure of code coverage implies something is well tested. Interestingly enough, 2 years ago I wrote a <a href="http://www.testingmentor.com/imtesty/2009/11/13/the-code-coverage-metric-is-inversely-proportional-to-the-criticality-of-the-information-it-provides/" target="_blank">post</a> illustrating how the metric can be gamed and how the code coverage measure tells us nothing about quality or test effectiveness, but also alluded to how it might be used more effectively.</p>
<p>I thought that how the metric is sometimes misused is mostly self-evident, but then I realized that almost every time testers start talking about code coverage the discussion tends to focus on the metric. This may seem a bit harsh, but if a person&#8217;s only contribution to a conversation about code coverage is about how the metric doesn’t relate to quality or testing effectiveness then that person should not be allowed to play with hammers, and employing more complex tools such a wheel-barrows are well beyond that person&#8217;s comprehension.</p>
<p>Only thinking of code coverage as a means to get some magic number is akin to thinking “how many nails can I pound with this hammer. The metric itself is mostly irrelevant; and it is completely irrelevant if you don’t know how to interpret it in a way that helps you as a tester. Think about it this way; if we told our managers “our tests achieved 80% code coverage” some of our managers would be elated. (Of course IMHO, these types of managers are metric morons.) But, what do you think these same pointy headed number zombies would say if we told them “we ran our tests and we only missed testing 20% of the code.” I suspect they would start pacing back and forth in the room mumbling “We must run more tests, we must run more tests.”</p>
<p>When we stop thinking of code coverage as a simply measure where our only use of the tool is to try and achieve some magical number then perhaps we can start thinking about how to actually use code coverage as an effective tool to help us design tests (in under-tested or untested areas of the code), reduce potential risk, and possibly even drive quality upstream.</p>
<p>For example, one of my mentees is currently working on a project that uses just in time code coverage as a tool to evaluate how tests exercise changed code and downstream dependencies prior to checking code changes (e.g. bug fixes) back into the main tree. The initial pushback by some members of the team (including some pointy headed managers) was “code coverage doesn’t tell us about product quality” or “its too hard to achieve 80% code coverage” (although no such goal had been mentioned), and my personal favorite, “it’s too difficult to get everyone to measure coverage.” I reminded my mentee that the project is not about achieving some magic number, and in fact, it’s really not even about measuring at all. It’s about using the tool to discover information and to help us design additional functional tests at the API or component level that we might otherwise overlook to help prevent downstream regressions. In a nutshell, its about using code coverage as a defect prevention tool in this case.</p>
<p>Bottom line, code coverage is a tool! If you don’t know how to use it to improve your testing, well…</p>
]]></content:encoded>
			<wfw:commentRss>http://www.testingmentor.com/imtesty/2010/01/21/code-coverage-more-than-just-a-number/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Refactoring for Testability</title>
		<link>http://www.testingmentor.com/imtesty/2009/12/02/refactoring-for-testability/</link>
		<comments>http://www.testingmentor.com/imtesty/2009/12/02/refactoring-for-testability/#comments</comments>
		<pubDate>Wed, 02 Dec 2009 20:35:24 +0000</pubDate>
		<dc:creator>Bj Rollison</dc:creator>
				<category><![CDATA[Testing Practices]]></category>
		<category><![CDATA[Code Coverage]]></category>
		<category><![CDATA[Testability]]></category>
		<category><![CDATA[White Box Testing]]></category>

		<guid isPermaLink="false">http://testingmentor.com/imtesty/2009/12/02/refactoring-for-testability/</guid>
		<description><![CDATA[ 

One of my hobbies is shooting CMP matches and long range precision shooting. Besides lots of practice perfecting the techniques a big part of precision shooting depends on the ammunition and studying the ballistic patterns of various loads. All precision shooters custom load their ammunition and it is not as simple as simply reading a [...]]]></description>
			<content:encoded><![CDATA[<p> </p>
<div class="mceTemp">
<div id="attachment_255" class="wp-caption alignleft" style="width: 209px"><img class="size-medium wp-image-255 " style="margin-left: 5px; margin-right: 5px;" title="DSC_1276" src="http://testingmentor.com/imtesty/wp-content/uploads/2009/12/DSC_1276-199x300.jpg" alt="Teaching my daughter about bullet seating depth." width="199" height="300" /><p class="wp-caption-text">Teaching my daughter about bullet seating depth.</p></div>
<p>One of my hobbies is shooting <a href="http://odcmp.com/">CMP matches</a> and long range precision shooting. Besides lots of practice perfecting the techniques a big part of precision shooting depends on the ammunition and studying the ballistic patterns of various loads. All precision shooters custom load their ammunition and it is not as simple as simply reading a reloading manual. Slight variations of .001” of an inch in seating depth of a bullet or .1 grain of powder may determine whether the group of shots at a target 600 yards away is 1” MOA or 6” MOA. So, getting the ammunition to match the rifle requires continually analyzing your shots, making slight adjustments to the load, and repeating; in computer jargon we might call that refactoring. Reloading for precision is a continually optimizing process until we find the optimal load. Similarly, one of the things we do in the Engineering Excellence group at Microsoft is to continually analyze our internal processes and practices to see how we can help our business groups constantly improve and optimize towards their target. One of the big things on our plate these days is testability.</div>
<p>In <a href="http://www.amazon.com/Testing-Object-Oriented-Systems-Models-Patterns/dp/0201809389%3FSubscriptionId%3D0JTCV5ZMHMF7ZYTXGFR2%26tag%3Dbrdicr-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0201809389">Testing Object-Oriented Systems: Models, Patterns, and Tools</a>, a book I consider one of the most important books on software testing practices, the author Robert Binder defines testability as “The relative ease or difficulty of producing and executing an economically feasible test suite to determine whether the [system under test ] SUT (i) conforms to stated requirements and specifications, and (ii) exhibits an acceptably low probability of failure.” This and several definitions of testability floating around on the web and all generally agree that testability generally involves</p>
<p>1.) The ease with which the SUT can be tested<br />
2.) The cost of testing is reasonable</p>
<p>So, as the testability increases the ease with which our tests can determine whether the SUT satisfies implicit and explicit requirements and has a lower chance of failure at reduced testing costs. This all sounds nice, but unfortunately testability cannot be directly measured; testability is a qualitative measure. Although we can’t accurately measure testability we can sometimes do small things to improve the characteristics of testability and help reduce testing costs by reducing the number of tests required to determine whether the SUT satisfies the stated requirements and also has a low chance of failure, or finding ways to test more efficiently through better designs.</p>
<p>In last week’s post I referred a pseudo code example that was written to illustrate how bugs could linger in code despite a high measure of code coverage. Of course we should realize that pseudo code is generally a far cry from the real implementation of the code. Pseudo code is simply a model, and there are many ways to implement that model. The advantage of a model is that we can often test a model earlier to identify potential issues before a single line of code is written. In this particular pseudo code sample, there were a couple of things that stood out that could likely impact the testability of an implementation of the pseudo code model. So, the neurons in my brain starting firing with lots of testing related questions.</p>
<p>So, let’s use that example to discuss potential testability issues. The sample was based on a requirement that stated “Student ID’ are seven digit numbers between one million and 6 million inclusive.” The function is relatively simple in that it takes a string type passed to the <em>sid</em> parameter, and returns a Boolean true or false to the calling function depending on whether the string satisfies the internal Boolean conditions it is being compared against. But this function also calls 2 other functions; the <em>length</em> () function, and the <em>number</em> () function. From the function names I would think the <em>length</em> () function provides a numeric value that represents the number of characters in the string passed to the <em>sid</em> parameter. I am also betting the <em>number</em> () function returns a numeric value (it converts the string variable to a numeric type such as an integer. The pseudo code example was</p>
<blockquote><p>function validate_studentid(string sid) return<br />
TRUEFALSE<br />
BEGIN<br />
  STATIC TRUEFALSE isOk;<br />
  isOk = true;</p>
<p>  if ((length(sid) is not 7) then<br />
    isOk = False;</p>
<p>  if (number(sid) &lt;= 1000000 or number(sid) &gt; 6000000 then<br />
     isOk = False;</p>
<p>  return isOk;</p>
<p>END</p></blockquote>
<p>One of the reasons that we hire testers with a programming background at Microsoft is that they can help the developer identify potential issues, reduce the probability of failure, and improve testability by stepping through the code during peer reviews, or while designing additional tests to cover un-tested or under-tested areas of the code that are exposed by code coverage analysis. So, when I come across a code sample, I generally step through it to</p>
<ul>
<li>See if it will work as intended (basic unit test)</li>
<li>See if there are any potential obvious errors in logic</li>
<li>Identify tests necessary for branch or conditional coverage (because developers are usually only concerned with block coverage)</li>
<li>Identify argument values for negative testing that might expose undesirable results (bugs)</li>
</ul>
<p>So, in this pseudo code example, once I got to the second conditional clause (if (number (sid)) &lt;= 1000000 or number (sid) &gt; 6000000 then) the little cranks in my brain began to turn. I thought to myself, why are we checking the length of the string? I mean, if the number can only be between 1,000,000 and 6,000,000 then it seems to me that checking the length of the string is simply redundant.</p>
<p>If we remove the first conditional clause (if ((length(sid) is not 7) then) then we actually reduce the number of tests to 3 instead of 4 assuming <a href="http://www.student.cs.uwaterloo.ca/~cs132/Weekly/W02/SCBooleans.html">short-circuiting</a> since short-circuiting compound Boolean expressions is one of several code optimization techniques. (By the way, the first caveat example in Wikipedia on short-circuiting where a function used as a Boolean conditional also “performs some required operation regardless of whether the first conditional evaluates true or false” is simply poor architectural design and is very, very likely to be problematic.) The 3 tests for condition (and basis path) coverage to exercise the true and false outcome of every single Boolean conditional expression are listed in the table below.</p>
<table border="1" cellspacing="0" cellpadding="2" width="681">
<tbody>
<tr>
<td width="173" valign="top"> </td>
<td width="196" valign="top">Conditional 1</td>
<td width="186" valign="top">Conditional 2</td>
<td width="124" valign="top"> </td>
</tr>
<tr>
<td width="172" valign="top">Test</td>
<td width="195" valign="top">number (sid) &lt;= 1000000</td>
<td width="186" valign="top">number (sid) &gt; 6000000</td>
<td width="126" valign="top">Expected Result</td>
</tr>
<tr>
<td width="172" valign="top">Any value between 1000000 and 6000000</td>
<td width="194" valign="top">false</td>
<td width="185" valign="top">false</td>
<td width="128" valign="top">true</td>
</tr>
<tr>
<td width="171" valign="top">Any value &gt; 6000000</td>
<td width="194" valign="top">false</td>
<td width="185" valign="top">true</td>
<td width="129" valign="top">false</td>
</tr>
<tr>
<td width="171" valign="top">Any value &lt; 1000000</td>
<td width="194" valign="top">true</td>
<td width="185" valign="top">(short-circuited)</td>
<td width="130" valign="top">false</td>
</tr>
</tbody>
</table>
<p>Of course, even testing several samples from the equivalent partitions may not expose the bug in this code because the bug in this code is a typical boundary error. (In a <a href="http://testingmentor.com/imtesty/2009/11/18/boundary-testing-isnt-guessing-at-numbers/">previous post</a> I explained the basic fault model that caused many boundary issues. In a nutshell, boundary bugs are generally caused by incorrect relational operators or <a href="http://en.wikipedia.org/wiki/Magic_number_(programming)">magic numbers</a> in code.) Without recognizing that we also need to test the boundaries (999999, 1000000, 1000001, and 5999999, 6000000, 6000001) also we could easily overlook the error in the pseudo code.</p>
<p>Another thing that caught my attention was the lack of exception handling. Some people may not consider including exception handling in pseudo code and take it as a given. But, as a tester when I don’t exception handling in pseudo code in a review then I need to start asking questions so I can better design tests to exercise the exception handling control flow paths that directly impact code coverage measures. Another reason this is an important consideration is because results of code coverage analysis indicates that exception handlers are generally under-tested. It seems we are really good at finding unhandled exceptions with our negative tests (which is really good), but we do not seem to be as thorough in testing the logical code paths of exception handlers. This is especially true for predicate statement with multiple Boolean sub-expressions might trigger an exception. We tend to test one of the conditionals, and the other conditionals expressions in that statement are often under-tested.</p>
<p>So, we can surmise the <em>number</em> () function must be converting the string parameter (the <em>sid</em> variable) to a numeric type and returning a type of number because the conditional clause is comparing it to magic numbers (1000000 and 6000000). But if we entered a string that contained non-numeric characters my initial thought was that the <em>number</em> () function would throw an exception that is unhandled by the <em>validate</em>_<em>studentID</em> () function.</p>
<p>Then I thought a bit more, and considered that the <em>number</em> () function might swallow the exception and return a 0 or even a -1. Now, there are some <a href="http://haacked.com/archive/2005/08/10/9293.aspx">arguments in favor of swallowing exceptions</a>, but in general it is not a good idea. In this case, it is probably a bad idea because one of the primary purposes of a separate function is reusability. If the <em>number</em> () is reused in some other code, or other part of the code where we need to convert a string to a numeric type regardless of the range (within the range of the data type being converted to), I would suspect we would want to throw an exception, and then rethrow the exception in the calling function. Of course, this is where the rubber hits the road, and a professional tester needs to dig in and start asking some hard questions as to how the developer is going to handle this situation. If the <em>number</em> () function is not going to be reused, then most modern programming languages include a function call that will easily convert the string to a numeric type and do it more efficiently as compared to calling a separate function. And may in that case we could swallow the exception in the <em>validate</em>_<em>studentID</em> () function and simply return false as illustrated in the C# code below.</p>
<div id="codeSnippetWrapper" style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; width: 97.5%; font-family: 'Courier New', courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; cursor: text; border: silver 1px solid; padding: 4px;">
<div id="codeSnippet" style="text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;">
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum1" style="color: #606060">   1:</span> <span style="color: #0000ff">try</span></pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum2" style="color: #606060">   2:</span> {</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum3" style="color: #606060">   3:</span>     <span style="color: #0000ff">if</span> (<span style="color: #0000ff">int</span>.Parse(sid) &lt; minValue || <span style="color: #0000ff">int</span>.Parse(sid) &gt; maxValue)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum4" style="color: #606060">   4:</span>     {</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum5" style="color: #606060">   5:</span>         isOk = <span style="color: #0000ff">false</span>;</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum6" style="color: #606060">   6:</span>     }</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum7" style="color: #606060">   7:</span> }</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum8" style="color: #606060">   8:</span> <span style="color: #0000ff">catch</span> (FormatException)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum9" style="color: #606060">   9:</span> {</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum10" style="color: #606060">  10:</span>     isOk = <span style="color: #0000ff">false</span>;</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum11" style="color: #606060">  11:</span> }</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum12" style="color: #606060">  12:</span> <span style="color: #0000ff">catch</span> (OverflowException)</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum13" style="color: #606060">  13:</span> {</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: #f4f4f4; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum14" style="color: #606060">  14:</span>     isOk = <span style="color: #0000ff">false</span>;</pre>
<p><!--CRLF--></p>
<pre style="text-align: left; line-height: 12pt; background-color: white; margin: 0em; width: 100%; font-family: 'Courier New', courier, monospace; direction: ltr; color: black; font-size: 8pt; overflow: visible; border-style: none; padding: 0px;"><span id="lnum15" style="color: #606060">  15:</span> }</pre>
<p><!--CRLF--></div>
</div>
<p>With the push to drive quality upstream, reduce costs (especially testing costs), and improve testability I envision that many testers will be working alongside our development counterparts to help them prevent defects from getting into the product code base, and improve the maintainability of the code. This doesn’t mean that testers will become developers or visa versa; it simply means that testers are (generally) experts in designing tests, and developers are experts in designing solutions that adhere to requirements. Rather than an adversarial relationship, I suspect in the future developers and testers will have a more symbiotic relationship to improve the intrinsic quality of our code bases.</p>
<p>The bottom line of all this is that in teams where testers are designing white box tests for improved code coverage (control flow testing), or where testers are engaged in design reviews or peer reviews of code prior to check in, I hope this gives you some things to think about.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.testingmentor.com/imtesty/2009/12/02/refactoring-for-testability/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Reconsidering Code Coverage</title>
		<link>http://www.testingmentor.com/imtesty/2009/11/25/reconsidering-code-coverage/</link>
		<comments>http://www.testingmentor.com/imtesty/2009/11/25/reconsidering-code-coverage/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 10:44:13 +0000</pubDate>
		<dc:creator>Bj Rollison</dc:creator>
				<category><![CDATA[Testing Practices]]></category>
		<category><![CDATA[Code Coverage]]></category>
		<category><![CDATA[Structural Testing]]></category>

		<guid isPermaLink="false">http://testingmentor.com/imtesty/2009/11/25/reconsidering-code-coverage/</guid>
		<description><![CDATA[Tonight on my way to teach a test automation course at the University of Washington I had some free time to catch up on my reading. My manager asked me if I had read this month’s copy of one of the several testing magazines we get and I replied that I had downloaded it but [...]]]></description>
			<content:encoded><![CDATA[<p>Tonight on my way to teach a test automation course at the University of Washington I had some free time to catch up on my reading. My manager asked me if I had read this month’s copy of one of the several testing magazines we get and I replied that I had downloaded it but hadn’t had a chance to read it yet. So, he tossed me the hardcopy of the magazine and said, “Enjoy.” Now this should have been a clue because although Alan is a great manager and mentor, I think he secretly likes to see the veins in my neck swell and blood shoot out of my eyes from time to time.</p>
<p>I read a lot of articles, white papers, and books. I like most of what I read, even if I disagree with some of the points being made. I can’t remember ever reading an article on software testing that ever made me angry. I was not angry because of the message of the article. In fact, I think the point the authors are trying to make is valid and I agree with them on their fundamental point. Unfortunately, the article is filled with technical inaccuracies the end message was almost lost.</p>
<p>I spent the last 10 years studying various techniques, methods, and approaches in software testing. I teach more than 500 testers a year on structural testing techniques, and am now working with a team in the Windows division to implement a new tool for just in time code coverage analysis at the component level that allows us to see how our tests exercise code paths in changed code and the dependent modules. I also discuss structural testing in chapter 5 of our book <em><a href="http://www.hwtams.com" target="_blank">How We Test Software At Microsoft</a></em>. I don’t really consider myself to be an expert in the subject, but I might know a thing or two about it. So, let’s Reconsider Code Coverage!</p>
<p>In August 2007 I wrote an <a href="http://blogs.msdn.com/imtesty/archive/2007/08/14/code-coverage-is-inversely-proportional-to-the-critical-information-it-provides.aspx">informative blog post</a> on the potential misuse of the code coverage measure. But code coverage measures are used by some companies as one of many ways to help them reduce risk. And, let me be very clear here, <strong><em>there is no correlation between code coverage and quality, and code coverage measures don’t tell us “how well” the code was tested</em></strong>. The code coverage measure simply measures what code has been executed, and more importantly what code has not been executed. The value of measuring code coverage is not in producing some “magic number,” but that it helps testers investigate untested or under-tested areas of the product and design additional tests (generally using structural testing techniques) to improve coverage and reduce overall risk.</p>
<blockquote><p><em>Just because you execute a line of code doesn’t mean a bug doesn’t still exist, but if you don’t execute a line of code you have 0 probability of finding a bug if one exists!</em></p></blockquote>
<p>Also it is important to note there are several ways to measure code coverage. Different tools employ different measures and sometimes different tools measure the same type of coverage differently. Also, I discovered that even the same tool can measure the same code differently depending on how it is compiled (debug, retail, etc.) and previously <a href="http://testingmentor.com/imtesty/2009/11/18/basic-blocks-arent-so-basic/">wrote</a> about my study. Some of the basic ways to measure code coverage (not test coverage) include:</p>
<ul>
<li><strong>Function coverage</strong> measures the percentage of functions or methods in a class or application that are called at runtime.</li>
<li><strong>Statement coverage</strong> measures the percentage of executable statements exercised at runtime.</li>
<li><strong>Block coverage</strong> measures the percentage of each sequence of non-branching statements that are executed at runtime. Block coverage subsumes statement coverage.</li>
<li><strong>Decision or branch coverage</strong> measures the percentage of both Boolean (not binary) outcomes (true and false) of simple conditional expressions at runtime. If a predicate statement has more than one conditional sub-expression decision (or branch) coverage treats that predicate statement as one conditional clause. Decision coverage subsumes block coverage.</li>
<li><strong>Condition coverage</strong> measures the percentage of both Boolean outcomes of each conditional sub-expressions that are separated by logical and or logical or in compound predicate statements. Condition coverage subsumes decision coverage.</li>
<li><a href="http://www.mccabe.com/pdf/nist235r.pdf"><strong>Basis path coverage</strong></a> measures the number of linearly independent paths through a program. Basis path coverage is based on <a href="http://www.literateprogramming.com/mccabe.pdf">McCabe’s cyclomatic complexity</a> research.</li>
<li><strong>Path coverage</strong> measures every possible path from the entry to the return statement (or exception) or exit of every method. Unfortunately path testing is usually impossible due to the sheer number of path combinations, and the inability to execute constrained path combinations.</li>
</ul>
<p>Clearly there are different measures of code coverage, and certain types of measures subsume other measures. So, now that we have a handle on the different types of code coverage measures, let’s look at testing some code. We will use the same pseudo code used in the aforementioned article which is based upon the following requirement.</p>
<blockquote><p>“Student ID’ are seven digit numbers between one million and 6 million inclusive.”</p></blockquote>
<p>The authors provided the following pseudo code example for a function to meet this requirement.</p>
<blockquote><p>function validate_studentid(string sid) return<br />
TRUEFALSE<br />
BEGIN<br />
  STATIC TRUEFALSE isOk;<br />
  isOk = true;</p>
<p>  if ((length(sid) is not 7) then<br />
    isOk = False;</p>
<p>  if (number(sid) &lt;= 1000000 or number(sid) &gt; 6000000 then<br />
     isOk = False;</p>
<p>  return isOk;</p>
<p>END</p></blockquote>
<p>So, other than the fact that there is no reason to ‘test’ the length of the sid variable before evaluating it to see if it is within the allowable range (removing this first conditional improves performance and also improves testability of the code), and that if the call to the number() function fails to convert the string to a number for a valid Boolean comparison it will throw an unhandled exception, let’s look at path testing of this simple example by starting with control flow diagrams of each possible path (assuming the call to the number() function does not throw an unhandled exception by passing this message a string of characters such as “foo” rather than a string of digits).</p>
<div id="attachment_244" class="wp-caption aligncenter" style="width: 594px"><img class="size-full wp-image-244" title="path" src="http://testingmentor.com/imtesty/wp-content/uploads/2009/11/path3.jpg" alt="Control flow diagram for validate_studentID() function pseudo-code" width="584" height="653" /><p class="wp-caption-text">Control flow diagram for validate_studentID() function pseudo-code</p></div>
<p>(Edited 11/25: After thinking about this a bit more, if the number() function returned a 0 (zero) if the input was incorrectly formatted, then the number() function would not throw an exception, and the control flow path would be identical to the first test in the table below).</p>
<p><a href="http://testingmentor.com/imtesty/wp-content/uploads/2009/11/path.jpg"></a></p>
<p>Because we are doing path coverage testing and not decision testing, we actually have to separate each Boolean conditional sub-expression in the second compound predicate statement if (number(sid) &lt;= 1000000 or number(sid) &gt; 600000. The example in the article treated both sub-expressions in the compound predicate statement as a single Boolean expression which would be synonymous with decision coverage. Path coverage actually treats each sub-expression as if there were 2 single Boolean conditions such as</p>
<blockquote><p>if (number(sid) &lt;= 1000000<br />
  isOk = False;</p>
<p>if number(sid) &gt; 600000<br />
  isOk = False;</p></blockquote>
<p>The table below illustrates the tests required for testing control flow through this function for path coverage (again assuming we are going to ignore the unhandled exception in the code that would occur by passing in a string such as “foo.”)</p>
<table border="1" cellspacing="0" cellpadding="2" width="553">
<tbody>
<tr>
<td width="71" valign="top">Input (sid)</td>
<td width="101" valign="top">Conditional<br />
length(sid)!= 7</td>
<td width="103" valign="top">Conditional<br />
number &lt;= 1mill</td>
<td width="93" valign="top">Conditional<br />
number &gt; 6mil</td>
<td width="86" valign="top">Expected<br />
Result</td>
<td width="97" valign="top">Actual<br />
Result</td>
</tr>
<tr>
<td width="71" valign="top">999999</td>
<td width="101" valign="top">true</td>
<td width="103" valign="top">true</td>
<td width="93" valign="top">false</td>
<td width="86" valign="top">False</td>
<td width="97" valign="top">False</td>
</tr>
<tr>
<td width="71" valign="top">6500000</td>
<td width="101" valign="top">false</td>
<td width="103" valign="top">false</td>
<td width="93" valign="top">true</td>
<td width="86" valign="top">False</td>
<td width="97" valign="top">False</td>
</tr>
<tr>
<td width="71" valign="top">1000000</td>
<td width="101" valign="top">false</td>
<td width="103" valign="top">true</td>
<td width="93" valign="top">false</td>
<td width="86" valign="top"><strong>True</strong></td>
<td width="97" valign="top"><strong>False</strong></td>
</tr>
<tr>
<td width="71" valign="top">6000000</td>
<td width="101" valign="top">false</td>
<td width="103" valign="top">false</td>
<td width="93" valign="top">false</td>
<td width="86" valign="top">True</td>
<td width="97" valign="top">True</td>
</tr>
</tbody>
</table>
<p>The first test would be a value less than 7 digits, and would cause all Boolean conditional expressions to evaluate as true which will set the isOk variable to false (3 times), and we correctly return the expected result of false (or invalid ID). The second test is a number greater than 6,000,000 (but less than the maximum value that would result in an unhandled overflow exception hopefully being thrown by the number() function). In this case the 3rd conditional expression (<em>if (number(sid) &gt; 6000000</em>) would evaluate as true and the function would return false. The 3rd path is buggy. In this pseudo code example, the only possible way to exercise the true outcome of the Boolean condition <em>if (number(sid) &lt;= 1000000</em> is to use the value of 1,000,000; any other value larger or smaller will cause this Boolean condition to evaluate as false. In this case we expect the function to return true, but it in fact will return false. Finally, any number greater than 1000001 and less than or equal to 6000000 will return a true result indicating a valid student ID.</p>
<p>The article also suggest that structural testing misses other problems. But, when we look at these issues, they actually have nothing to do with structural testing of the function; in other words they are completely out of context of the problem being discussed.</p>
<p>For example, the assert is the requirement is incorrect and should have read 6,999,999 (<strong><em>which I believe is a typo and should be 5,999,999</em></strong>) because of confusion over the word “inclusive.” Inclusive means “<em>including the stated limit or extremes in consideration or account,</em>” but in computing inclusive means “<em>the predicate holds for all elements of an increasing sequence then it holds for their least upper bound.</em>” I disagree with this assumption because I suspect the analyst writing the spec is basing the inclusive range on the common definition, and not a definition based on <a href="http://www.cs.bham.ac.uk/~axj/pub/papers/handy1.pdf">domain theory</a>.</p>
<p>The article questions what would occur with incorrectly formatted numbers such as 123 456 789 or 123,456,789. So, beside the point that these values are not within the valid range of student id numbers, the answer to the question would actually lie in how the <em>number()</em> function being called handles improperly formatted numbers (e.g throwing a format exception, which again is unhandled in our <em>validate_studentid()</em> function), or how an event handler that sits between the UI and the function might deal with invalid or incorrectly formatted inputs.</p>
<p>The next question concerned resizing of the input window or the screen (assuming desktop resolution) and repainting the window or form and its affect on code coverage of the <em>validate_studentid()</em> function. Well, I am going out on a limb here and I am going to say…”what are you talking about?” I am not quite sure how to phrase this, but let me try…resizing or repainting a window has 0 effect on the structural control flow of the <em>validate_studentid()</em> function. (Of course, I could be wrong, and the length() function number() function might have some code that mysteriously interacts with the repainting libraries and how it determines the length of a string or whether a string is a valid number.)</p>
<p>Bugs in external libraries are part of the business. Hopefully those external libraries are well tested or at least documented especially if our development team wrote them. Personally, I have not encountered any public functions or APIs which use wild ass random numbers such as 5.8 million as boundary values, but that’s not to say it couldn’t happen. And of course, if these external functions throw exceptions (as they should based on what they are probably doing), we should have exception handler code in our function to deal with any exceptions thrown from external libraries or function calls.</p>
<p>Based on incorrect path analysis, and out-of-context questions that have nothing to do with control flow through the <em>validate_studentid()</em> function the article suggests that path testing is not a magic potion, but I am not too sure that anyone actually believes it is. And so, the article suggests that “input combinatorics coverage” might work better. Hmm…now I have been teaching combinatorial testing for over 10 years and have read some interesting papers on the effectiveness of combinatorics on statistical testing and code coverage, and I must say I pretty sure you need more than one input parameter in combinatorial testing!</p>
<p>Finally, I don’t agree that code coverage measures tell us “how well the developers have tested their code.” The code coverage measure only tells us what percentage of the code has been executed in a particular way, and more importantly it tells us how what percentage of code has been untested. We must determine whether we need to investigate that area to reduce risk. Of course, many code coverage tools provide a “heat map” that helps us and developers identify untested code, and that is where we shift from the simple act of measuring coverage to the testing method of code coverage analysis in order to design new tests that effectively exercise previously untested code if that level of coverage is important to reduce overall risk.</p>
<p><a href="http://testingmentor.com/imtesty/wp-content/uploads/2009/11/heatmap.jpg"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="heat map" src="http://testingmentor.com/imtesty/wp-content/uploads/2009/11/heatmap_thumb.jpg" border="0" alt="heat map" width="545" height="514" /></a></p>
<p>My intent here is not to ridicule the authors of the article. In fact, I agree with their summation that testers should not believe high code coverage numbers mean “well tested.” (Again see my <a href="http://testingmentor.com/imtesty/2009/11/13/the-code-coverage-metric-is-inversely-proportional-to-the-criticality-of-the-information-it-provides/">blog post from Aug 2007</a>.) Unfortunately, the path to the point was fraught with inaccuracies and tangents that I almost never made it to the end.</p>
<p>There are many books and white papers on this subject in the ACM and IEEE libraries. Books by Boris Beizer, Robert Binder, and others go into great detail on structural testing. McCabe’s papers linked to in this post are an excellent resources.</p>
<p>OK…I feel better now. I need to clean up the blood, take a sedative, and go to sleep.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.testingmentor.com/imtesty/2009/11/25/reconsidering-code-coverage/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Basic Blocks Aren&#8217;t So Basic</title>
		<link>http://www.testingmentor.com/imtesty/2009/11/18/basic-blocks-arent-so-basic/</link>
		<comments>http://www.testingmentor.com/imtesty/2009/11/18/basic-blocks-arent-so-basic/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 04:20:56 +0000</pubDate>
		<dc:creator>Bj Rollison</dc:creator>
				<category><![CDATA[Testing Practices]]></category>
		<category><![CDATA[Code Coverage]]></category>
		<category><![CDATA[Structural Testing]]></category>

		<guid isPermaLink="false">http://testingmentor.com/imtesty/2009/11/18/basic-blocks-arent-so-basic/</guid>
		<description><![CDATA[Originally Published Friday, March 06, 2009 
In the book How We Test Software at Microsoft I discuss structural testing techniques. Structural testing techniques are systematic procedures designed to analyze and evaluate control flow through a program. These are classic white box test design techniques, although my friend and respected colleague Alan Richardson states in his [...]]]></description>
			<content:encoded><![CDATA[<p>Originally Published Friday, March 06, 2009 </p>
<p>In the book <a href="http://www.amazon.com/exec/obidos/ASIN/0735624259/compendiumdev-20"><em>How We Test Software at Microsoft</em></a> I discuss structural testing techniques. Structural testing techniques are systematic procedures designed to analyze and evaluate control flow through a program. These are classic white box test design techniques, although my friend and respected colleague <a href="http://www.eviltester.com/index.php/about/">Alan Richardson</a> states in his review of the book that he also <a href="http://www.compendiumdev.co.uk/blog/index.php/2009/02/04/book-review-how-we-test-software-at-microsoft/">employs similar techniques on models</a> and I have to agree with him on that point.</p>
<p>Also, Peter M. sent me mail pointing out a reasonably obvious bug in the code chunks on pages 118 and 119. Both functions are declared as static void, but each has a return statement. Somehow this oversight made it through the review process, but of course a return statement in a function declared as static void would cause a compiler error. (Thanks for discovering that bug Peter and letting us know so we can fix it for the 2nd edition!) </p>
<p>Peter also asked for further clarification of how blocks are counted, and why a test that evaluated both conditional clauses in the compound expression as true in the below example (and on page 119) results in 85.71% coverage. Unfortunately, the answer for that is not simple. </p>
<h3>Some surprising details…</h3>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">int</span> BlockExample1(<span style="color: #0000ff">bool</span> cond_1, <span style="color: #0000ff">bool</span> cond_2)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   <span style="color: #0000ff">int</span> x = 0, y = 0, z = 0;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>   <span style="color: #0000ff">if</span> (cond_1 &amp;&amp; cond_2)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>   {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>     x = 1;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>     y = 2;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     z = 3;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>   }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>   <span style="color: #0000ff">return</span> x + y + z;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span> }</pre>
<p><!--CRLF--></div>
</div>
<p>The above code can be re-written as:</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">int</span> BlockExample2(<span style="color: #0000ff">bool</span> cond_1, <span style="color: #0000ff">bool</span> cond_2)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   <span style="color: #0000ff">int</span> x = 0,</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>   y = 0,</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>   z = 0;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>   <span style="color: #0000ff">if</span> (cond_1)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>   {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>     <span style="color: #0000ff">if</span> (cond_2)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     { </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>       x = 1;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>       y = 2;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>       z = 3;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>     } </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>   }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>   <span style="color: #0000ff">return</span> x + y + z;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span> }</pre>
<p><!--CRLF--></div>
</div>
<p>First, a &#8216;basic block&#8217; is defined as a set of contiguous executable statements with no logical branches which seems pretty straight forward. So, based on our definition of basic blocks it appears there are 4 blocks of contiguous statements. However, the conditional clauses on line 4 and line 6 in the BlockExample2 method introduce logical branches which theoretically introduce 2 implicit blocks (e.g. one block when control flow follows the true path, and another block when control flow follows the false path). So, that is essentially how the 6 blocks are determined. But, that&#8217;s not the end of the story.</p>
<p>If we pass a Boolean true to both cond_1 and cond_2 conditional clauses the block coverage measure in BlockExample1 results in 85.71% coverage; however, the block coverage measure for BlockExample2 actually results in 100% coverage as illustrated below.</p>
<p><a href="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/ed1c2ebc6677_79E3/coverage_2.jpg"><img title="coverage" border="0" alt="coverage" src="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/ed1c2ebc6677_79E3/coverage_thumb.jpg" width="715" height="235" /></a> What? How can this be? Both BlockExample1 and BlockExample2 are syntactically identical. Well, to understand this we would really need to dig deeper into compilers and coverage tools. That is well beyond the boundaries of this blog, but the IL does provide some insight.</p>
<p><a href="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/ed1c2ebc6677_79E3/msil_2.jpg"><img title="msil" border="0" alt="msil" src="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/ed1c2ebc6677_79E3/msil_thumb.jpg" width="727" height="677" /></a></p>
<p>The MSIL for BlockExample1 is on the left and BlockExample2 is on the right. Now, I don&#8217;t want to do a deep dive into MSIL, but&#160; those who are really observant can see that for some reason the Visual Studio compiler evaluated a branch in BlockExample1 to false (instruction IL_0008), and then instruction IL_000c compares the 2 values for equality and instruction IL_0015 appears to evaluate the optimized compound conditional expression to true. Compare that to BlockExample2 MSIL which shows the first comparison of 2 values occurs at IL_0009 and the branch is evaluated as true (IL_000f) and the second comparison of 2 values occurs at IL_0014 and again evaluates to true at instruction IL_001a. </p>
<p>But wait…it gets even more confusing. We typically measure structural coverage using the debug build. So, imagine my surprise when I recompiled the code using the retail build settings and again passed true arguments to the cond_1 and cond_2 parameters for BlockExample1 and BlockExample2 and the coverage tool in Visual Studio indicated these methods now only had 4 blocks, and the block coverage measure for both methods was 100% as illustrated below. </p>
<p><a href="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/ed1c2ebc6677_79E3/coverage2_2.jpg"><img title="coverage2" border="0" alt="coverage2" src="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/ed1c2ebc6677_79E3/coverage2_thumb.jpg" width="694" height="207" /></a></p>
<p>Also, interestingly enough the compiler optimized the code so both methods had identical MSIL op code instructions as illustrated below.<a href="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/ed1c2ebc6677_79E3/be2_2.jpg"><img title="be2" border="0" alt="be2" src="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/ed1c2ebc6677_79E3/be2_thumb.jpg" width="674" height="513" /></a>Steve Carroll (a senior developer in Visual Studio) <a href="http://blogs.msdn.com/scarroll/archive/2005/01/14/353427.aspx">wrote</a> we &quot;<em>shouldn&#8217;t be too concerned if you can&#8217;t exactly identify where all the blocks are.&#160; When you turn the optimizer on your binary, block counts are fairly unpredictable</em>. <em>Don&#8217;t worry though, the source line coloring will almost always lead you to the parts of the code that you need to worry about targeting to get your coverage stats up.</em>&quot;</p>
<p>I agree with Steve when he states block counts are unpredictable when the code is optimized (and different tools that measure block coverage may provide different results). However, I only partially with his statement that source line coloring leading us to parts of the code we need to test. Maybe it will, maybe it won&#8217;t. But, professional testers performing an in-depth analysis of code coverage results will help us identify important parts of the code that require further investigation and testing.</p>
<h3><strong>So, what does it all mean?</strong></h3>
<p>Block testing is useful for unit testing and designing white box tests for switch statements and exception handlers (based on how we can track control flow through source code using a debugger as opposed to through the IL Disassembler). But, as I stated in <em><a href="http://www.amazon.com/exec/obidos/ASIN/0735624259/compendiumdev-20">How We Test Software at Microsoft</a></em> block testing is the weakest form of structural testing. But, it does provide a different perspective as compared to other structural approaches or techniques and is useful when used by a professional tester in the right context.</p>
<p>But, the important point here is that just as we wouldn&#8217;t rely on only one tool to tune the carburetor on an automobile, we certainly would rely on only one technique or approach for designing structural tests; and we certainly wouldn&#8217;t only rely on structural testing as a single approach to testing. This example further reinforces another important point that I make in the book; code coverage is not directly related to quality. Any professional tester can clearly see that although we are able to achieve high levels of coverage with one test, these methods are not at all well tested. </p>
<p>Only a fool would use code coverage metrics to derive some measure of quality, or suggest the implication that high coverage measures equal greater quality. In truth, the value of code coverage is in its ability to help professional testers identify areas of the code that have not been previously exercised and to design tests to evaluate those areas of the code more effectively to help reduce overall risk. </p>
<p>If we don&#8217;t execute an area of code then we have zero probability of exposing errors in that code if they exist. However, just because we do execute a code statement doesn&#8217;t mean we expose all potential errors. But, it at least increases the probability from 0% and helps reduce risk.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.testingmentor.com/imtesty/2009/11/18/basic-blocks-arent-so-basic/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>The Code Coverage Metric is Inversely Proportional to the Criticality of the Information It Provides.</title>
		<link>http://www.testingmentor.com/imtesty/2009/11/13/the-code-coverage-metric-is-inversely-proportional-to-the-criticality-of-the-information-it-provides/</link>
		<comments>http://www.testingmentor.com/imtesty/2009/11/13/the-code-coverage-metric-is-inversely-proportional-to-the-criticality-of-the-information-it-provides/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 05:07:32 +0000</pubDate>
		<dc:creator>Bj Rollison</dc:creator>
				<category><![CDATA[Testing Practices]]></category>
		<category><![CDATA[Code Coverage]]></category>
		<category><![CDATA[Structural Testing]]></category>
		<category><![CDATA[White Box Testing]]></category>

		<guid isPermaLink="false">http://testingmentor.com/imtesty/2009/11/13/the-code-coverage-metric-is-inversely-proportional-to-the-criticality-of-the-information-it-provides/</guid>
		<description><![CDATA[One of the best aspects of my current role is the opportunity to interact with so many talented, highly skilled, and extremely intelligent testers at Microsoft and other companies around the world. Last week I was teaching a new group of SDETs at Microsoft, and during our discussion of code coverage (the metric) and code [...]]]></description>
			<content:encoded><![CDATA[<p>One of the best aspects of my current role is the opportunity to interact with so many talented, highly skilled, and extremely intelligent testers at Microsoft and other companies around the world. Last week I was teaching a new group of SDETs at Microsoft, and during our discussion of code coverage (the metric) and code coverage analysis (the process of analyzing areas of untested or unexercised code) Alex Kronrod (an intern from UC Berkeley who attended the class) stated &quot;so basically what you&#8217;re saying is the code coverage measure is inversely proportional to the amount of information it provides.&quot; Now, I don&#8217;t know whether or not there is exact proportionality in the code coverage metric and the information provided by the measure itself, but I thought about it a moment and thought to myself, &quot;Wow, what a great perspective!&quot; </p>
<p>Code coverage is a frequently sought after measure in software testing. Code coverage is an important metric and it should not be ignored; however, as a measure it must not be abused or over-rated, nor should we attempt to correlate code coverage as a direct measure of quality. While many teams strive for higher percentages of code coverage at the system level (which is good), the code coverage metric simply tells us if statements, block of statements, or conditional expressions have been exercised. Low measures of code coverage may sometimes result from software complexity and lack of testability or from testing ineffectiveness, but are generally indicative of a software project in peril (with regards to risk). Higher percentages of code coverage certainly help reduce perceived overall risk, but the code coverage measure by itself doesn&#8217;t necessarily tell us HOW it was exercised, and it doesn&#8217;t provide useful information about the areas of the code that have not been exercised other than what percentage of the code is at 100% at risk. (If we don&#8217;t test it; we can&#8217;t qualitatively say anything about it, so risk must be assumed to be 100%.)</p>
<p>Let&#8217;s examine the following simple example to explain this search algorithm to better understand how increased measures of code coverage provide less valuable information regarding testing effectiveness. This algorithm searches for a particular character in a string of characters and returns the index position of the character if found; otherwise it returns 0.</p>
<div style="border-bottom: silver 1px solid; text-align: left; border-left: silver 1px solid; padding-bottom: 4px; line-height: 12pt; background-color: #f4f4f4; margin: 20px 0px 10px; padding-left: 4px; width: 97.5%; padding-right: 4px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; max-height: 200px; font-size: 8pt; overflow: auto; border-top: silver 1px solid; cursor: text; border-right: silver 1px solid; padding-top: 4px" id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px" id="codeSnippet">
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum1">   1:</span> <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">int</span> CharSrch(<span style="color: #0000ff">string</span> s, <span style="color: #0000ff">char</span> c)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum2">   2:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum3">   3:</span>   <span style="color: #0000ff">int</span> i = 0;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum4">   4:</span>   <span style="color: #0000ff">int</span> retVal = 0;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum5">   5:</span>   <span style="color: #0000ff">char</span>[] cArray = s.ToCharArray();</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum6">   6:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum7">   7:</span>   <span style="color: #0000ff">while</span> ((i &lt; cArray.Length) &amp;&amp; (cArray[i] != c))</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum8">   8:</span>   {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum9">   9:</span>     i++;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum10">  10:</span>   } </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum11">  11:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum12">  12:</span>   <span style="color: #0000ff">if</span> (i &lt; (cArray.Length))</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum13">  13:</span>   {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum14">  14:</span>     retVal = i;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum15">  15:</span>   }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum16">  16:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: white; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum17">  17:</span>   <span style="color: #0000ff">return</span> retVal;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 12pt; border-right-style: none; background-color: #f4f4f4; margin: 0em; padding-left: 0px; width: 100%; padding-right: 0px; font-family: &#39;Courier New&#39;, courier, monospace; direction: ltr; border-top-style: none; color: black; font-size: 8pt; border-left-style: none; overflow: visible; padding-top: 0px"><span style="color: #606060" id="lnum18">  18:</span> }</pre>
<p><!--CRLF--></div>
</div>
<p><a href="http://11011.net/software/vspaste"></a>Using Visual Studio Team System to measure block coverage and executing a test in which s = &quot;&quot; and c = &#8216;c&#8217; the code coverage measure is only 72.73% for the CharSrch method as illustrated in the figure below. In this example it is easy to understand why the relatively low code coverage measure is giving us valuable information (perceived risk is great, overall confidence is low). Clearly we have more testing to do!</p>
<p><a href="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/Codecoverageisinverselyproportionaltoth_F010/CodeCoverageTest3.jpg"><img border="0" alt="CodeCoverageTest3" src="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/Codecoverageisinverselyproportionaltoth_F010/CodeCoverageTest3_thumb.jpg" width="700" height="659" /></a></p>
<p>Again using Visual Studio Team System to measure block coverage and executing a test in which the search string is &quot;abc&quot; and the character to search for is &#8216;c&#8217; the code coverage measure jumps up to 90.91% for the CharSrch method as illustrated in the figure below. Using just the code coverage measure as an indication of test effectiveness we might feel much more confident and perceive our exposure to risk is greatly reduced, and the algorithm is doing the right thing! But, we are still not at 100% (which is easy for this example), so we need just one more test to achieve that magic number.</p>
<p><a href="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/Codecoverageisinverselyproportionaltoth_F010/CodeCoverageTest2_1.jpg"><img border="0" alt="CodeCoverageTest2" src="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/Codecoverageisinverselyproportionaltoth_F010/CodeCoverageTest2_thumb_1.jpg" width="700" height="671" /></a></p>
<p>A third test in which the search string is &quot;a&quot; and the character to search for is &#8216;c&#8217; we see the resultant code coverage is again 90.91% as illustrated in the figure below. By merging the code coverage results in Visual Studio Team System we can achieve 100% block coverage by merging the results of Test 1 ( s = &quot;a&quot; and c = &#8216;c&#8221;) and Test 2 (s = &quot;abc&quot; and c = &#8216;c&#8217;) . If unit tests were written in such a way as to check for an output of retVal == 0 for Test 1, and an output of retVal != 0 for Test 2, then both tests pass. Overall, my perceived risk is relatively low, and my confidence is relatively high as compared to the first test based on the code coverage measure. But, did we miss something?</p>
<p><a href="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/Codecoverageisinverselyproportionaltoth_F010/CodeCoverageTest1_1.jpg"><img border="0" alt="CodeCoverageTest1" src="http://blogs.msdn.com/blogfiles/imtesty/WindowsLiveWriter/Codecoverageisinverselyproportionaltoth_F010/CodeCoverageTest1_thumb_1.jpg" width="702" height="702" /></a></p>
<p>Although the percentage of block coverage is relatively high (OK&#8230;100% is the max), the information provided by the measure itself is actually less valuable because it may have actually failed to detect the defect in which the CharSrch method returns a value of 0 if the character is not found, and also returns a value of 0 if the search character is the first character in the string.</p>
<p>This simple example is not meant to discount the overall value of code coverage as a software metric. However, as professional testers we must realize that high levels of code coverage do not directly relate to quality, and code coverage is only an indirect indication of test effectiveness. From my perspective, the most important measure with regards to code coverage is not how much has been exercised, but the percentage of code that has been unexercised by our testing. That is the purpose of code coverage analysis (which is a great segue for a follow up blog post). </p>
]]></content:encoded>
			<wfw:commentRss>http://www.testingmentor.com/imtesty/2009/11/13/the-code-coverage-metric-is-inversely-proportional-to-the-criticality-of-the-information-it-provides/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
