<?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; White Box Testing</title>
	<atom:link href="http://www.testingmentor.com/imtesty/tag/white-box-testing/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.testingmentor.com/imtesty</link>
	<description>Treatises on the practice of software testing</description>
	<lastBuildDate>Fri, 02 Dec 2011 01:48:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Code Coverage: Unreachable Code and Hard to Reach Code</title>
		<link>http://www.testingmentor.com/imtesty/2010/08/27/code-coverage-unreachable-code-and-hard-to-reach-code/</link>
		<comments>http://www.testingmentor.com/imtesty/2010/08/27/code-coverage-unreachable-code-and-hard-to-reach-code/#comments</comments>
		<pubDate>Fri, 27 Aug 2010 21:44:26 +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[White Box Testing]]></category>

		<guid isPermaLink="false">http://www.testingmentor.com/imtesty/2010/08/27/code-coverage-unreachable-code-and-hard-to-reach-code/</guid>
		<description><![CDATA[Well, I am back from a sailing excursion to the San Juan Islands. I wanted to go to the Gulf Islands, but considering an unexpected ordeal with a kidney stone just before taking off on the trip I decided it might be better to be a bit closer…just in case. The weather was great, and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image4.png"><img style="margin: 0px 10px 0px 0px; display: inline; border: 0px;" title="image" src="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image_thumb4.png" border="0" alt="image" width="263" height="293" align="left" /></a> Well, I am back from a sailing excursion to the San Juan Islands. I wanted to go to the Gulf Islands, but considering an unexpected ordeal with a kidney stone just before taking off on the trip I decided it might be better to be a bit closer…just in case. The weather was great, and we spent a lot of time exploring Stuart and James Islands, and dropped into Roche Harbor the first night and Friday Harbor the last night in the islands. We limited out on Dungeness crabs on all but 2 days where we only managed to get 3 legal size crabs on those 2 days. Basically this translates to a lot of crab cakes in the freezer&#8230;yum! This was the first time my daughter went crabbing with me. My daughter would ride out in the dinghy with me to check the pots, and would point out the male crabs for me, but she wouldn’t reach in an help me throw back the females or undersized males. Come to think about it, she didn’t help me cook and clean the crabs either…she just ate the crab cakes we made on the boat. I think the rules might have to change next year! All in all it was a great month decompressing and recharging, and contemplating my personal and professional future.</p>
<p>But enough about me. My last 2 posts have been discussing code coverage analysis. The primary purpose of using code coverage tools as either a developer or as a tester is not to try to obtain some magical ROMA number. The biggest value of measuring code coverage is to help us analyze untested areas of code and make informed decisions of whether or not we need to design additional tests to increase test coverage and help reduce exposure to risk.</p>
<p>The last post illustrated how we might use code coverage results to help us design additional tests we might have missed during the execution of any pre-defined tests (automated or manual) and additional exploratory testing efforts. But remember, the goal is simply not to design tests in order to get the tool to report 100% code coverage. In fact, in just about any complex system executing 100% of the statements in code may not be feasible or provide any practical value. This is generally referred to as unreachable code.</p>
<p>For example, let’s look at this (albeit antiquated) code snippet.</p>
<p><a href="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image5.png"><img style="display: inline; border-width: 0px;" title="image" src="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image_thumb5.png" border="0" alt="image" width="947" height="110" /></a></p>
<p>The code coverage tool is indicating that this conditional statement has been exercised to its true outcome, but not it’s false outcome. This was a common approach used in 16-bit applications to prevent multiple instances of the same application on a single machine. However, in the 32-bit world <a href="http://support.microsoft.com/kb/106385" target="_blank"><em>hPrevInstance</em></a> always returns null, which means there is no practical way to make this conditional statement return false.</p>
<p>This is a bit of an obscure example, but is used to illustrate why a greater understanding of the programming language used by the development team would help testers from banging their heads against the wall ‘trying’ different things until someone realizes we could never make this conditional statement return false. By analyzing this section of the code coverage results we might suggest refactoring for a Win32/64 environment, or at least be able to explain why this conditional will not return false. (Remember…it’s all about information.)</p>
<p>Another example of unreachable code is sometimes caused by coding style or possibly unnecessary code. For example, the following lines are also in the <em>WinMain</em>() function that is called when the ‘user’ launches the application.</p>
<p><a href="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image6.png"><img style="display: inline; border-width: 0px;" title="image" src="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image_thumb6.png" border="0" alt="image" width="959" height="170" /></a></p>
<p>In this situation when the application initially starts and calls the <em>WinMain</em>() function these 2 conditional statements in <em>WinMain</em>() determine whether the Frog and Car bitmaps are true. Since we just launched the application and the bitmaps have not yet been loaded by any other calls to <em>LoadBitmap</em>() then the conditional statements in lines 104 and 109 will never go true, and lines 105 and 110 will never be executed. Again, following an analysis of the section of the code we can provide information regarding why we can’t design a test to cause these conditional statements to return true without fault injection or code mutation. Additional information that we might provide based on our analysis of the code coverage results may be a suggestion to refactor this code to improve testability.</p>
<p>A similar example of unreachable code is a common coding style involving <em>switch</em> statements where developers included a <em>case</em> statement for each possible value, and also included a <em>default</em> statement. For example in the last post we saw how we saw this code chunk which is essentially the menu structure.</p>
<p><img title="image" src="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image_thumb3.png" border="0" alt="image" width="959" height="220" /></p>
<p>When the menu item is selected the submenu displays the submenu items <em>Start</em> and <em>Exit</em>. When the submenu is displayed the only actions possible is to select the Start submenu item (line 270), or the Exit submenu item (line 274). Without fault injection there is no practical way to execute the <em>default</em> statement in line 277. Again, this may be another example where refactoring could improve testability because if the <em>default</em> statement is removed control flow would simply pass out of the switch block.</p>
<p>However, this is not always the case with <em>switch</em> statements. Here is an example in which a modal message box is displayed and draws 2 buttons; a yes button to restart the game, and a no button to quit the game. But notice that the <em>default</em> case statement (line 295) has not been executed.</p>
<p><a href="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image7.png"><img style="display: inline; border-width: 0px;" title="image" src="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image_thumb7.png" border="0" alt="image" width="935" height="260" /></a></p>
<p>In this situation if we launch the game, move the frog to get hit by a car this modal message box will display showing the ‘end user’ 2 possible buttons to press (in this case the ESC key or the Close control button in the upper right corner of the modal dialog are not possible options). However, if we put the game into a state where this modal dialog is displayed and then kill the application process using Windows Task Manager control flow will pass to line 295 as the process terminates.</p>
<p>Of course, it may not be practical or reasonable to terminate the application process from every possible machine state. Also, this simply increases the costs of testing without adding any real practical value. Providing this information to the decision makers along with suggestions to refactor and improve testability to reduce overall testing costs is another way code coverage analysis can be a valuable tool in a tester’s toolbox.</p>
<p>Another example of hard to reach code. In this case the conditional statement is if the RegisterClass() function fails then we want to return false.</p>
<p><a href="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image8.png"><img style="display: inline; border: 0px;" title="image" src="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image_thumb8.png" border="0" alt="image" width="959" height="77" /></a></p>
<p>The RegisterClass() function is also called within the WinMain() function when the application initially launches. So, while analyzing the code coverage results the question we ask ourselves is, “Without fault injection can we make the conditional statement in line 88 return true, and if so how?”</p>
<p>Well, we can. All we have to do is launch about 450 instances of this application to cause line 88 return true. Now, we have to ask ourselves, “What value does this test provide?” Especially since the code design should only allow 1 instance of the application (although it fails to do that because it is a 16-bit app running on a 32-bit environment and that is the nature of hPrevInstance as explained earlier.</p>
<p>From a testing perspective the primary goal of code coverage is not to achieve some magic number; the objective of code coverage is to analyze code coverage results in order to</p>
<ul>
<li>Improve test coverage</li>
<li>Reduce overall risk</li>
<li>Potentially increase testability of the project</li>
</ul>
<p>The code coverage number is not really useful information to anyone. It is the analysis of the code coverage results that can help us decide whether we need to design additional tests, identify areas of the code that can’t be executed without even more expensive testing such as fault injection and/or code mutation, or refactor the code to improve testability (which often increases the code coverage measure).</p>
<p>But, this is not to suggest that we should employ code coverage and analyze the results for all software projects. Analyzing code coverage results and designing additional tests from a white box perspective, or refactoring code are all additional expenses for any project. For each project we (or our managers) must decide whether the cost is worth the improved coverage and potentially a reduction in overall risk.</p>
<p>Another way to look at it…it is our responsibility as testers to provide valued information to the decision makers. If the only information we are providing is that we achieved 80% code coverage then we really aren’t doing an effective job. Yes, many managers are number focused; however, the valuable information is in the rest of the story about the 20% that has not been executed.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.testingmentor.com/imtesty/2010/08/27/code-coverage-unreachable-code-and-hard-to-reach-code/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Code Coverage: Finding missing tests</title>
		<link>http://www.testingmentor.com/imtesty/2010/08/22/code-coverage-finding-missing-tests/</link>
		<comments>http://www.testingmentor.com/imtesty/2010/08/22/code-coverage-finding-missing-tests/#comments</comments>
		<pubDate>Mon, 23 Aug 2010 00:11:12 +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[White Box Testing]]></category>

		<guid isPermaLink="false">http://www.testingmentor.com/imtesty/2010/08/22/code-coverage-finding-missing-tests/</guid>
		<description><![CDATA[[NOTE: This was written last week but due to a glitch did not get automatically posted before I left on a boat trip where I disconnected from the world. How refreshing…but more about that later.] Well, we got a buy in the quarter final play-offs, and we won our semi-final game against the Sockeyes (2 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/hockey.jpg"><img style="border-bottom: 0px; border-left: 0px; margin: 0px 0px 5px 10px; display: inline; border-top: 0px; border-right: 0px" title="hockey" border="0" alt="hockey" align="right" src="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/hockey_thumb.jpg" width="225" height="193" /></a> </p>
<p>[<em>NOTE: This was written last week but due to a glitch did not get automatically posted before I left on a boat trip where I disconnected from the world. How refreshing…but more about that later.</em>]</p>
<p>Well, we got a buy in the quarter final play-offs, and we won our <a href="http://www.gshockey.com/sites/3333/page.asp?Site=9941&amp;LeagueID=9941&amp;DivisionID=47&amp;page=playoff_tree2_gshl" target="_blank">semi-final game</a> against the Sockeyes (2 – 0) last Tuesday. Unfortunately, while celebrating with my teammates I was literally knocked to the floor by a kidney stone in my bladder. After a trip to the hospital I am now taking a battery of pain-killers until I pass the stone. Unfortunately, this put me on the injured roster and knocked me out of the final game and until I get an OK from the doctor. Fortunately, I am not prone to kidney stones and this shall pass (literally). I have only had one kidney stone in the past and that was about 20 years ago. For those of you who have not experienced a kidney stone, trust me on this…be very, very glad and I hope you never experience this malady. </p>
<p>Last week I attempted to to illustrate how we might achieve high levels of code coverage (structural control flow) but potentially overlook critical tests, especially from a ‘black-box’ testing approach. The bottom line message…high code coverage does not necessarily equal good test coverage. In reality it is really unlikely to get 100% measured code coverage of an reasonably complex application under test. Unfortunately this often begs the question, “What is the right amount of code coverage for [my] application?” To which I have heard several leads/managers reply, “Our goal is 80% code coverage?” Really? C’mon…that’s just plain <a href="http://www.jargondatabase.com/Jargon.aspx?id=9903" target="_blank">ROMA data</a>. Setting arbitrary goals for code coverage is about as <a href="http://www.urbandictionary.com/define.php?term=useless%20as%20tits%20on%20a%20boar%20hog" target="_blank">pointless as tits on a boar hog</a>. The real answer is that we simply don’t know what measure of code coverage is the ideal level for any product.</p>
<p><a href="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image.png"><img style="border-right-width: 0px; margin: 0px 10px 0px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image_thumb.png" width="497" height="271" /></a>Also, for those who have read <a href="http://testingexperience.com/testingexperience04_09.pdf" target="_blank">this article</a> will know that regardless of the testing approach at some point the effectiveness of our tests to hit untested areas of code diminishes. While more time and effort may increase data flow coverage and expose issues, it is unlikely to increase control flow (code) coverage. Remember, just because you exercise a line of code doesn’t mean you found all the bugs, but you have 0% probability of finding any bugs in any untested code.</p>
<p>Fortunately, the majority of customers will traverse the same code paths covered by many of our tests. Also, if your team/organization does robust unit testing then there is a good probability that unit tests at least provided some minimal level of code coverage. (<em>NOTE: While I highly recommend that unit tests and coverage results should be transparent to the test team, I do not recommend using unit tests as part of the battery of tests designed by the test team and executed against the whole build to measure code coverage.</em>) So, there are a couple of questions we have to ask ourselves. </p>
<blockquote><p>“Does the untested code present significant risk to our customers?”</p>
<p>“Do we need to reduce exposure to risk in the untested areas of code?”</p>
<p>“What is the most efficient way to effectively evaluate the untested code?”</p>
</blockquote>
<p>As I wrote last week, code coverage is not about the number. Code coverage is about analyzing the results and potentially designing additional functional tests, or at least being able to explain why areas of the code are untested. If we determine that it is important for our business to better understand the untested code, or improve overall confidence and reduce potential risk then we should use a tool to measure code coverage. But, again it is not about simply measuring code coverage and reporting some magical metric.</p>
<p>Code coverage analysis is the most efficient method to help testers evaluate untested code. Code coverage analysis basically involves the tester reviewing untested code reported by the code coverage tool and determining why some code was not exercised, and possibly design additional tests to exercise the previously untested code. (Remember I also wrote last week the future of professional testing is about analyzing information and designing tests…so, here we go!)</p>
<h4><strong>Missing tests</strong></h4>
<p>For several years I’ve used the triangle simulation to help set a ‘test effectiveness’ baseline for new testers who had never been formally trained in different test techniques, patterns, or approaches. After a few years of analyzing the results we found that there was about a 70 to 75% probability of tests exercising true branch of the first conditional expression in a compound predicate statement in a key method in the program. There was about a 20 to 25% chance of tests exercising the true branch of the second conditional expression, and there was less than a 10% probability of tests exercising the third conditional expression in the predicate statement. When I found these results I could hardly believe it, so I changed the third conditional expression to inject a bug and sure enough the results held true; in any class of 20 people on average only 1 or 2 people found the bug in the software.</p>
<p>From a black box approach let’s say our tests used the following values for sides A, B, and C respectively:</p>
<ol>
<li>1, 2, 3 – an error message indicating the values would not produce a triangle </li>
<li>2, 1, 3 – an error message indicating the values would not produce a triangle </li>
<li>4, 5, 6 – scalene triangle </li>
<li>2, 1, 2 – isosceles triangle </li>
<li>5, 5, 5 – equilateral triangle </li>
</ol>
<p>In this case our code coverage tool would report our coverage is less than 100%. As we drill down we see that the IsValidTriangle() method illustrated below is not completely covered. So, (assuming the arguments values passed to the parameters in this method are all validated to be greater than 0) we analyze the code below in our coverage tool and realize that we need a test to evaluate the third conditional expression to true (e.g. 1, 3, 2 for sides A, B, and C respectively). </p>
<div>
<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: #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="lnum1">   1:</span> <span style="color: #0000ff">internal</span> <span style="color: #0000ff">bool</span> IsValidTriangle(<span style="color: #0000ff">int</span> sideA, <span style="color: #0000ff">int</span> sideB, <span style="color: #0000ff">int</span> sideC)</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: #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="lnum3">   3:</span>   <span style="color: #0000ff">bool</span> result = <span style="color: #0000ff">true</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="lnum4">   4:</span>   <span style="color: #0000ff">if</span> ((sideA + sideB &lt;= sideC) || (sideB + sideC &lt;= sideA) || (sideA + sideC &lt;= sideB))</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="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>     result = <span style="color: #0000ff">false</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="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>&#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="lnum9">   9:</span>   <span style="color: #0000ff">return</span> result;</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--></div>
</div>
<div>This is a simple example, and things aren’t always so easy in the ‘real-world.’ So, let’s look at something a bit more complicated. In this example, we are testing a game (Frogger) and discover that we called the MoveFrogLeft function, but we didn’t evaluate the conditional expression in line 499 to its false outcome as illustrated below by the red arrow and blue ‘T’.</div>
<div>&#160;</div>
<div><a href="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image1.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image_thumb1.png" width="606" height="227" /></a></div>
<div>&#160;</div>
<div>For this we must find where the frogExists variable is set to true (or 1). So, we search the code for the frogExists variable and soon find the FrogStart() function where the frogExists variable is set to 1. </div>
<div>&#160;</div>
<div><a href="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image2.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image_thumb2.png" width="772" height="276" /></a> </div>
<div>Now we must find when the FrogStart() function is called and we find the following case statement that basically deals with sending windows messages from the window menu (WM_COMMAND msg). In this example, when we start the game and click the Start menu item (IDM_START) the StartWorkers() and FrogStart() functions are called.</div>
<div>&#160;</div>
<div><a href="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image3.png"><img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="image" border="0" alt="image" src="http://testingmentor.com/imtesty/wp-content/uploads/2010/08/image_thumb3.png" width="466" height="147" /></a> </div>
<div>So, now we need to put the puzzle pieces together and design a test that will make the conditional expression in line 499 to evaluate false. In this case the test will be to launch the game, then press the left arrow key before clicking the game’s Start menu item. </div>
<div>&#160;</div>
<div>These are rather simple examples, but should serve to illustrate how we can use code coverage tools and analyze the results to help us design additional tests from a white box test design approach to identify additional tests to increase control flow (code) coverage and improve functional testing effectiveness. </div>
<div>&#160;</div>
<div>Next week I will discuss unreachable code.</div>
]]></content:encoded>
			<wfw:commentRss>http://www.testingmentor.com/imtesty/2010/08/22/code-coverage-finding-missing-tests/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Code Coverage: Did we run the right tests?</title>
		<link>http://www.testingmentor.com/imtesty/2010/08/09/code-coverage-did-we-run-the-right-tests/</link>
		<comments>http://www.testingmentor.com/imtesty/2010/08/09/code-coverage-did-we-run-the-right-tests/#comments</comments>
		<pubDate>Mon, 09 Aug 2010 20:14:42 +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[White Box Testing]]></category>

		<guid isPermaLink="false">http://www.testingmentor.com/imtesty/2010/08/09/code-coverage-did-we-run-the-right-tests/</guid>
		<description><![CDATA[It has been awhile since my last post, and I apologize for the few folks who follow my rants. Over the last few months I have been busy working on my boat (she is almost 30 years old now and needs some major refitting). Since starting to play hockey again I have been spending a [...]]]></description>
			<content:encoded><![CDATA[<p>It has been awhile since my last post, and I apologize for the few folks who follow my rants. Over the last few months I have been busy working on my boat (she is almost 30 years old now and needs some major refitting). Since starting to play hockey again I have been spending a lot of time at the gym and on the ice and trying to keep my body from getting too battered in the games (for I too am older now…let’s just say more than 30). I have also done a bit of&#160; soul searching on the past year or so reflecting on the high points and the low points as well.</p>
<p>So, the refitting on the boat is almost complete and she is ready for a nice long trip to the Gulf Islands starting next week. The Monarch’s Div 7A team finished the regular summer hockey season in first place and playoffs are this week. Winter season doesn’t start until October so I have a month and a half to recuperate. And, I have contemplated a few things to help nurture my professional and personal growth that I will proactively begin working on…beginning with a vacation to the Gulf Islands next week.</p>
<p>But, for now I want to talk more about code coverage. Not the number! Forget the measure! The code coverage percentage is simply a magic metric for pointy-haired managers and other thoughtless chowderheads who like to wave it around as if it actually means something. Look…as a manager I really don’t give a rat’s butt about what percentage of coverage was achieved by testing. If you tell me that your testing achieved 80% code coverage I will probably say, “That’s great! Now tell me about the 20% of the code that you didn’t test!” As a manager what I want to know is:</p>
<ul>
<li>Did we run the right tests? Did the test suites we ran give us the information that we need to make good business decisions? </li>
<li>What is my potential exposure to risk in the areas of untested code and how do/can we reduce that risk?</li>
</ul>
<p>I have said for years now that the future of professional testing is not simply about beating on a product and finding bugs. The future of testing lies in our ability to design effective tests and critically analyze results in order to provide better information to our primary customers (the decision makers). Code coverage is about analyzing the results and potentially designing additional functional tests, or at least being able to explain why areas of the code are untested.</p>
<h4><strong>Did we run the right tests?</strong></h4>
<p>The code coverage metric simply measures the number of statements in the code have been exercised by monitoring control flow through the code. Control flow through code is sequential until it hits some type of branch such as an if statement, a for loop, or an exception. For example, when we call the CalculateMonthlyMortgage method below control flows sequentially from the statement in line 6 to the statement in lines 7 and 8 and finally to the return statement in line 9. </p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 0pt; 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: 8pt; 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="lnum1">   1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">double</span> CalculateMonthlyMortgage(</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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>   <span style="color: #0000ff">double</span> principle,</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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="lnum3">   3:</span>   <span style="color: #0000ff">double</span> annualInterest,</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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> months)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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="lnum5">   5:</span> {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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">double</span> monthlyInterest = (0.01 * annualInterest) / 12;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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="lnum7">   7:</span>   <span style="color: #0000ff">double</span> monthlyPayment = principle * monthlyInterest /</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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>     (1 - Math.Pow((1 + monthlyInterest), (-1) * months));</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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="lnum9">   9:</span>   <span style="color: #0000ff">return</span> monthlyPayment;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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--></div>
</div>
<p>So, by passing in a value of 250000 for the principle, 4.5 for the annual interest rate, and 360 for the months parameter the method would return an expected value of 1266.71327456471 and we would measure 100% coverage of this method. That’s a happy path test. Yes, it does what we think it is supposed to do. But, what happens when we pass in a value of 0 to the annualInterest parameter? Control flows through the method as described above giving us 100% code coverage, but the return value is NaN, or Not a Number. Similarly, if the value for the months parameter is 0 we get 100% code coverage and the return value is Infinity. Of course, negative values for any of the parameters would also produce undesirable output results.</p>
<p>This example illustrates sequential control flow through a method that contains simple statements. When branching conditions occur in software the control flow through the method becomes a bit more complicated as does the testing required. The following snippet counts the number of characters in a string. But, to prevent a null reference exception we use a predicate or conditional statement in line 4 that branches control flow from line 4 to line 12 if the input argument is null, and from line 4 to the loop structure starting in line 6 if the string is not null. If the input argument is an empty string control will flow from line 6 to line 10 bypassing the inner block that increments the count variable. But, if the input argument is a string of at least 1 character control flows from line 6 to line 8 and loops back to line 6 until all characters in the string are counted. (This previous <a href="http://www.testingmentor.com/imtesty/2009/11/25/reconsidering-code-coverage/" target="_blank">post</a> shows how you can create a model or control flow graph to map control flow through an algorithm.)</p>
<div id="codeSnippetWrapper">
<div style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 0pt; 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: 8pt; 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="lnum1">   1:</span> <span style="color: #0000ff">public</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">int</span> CharacterCounter(<span style="color: #0000ff">string</span> input)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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: 8pt; 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="lnum3">   3:</span>   <span style="color: #0000ff">int</span> count = 0;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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> (input != <span style="color: #0000ff">null</span>)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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="lnum5">   5:</span>   {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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">foreach</span> (<span style="color: #0000ff">char</span> c <span style="color: #0000ff">in</span> input)</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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="lnum7">   7:</span>     {</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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>       count++;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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="lnum9">   9:</span>     }</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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: 8pt; 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="lnum11">  11:</span>&#160; </pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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">return</span> count;</pre>
<p><!--CRLF--></p>
<pre style="border-bottom-style: none; text-align: left; padding-bottom: 0px; line-height: 8pt; 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="lnum13">  13:</span> }      </pre>
<p><!--CRLF--></div>
</div>
<div>&#160;</div>
<div>With 3 tests (null, empty string, and a string of at least 1 character) we can achieve 100% code coverage of this method. However, there are still 2 basic problems. The first problem is that a null and an empty string both produce an output of 0. This may be desired output, but not in all cases. Secondly, if the input argument is the string “ꇔㄣᦅrえꞄ௏Жᾁ” the return value will be 11 instead of the expected 10. This is because the last character in the string is actually a Unicode surrogate-pair character composed of 2 UTF-16 code points. (Assuming that 1 character glyph is 1 byte or one UTF-16 encoded code point value is a common mistake in string parsing.)</div>
<p>These are just 2 simple examples designed to illustrate how we can get high levels of code coverage yet still have bugs lurking in our software. Code coverage tools tell us whether we exercised code; it doesn’t tell us if we ran the right set of tests to expose potential issues. </p>
<p>Next week let’s continue this with some thoughts on analyzing code coverage results to help reduce risk.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.testingmentor.com/imtesty/2010/08/09/code-coverage-did-we-run-the-right-tests/feed/</wfw:commentRss>
		<slash:comments>4</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 [...]]]></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>Do Testers Do Code Reviews?</title>
		<link>http://www.testingmentor.com/imtesty/2009/11/18/do-testers-do-code-reviews/</link>
		<comments>http://www.testingmentor.com/imtesty/2009/11/18/do-testers-do-code-reviews/#comments</comments>
		<pubDate>Thu, 19 Nov 2009 02:17:10 +0000</pubDate>
		<dc:creator>Bj Rollison</dc:creator>
				<category><![CDATA[Testing Practices]]></category>
		<category><![CDATA[White Box Testing]]></category>

		<guid isPermaLink="false">http://testingmentor.com/imtesty/2009/11/18/do-testers-do-code-reviews/</guid>
		<description><![CDATA[Originally Published Tuesday, March 11, 2008 This weekend on the flight from Seattle to Ireland I finally got to catch up on some reading. One of the books I grabbed off the shelf that I hadn&#8217;t gotten around to reading yet was Best Kept Secrets of Peer Code Review by Jason Cohen. The book is [...]]]></description>
			<content:encoded><![CDATA[<p>Originally Published Tuesday, March 11, 2008</p>
<p>This weekend on the flight from Seattle to Ireland I finally got to catch up on some reading. One of the books I grabbed off the shelf that I hadn&#8217;t gotten around to reading yet was <em>Best Kept Secrets of Peer Code Review</em> by Jason Cohen. The book is 160 pages packed with great information, and I highly recommend it for some fresh perspectives of the value or ideas on improving code reviews. For decades the industry collected mounds of empirical data that pretty clearly illustrates the value of code reviews in a software development lifecycle in the early detection and removal of issues and anomalies. With the industry wide push to drive quality upstream via approaches such as agile programming and test driven development there is a resurgence of effort by developers to engage in more frequent code reviews.</p>
<p>Many people seem assume the primary reason why Microsoft (and other companies) is recruiting more technically skills testers is simply to automate tests. But, in fact, many testers at the company engaged in writing test automation long before our efforts towards engineering excellence. The skills and knowledge that people who have a much deeper understanding of the &#8216;system&#8217; bring to an organization extends well beyond their ability to write automation. </p>
<p>But, should testers be performing code reviews? In my opinion, code reviews are simply another approach in a myriad of approaches to testing a software project, and professional testers should be able to engage the testing effort from a variety of testing perspectives.</p>
<p>Testers who participate in project code reviews are part of the <strong><em>team effort</em></strong> to drive quality upstream, reduce certain classes of issues before they are checked into the build, improve overall long-term maintainability of the code base, and effectively reduce long term costs. Just as testers participate in the early stages of the design and requirements phase of a project to provide valuable input, some testers on every team should engage in code reviews either with other developers, or perhaps as the primary reviewers of project code. Some people will argue that testers may be biased by participating in code reviews and lose the &#8216;customer&#8217; perspective. This may be true in some cases, but I suspect that most professional testers clearly understand the different classes of issues that are more easily found in a code review versus other approaches of testing. But, testers who engage in code reviews tend to have a much deeper understanding of the overall project, and they are also able to identify potential areas of the code that may be more problematic and focus additional testing approaches in those areas.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.testingmentor.com/imtesty/2009/11/18/do-testers-do-code-reviews/feed/</wfw:commentRss>
		<slash:comments>1</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>

