<?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>进化的测试 &#187; 单元测试</title>
	<atom:link href="http://magustest.com/blog/tag/%e5%8d%95%e5%85%83%e6%b5%8b%e8%af%95/feed/" rel="self" type="application/rss+xml" />
	<link>http://magustest.com/blog</link>
	<description>关注软件测试，白盒测试，自动化测试，性能测试</description>
	<lastBuildDate>Wed, 02 Jun 2010 16:12:11 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>单元测试中的异常处理</title>
		<link>http://magustest.com/blog/whiteboxtesting/exception-handling-in-unit-test/</link>
		<comments>http://magustest.com/blog/whiteboxtesting/exception-handling-in-unit-test/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 02:21:42 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[白盒测试]]></category>
		<category><![CDATA[软件测试]]></category>
		<category><![CDATA[单元测试]]></category>
		<category><![CDATA[自动化测试]]></category>
		<category><![CDATA[集成测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=398</guid>
		<description><![CDATA[最近项目不是十分多，所以大部分的学习来自于书本还有同行的博客，淘宝的QA Team博客就是一个很好博客，里面N多淘宝的工程师写，而且更新的非常频繁，质量也很好。翠翠同学以后就要加入淘宝了，以后就能看到他写的博客了。 早上来看到一篇文章，大概讲的是在单元测试中容易用到了Try&#8230;Catch语句而容易出现的一个错误，这里想说一下我对单元测试中异常处理的。记得一个牛人曾经说过（实在想不起来谁也搜不到），大概的意思就是“处理一个问题的最好的办法就是不去处理它”。我不知道当时他讲这句话的具体场景是什么，不过我觉得这句话用在单元测试的异常处理中还是比较合适的。 首先来看看两条关于异常处理的原则 如果无法处理某个异常，那么就不要捕获它 如果捕获到一个异常，那么不要胡乱处理它 单元测试的代码和开发的生产代码，虽然同是程序代码，但是他们存在的意义是不一样的。前者是验证程序的正确性，属于为程序服务的；后者是实现某种功能，属于为客户服务的。然后在看上面的两条异常处理的原则。 作为测试代码，如果捕获到一个异常，其实是无法处理它的。从某种角度来看，测试代码和被测代码是不在一个系统中，AUT所抛出的异常，测试代码无法处理，其实也无需处理。 假如测试代码捕获了一个异常，那么唯一能做的事情就是把这个异常重新包装一下，或者直接重新抛出给单元测试框架，然后由单元测试框架打印到界面上或者是执行结果中。但是其实我们什么都不做（不用Try&#8230;Catch）也能达到这样的效果。 可能会有这样的一些测试用例：在输入某些数据的情况下，该函数会抛出某异常。测试工程师就是要验证有异常的抛出。如果是这样的情况，可以用ExpectedException的Attribute（.NET）来标识出该测试代码必须要抛出该异常，如果没有抛出，该测试就是失败。 所以在单元测试的代码中出现Try&#8230;Catch其实是没有必要的，如果是真的觉得要使用Try&#8230;Catch才能完成某些用例，那么我觉得可以重新设计测试用例，或者测试用例的实现。Try&#8230;Catch增加了测试代码的不确定性，而这样的不确定性会导致诡异的自动化测试脚本的出现。在回归测试的过程中就有可能出现运行10次测试，有2次失败8次成功的情况。 不过在单元测试（集成测试）中Try&#8230;Finally语句的使用还是很有必要的，例如我们会把数据库链接释放的代码放在Finally语句块中，保证测试运行无论成功还是失败，都能释放数据库链接，或者其他昂贵的系统资源。 总结：在单元测试（集成测试等……）中，尽量不要使用Try&#8230;Catch代码块；如果需要释放昂贵或者有限的系统资源、做清理工作，可以把相关的代码放在Finally代码块中。 参考资料： 异常处理 &#8211; MSDN 异常处理原则 理解.NET中的异常 单元测试之新手最容易犯的错误 Share and Enjoy: Related posts:自动化单元测试要点


Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/unit-test-and-integration-test/' rel='bookmark' title='Permanent Link: 自动化单元测试要点'>自动化单元测试要点</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>最近项目不是十分多，所以大部分的学习来自于书本还有同行的博客，<a href="http://rdc.taobao.com/blog/qa/" target="_blank">淘宝的QA Team博客</a>就是一个很好博客，里面N多淘宝的工程师写，而且更新的非常频繁，质量也很好。翠翠同学以后就要加入淘宝了，以后就能看到他写的博客了。</p>
<p>早上来看到一篇文章，大概讲的是在单元测试中容易用到了Try&#8230;Catch语句而容易出现的一个错误，这里想说一下我对单元测试中异常处理的。记得一个牛人曾经说过（实在想不起来谁也搜不到），大概的意思就是“<strong>处理一个问题的最好的办法就是不去处理它</strong>”。我不知道当时他讲这句话的具体场景是什么，不过我觉得这句话用在单元测试的异常处理中还是比较合适的。</p>
<p>首先来看看两条关于异常处理的原则</p>
<ul>
<li>如果无法处理某个异常，那么就不要捕获它</li>
<li>如果捕获到一个异常，那么不要胡乱处理它</li>
</ul>
<p>单元测试的代码和开发的生产代码，虽然同是程序代码，但是他们存在的意义是不一样的。前者是验证程序的正确性，属于为程序服务的；后者是实现某种功能，属于为客户服务的。然后在看上面的两条异常处理的原则。<br />
<span id="more-398"></span></p>
<ul>
<li> 作为测试代码，如果捕获到一个异常，其实是无法处理它的。从某种角度来看，测试代码和被测代码是不在一个系统中，AUT所抛出的异常，测试代码无法处理，其实也无需处理。</li>
<li>假如测试代码捕获了一个异常，那么唯一能做的事情就是把这个异常重新包装一下，或者直接重新抛出给单元测试框架，然后由单元测试框架打印到界面上或者是执行结果中。但是其实我们什么都不做（不用Try&#8230;Catch）也能达到这样的效果。</li>
</ul>
<p>可能会有这样的一些测试用例：在输入某些数据的情况下，该函数会抛出某异常。测试工程师就是要验证有异常的抛出。如果是这样的情况，可以用ExpectedException的Attribute（.NET）来标识出该测试代码必须要抛出该异常，如果没有抛出，该测试就是失败。</p>
<p>所以在单元测试的代码中出现Try&#8230;Catch其实是没有必要的，如果是真的觉得要使用Try&#8230;Catch才能完成某些用例，那么我觉得可以重新设计测试用例，或者测试用例的实现。Try&#8230;Catch增加了测试代码的不确定性，而这样的不确定性会导致<a href="http://magustest.com/blog/softwaretesting/automationtesting/avoid-flakey-automation-test/" target="_blank">诡异的自动化测试脚本</a>的出现。在回归测试的过程中就有可能出现运行10次测试，有2次失败8次成功的情况。</p>
<p>不过在单元测试（集成测试）中Try&#8230;Finally语句的使用还是很有必要的，例如我们会把数据库链接释放的代码放在Finally语句块中，保证测试运行无论成功还是失败，都能释放数据库链接，或者其他昂贵的系统资源。</p>
<p>总结：在单元测试（集成测试等……）中，尽量不要使用Try&#8230;Catch代码块；如果需要释放昂贵或者有限的系统资源、做清理工作，可以把相关的代码放在Finally代码块中。</p>
<p><strong>参考资料：</strong></p>
<p><a href="http://msdn.microsoft.com/zh-cn/library/ms229005.aspx" target="_blank">异常处理 &#8211; MSDN</a></p>
<p><a href="http://www.blogjava.net/usherlight/archive/2006/10/23/76782.html" target="_blank">异常处理原则</a></p>
<p><a href="http://www.cnblogs.com/anderslly/archive/2007/03/15/675642.html" target="_blank">理解.NET中的异常</a></p>
<p><a href="http://rdc.taobao.com/blog/qa/?p=1317" target="_blank">单元测试之新手最容易犯的错误</a></p>



Share and Enjoy:


	<a rel="nofollow"  target="_blank" href="http://magustest.com/blog/feed/" title="RSS"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/rss.png" title="RSS" alt="RSS" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fexception-handling-in-unit-test%2F&amp;t=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86" title="Facebook"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fexception-handling-in-unit-test%2F&title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86" title="豆瓣"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban.png" title="豆瓣" alt="豆瓣" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fexception-handling-in-unit-test%2F&title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86&n=1" title="豆瓣九点"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban9.png" title="豆瓣九点" alt="豆瓣九点" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.friendfeed.com/share?title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86&amp;link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fexception-handling-in-unit-test%2F" title="FriendFeed"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fexception-handling-in-unit-test%2F&amp;title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86" title="Live"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/live.png" title="Live" alt="Live" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://ping.fm/ref/?link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fexception-handling-in-unit-test%2F&amp;title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86&amp;body=%E6%9C%80%E8%BF%91%E9%A1%B9%E7%9B%AE%E4%B8%8D%E6%98%AF%E5%8D%81%E5%88%86%E5%A4%9A%EF%BC%8C%E6%89%80%E4%BB%A5%E5%A4%A7%E9%83%A8%E5%88%86%E7%9A%84%E5%AD%A6%E4%B9%A0%E6%9D%A5%E8%87%AA%E4%BA%8E%E4%B9%A6%E6%9C%AC%E8%BF%98%E6%9C%89%E5%90%8C%E8%A1%8C%E7%9A%84%E5%8D%9A%E5%AE%A2%EF%BC%8C%E6%B7%98%E5%AE%9D%E7%9A%84QA%20Team%E5%8D%9A%E5%AE%A2%E5%B0%B1%E6%98%AF%E4%B8%80%E4%B8%AA%E5%BE%88%E5%A5%BD%E5%8D%9A%E5%AE%A2%EF%BC%8C%E9%87%8C%E9%9D%A2N%E5%A4%9A%E6%B7%98%E5%AE%9D%E7%9A%84%E5%B7%A5%E7%A8%8B%E5%B8%88%E5%86%99%EF%BC%8C%E8%80%8C%E4%B8%94%E6%9B%B4%E6%96%B0%E7%9A%84%E9%9D%9E%E5%B8%B8%E9%A2%91%E7%B9%81%EF%BC%8C%E8%B4%A8%E9%87%8F%E4%B9%9F%E5%BE%88%E5%A5%BD%E3%80%82%E7%BF%A0%E7%BF%A0%E5%90%8C%E5%AD%A6%E4%BB%A5%E5%90%8E%E5%B0%B1%E8%A6%81%E5%8A" title="Ping.fm"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/ping.png" title="Ping.fm" alt="Ping.fm" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://shuqian.qq.com/post?jumpback=1&title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86&uri=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fexception-handling-in-unit-test%2F" title="QQ书签"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/qq.png" title="QQ书签" alt="QQ书签" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86%20-%20http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fexception-handling-in-unit-test%2F" title="Twitter"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>

<p>Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/unit-test-and-integration-test/' rel='bookmark' title='Permanent Link: 自动化单元测试要点'>自动化单元测试要点</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/whiteboxtesting/exception-handling-in-unit-test/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>测试代码重构实例</title>
		<link>http://magustest.com/blog/whiteboxtesting/refactoring-unit-test/</link>
		<comments>http://magustest.com/blog/whiteboxtesting/refactoring-unit-test/#comments</comments>
		<pubDate>Sat, 21 Mar 2009 11:17:35 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[白盒测试]]></category>
		<category><![CDATA[单元测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=383</guid>
		<description><![CDATA[Martin Fowler的《重构》这本书基本上每个程序员都会看，对于做单元测试的测试工程师来说，测试的代码本身也是程序，也需要重构。最近在看《XUnit Test Patterns》，把以前的做的东西重新梳理了一下，并且落实到新的项目中。 首先来看看一个最原始的单元测试代码： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 &#91;TestMethod&#93; public void GetPaymentAccountByOwnerID&#40;&#41; &#123; int ownerId = 1300100000; //Delete the account TestHelper.DeletePaymentAccountByOwnerId&#40;ownerId&#41;; &#160; //Here should be create an account PaymentAccount paymentAccount = PaymentGateway.PaymentProvider.GetPaymentAccountByOwnerID&#40;ownerId, AccountOwnerType.NormalUser&#41;; &#160; //Verify the payment account instance Assert.IsTrue&#40;paymentAccount.AccountID [...]


Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/unit-test-pattern/' rel='bookmark' title='Permanent Link: 单元测试中的常用测试模式'>单元测试中的常用测试模式</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/beginning-nmock/' rel='bookmark' title='Permanent Link: NMock2入门经验'>NMock2入门经验</a></li>
<li><a href='http://magustest.com/blog/automationtesting/data-driven-codedui-test/' rel='bookmark' title='Permanent Link: 实现数据驱动的CodedUI Test'>实现数据驱动的CodedUI Test</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Martin Fowler的<a href="http://www.china-pub.com/12901">《重构》</a>这本书基本上每个程序员都会看，对于做单元测试的测试工程师来说，测试的代码本身也是程序，也需要重构。最近在看<a href="http://xunitpatterns.com/">《XUnit Test Patterns》</a>，把以前的做的东西重新梳理了一下，并且落实到新的项目中。</p>
<p>首先来看看一个最原始的单元测试代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestMethod<span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> GetPaymentAccountByOwnerID<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #FF0000;">int</span> ownerId <span style="color: #008000;">=</span> <span style="color: #FF0000;">1300100000</span><span style="color: #008000;">;</span>
	<span style="color: #008080; font-style: italic;">//Delete the account</span>
	TestHelper.<span style="color: #0000FF;">DeletePaymentAccountByOwnerId</span><span style="color: #000000;">&#40;</span>ownerId<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #008080; font-style: italic;">//Here should be create an account</span>
	PaymentAccount paymentAccount <span style="color: #008000;">=</span> PaymentGateway.<span style="color: #0000FF;">PaymentProvider</span>.<span style="color: #0000FF;">GetPaymentAccountByOwnerID</span><span style="color: #000000;">&#40;</span>ownerId, AccountOwnerType.<span style="color: #0000FF;">NormalUser</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #008080; font-style: italic;">//Verify the payment account instance</span>
	Assert.<span style="color: #0000FF;">IsTrue</span><span style="color: #000000;">&#40;</span>paymentAccount.<span style="color: #0000FF;">AccountID</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>DateTime.<span style="color: #0000FF;">Now</span>.<span style="color: #0000FF;">DayOfYear</span>, paymentAccount.<span style="color: #0000FF;">CreateTime</span>.<span style="color: #0000FF;">DayOfYear</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>DateTime.<span style="color: #0000FF;">Now</span>.<span style="color: #0000FF;">DayOfYear</span>, paymentAccount.<span style="color: #0000FF;">UpdateTime</span>.<span style="color: #0000FF;">DayOfYear</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">0</span>, paymentAccount.<span style="color: #0000FF;">Balance</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">0</span>, paymentAccount.<span style="color: #0000FF;">AvailableBalance</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">0</span>, paymentAccount.<span style="color: #0000FF;">FreezeAccount</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>以上是个很简单的单元测试代码，应用了AAA原则，首先做好准备（删掉原有的数据），然后执行测试，最后再验证返回结果。看起来很好也很清晰。首先发现一个问题，就是那一堆Assert让人觉得迷惑，究竟想干啥？其实那6句Assert都是验证程序返回的PaymentAccount对象是是否符合设计。我把这些Assert语句提取出来，作为一个方法，让测试代码更加容易让人明白。也就有了版本2。<br />
<span id="more-383"></span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestMethod<span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> GetPaymentAccountByOwnerID<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #FF0000;">int</span> ownerId <span style="color: #008000;">=</span> <span style="color: #FF0000;">1300100000</span><span style="color: #008000;">;</span>
	<span style="color: #008080; font-style: italic;">//Delete the account</span>
	TestHelper.<span style="color: #0000FF;">DeletePaymentAccountByOwnerId</span><span style="color: #000000;">&#40;</span>ownerId<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #008080; font-style: italic;">//Here should be create an account</span>
	PaymentAccount paymentAccount <span style="color: #008000;">=</span> PaymentGateway.<span style="color: #0000FF;">PaymentProvider</span>.<span style="color: #0000FF;">GetPaymentAccountByOwnerID</span><span style="color: #000000;">&#40;</span>ownerId, AccountOwnerType.<span style="color: #0000FF;">NormalUser</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #008080; font-style: italic;">//Verify the payment account instance</span>
	PaymentAccountAssertion<span style="color: #000000;">&#40;</span>paymentAccount<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> PaymentAccountAssertion<span style="color: #000000;">&#40;</span>PaymentAccount paymentAccount<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	Assert.<span style="color: #0000FF;">IsTrue</span><span style="color: #000000;">&#40;</span>paymentAccount.<span style="color: #0000FF;">AccountID</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>DateTime.<span style="color: #0000FF;">Now</span>.<span style="color: #0000FF;">DayOfYear</span>, paymentAccount.<span style="color: #0000FF;">CreateTime</span>.<span style="color: #0000FF;">DayOfYear</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>DateTime.<span style="color: #0000FF;">Now</span>.<span style="color: #0000FF;">DayOfYear</span>, paymentAccount.<span style="color: #0000FF;">UpdateTime</span>.<span style="color: #0000FF;">DayOfYear</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">0</span>, paymentAccount.<span style="color: #0000FF;">Balance</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">0</span>, paymentAccount.<span style="color: #0000FF;">AvailableBalance</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">0</span>, paymentAccount.<span style="color: #0000FF;">FreezeAccount</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>以上代码看起来就舒服多了，比较清晰、简短。但是有一个问题，就是后面的3条Assert语句的期望结果是Hard code的，这样很不利于这个自定义的Assert方法的重用。改！我会把那3个〇抽取成这个方法的一个参数，这个自定义的Assert方法变得更加灵活了。代码不贴上来了，因为有一个问题，就是如果我们还需要对PaymentAccount增加一些属性，而这些属性的值都需要被验证，那么这个PaymentAccountAssertion方法的参数就会越来越长。超长的方法参数也是一个不好的味道，我改！改为传递一个期望的PaymentAccount对象进来，这样就是两个参数了，很好。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestMethod<span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> GetPaymentAccountByOwnerID<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #FF0000;">int</span> ownerId <span style="color: #008000;">=</span> <span style="color: #FF0000;">1300100000</span><span style="color: #008000;">;</span>
	<span style="color: #008080; font-style: italic;">//Delete the account</span>
	TestHelper.<span style="color: #0000FF;">DeletePaymentAccountByOwnerId</span><span style="color: #000000;">&#40;</span>ownerId<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #008080; font-style: italic;">//Here should be create an account</span>
	PaymentAccount paymentAccount <span style="color: #008000;">=</span> PaymentGateway.<span style="color: #0000FF;">PaymentProvider</span>.<span style="color: #0000FF;">GetPaymentAccountByOwnerID</span><span style="color: #000000;">&#40;</span>ownerId, AccountOwnerType.<span style="color: #0000FF;">NormalUser</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #008080; font-style: italic;">//Verify the payment account instance</span>
	PaymentAccount expected <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> PaymentAccount<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	PaymentAccountAssertion<span style="color: #000000;">&#40;</span>expected, paymentAccount<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> PaymentAccountAssertion<span style="color: #000000;">&#40;</span>PaymentAccount expectedObject, PaymentAccount paymentAccount<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	Assert.<span style="color: #0000FF;">IsTrue</span><span style="color: #000000;">&#40;</span>paymentAccount.<span style="color: #0000FF;">AccountID</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>DateTime.<span style="color: #0000FF;">Now</span>.<span style="color: #0000FF;">DayOfYear</span>, paymentAccount.<span style="color: #0000FF;">CreateTime</span>.<span style="color: #0000FF;">DayOfYear</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>DateTime.<span style="color: #0000FF;">Now</span>.<span style="color: #0000FF;">DayOfYear</span>, paymentAccount.<span style="color: #0000FF;">UpdateTime</span>.<span style="color: #0000FF;">DayOfYear</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>expectedObject.<span style="color: #0000FF;">Balance</span>, paymentAccount.<span style="color: #0000FF;">Balance</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>expectedObject.<span style="color: #0000FF;">AvailableBalance</span>, paymentAccount.<span style="color: #0000FF;">AvailableBalance</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>expectedObject.<span style="color: #0000FF;">FreezeAccount</span>, paymentAccount.<span style="color: #0000FF;">FreezeAccount</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>第三版出来了，这时候我想起淘宝QA TEAM的一篇文章，我想到用反射去做一个简单的比较，而不用对于每个属性都做对比。（但是我犯了一个错误，我只是“想到”，问没有去重新看一次那篇文章，我写的那个方法有缺点！）</p>
<p>先看看用反射比较属性方法的代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> ObjectAreEqual<span style="color: #008000;">&lt;</span>t<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>T expected, T actual, List<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span> excludedProperties<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #000000;">System</span>.<span style="color: #0000FF;">Type</span> myType <span style="color: #008000;">=</span> <span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>T<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	PropertyInfo<span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> props <span style="color: #008000;">=</span> myType.<span style="color: #0000FF;">GetProperties</span><span style="color: #000000;">&#40;</span>BindingFlags.<span style="color: #0600FF;">Public</span> <span style="color: #008000;">|</span> BindingFlags.<span style="color: #0000FF;">Instance</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var item <span style="color: #0600FF;">in</span> props<span style="color: #000000;">&#41;</span>
	<span style="color: #000000;">&#123;</span>
		<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #0600FF;">null</span> <span style="color: #008000;">==</span> excludedProperties <span style="color: #008000;">||</span> <span style="color: #008000;">!</span>excludedProperties.<span style="color: #0000FF;">Contains</span><span style="color: #000000;">&#40;</span>item.<span style="color: #0000FF;">Name</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
		<span style="color: #000000;">&#123;</span>
			<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>item.<span style="color: #0000FF;">PropertyType</span>.<span style="color: #0000FF;">Equals</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">double</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
			<span style="color: #000000;">&#123;</span>
				Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">double</span><span style="color: #000000;">&#41;</span>item.<span style="color: #0000FF;">GetValue</span><span style="color: #000000;">&#40;</span>expected, <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>, <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">double</span><span style="color: #000000;">&#41;</span>item.<span style="color: #0000FF;">GetValue</span><span style="color: #000000;">&#40;</span>actual, <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
			<span style="color: #000000;">&#125;</span>
			<span style="color: #0600FF;">else</span> <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>item.<span style="color: #0000FF;">PropertyType</span>.<span style="color: #0000FF;">Equals</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">float</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
			<span style="color: #000000;">&#123;</span>
				Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">float</span><span style="color: #000000;">&#41;</span>item.<span style="color: #0000FF;">GetValue</span><span style="color: #000000;">&#40;</span>expected, <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>, <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">float</span><span style="color: #000000;">&#41;</span>item.<span style="color: #0000FF;">GetValue</span><span style="color: #000000;">&#40;</span>actual, <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
			<span style="color: #000000;">&#125;</span>
			<span style="color: #0600FF;">else</span>
			<span style="color: #000000;">&#123;</span>
				Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>item.<span style="color: #0000FF;">GetValue</span><span style="color: #000000;">&#40;</span>expected, <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>, item.<span style="color: #0000FF;">GetValue</span><span style="color: #000000;">&#40;</span>actual, <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
			<span style="color: #000000;">&#125;</span>
		<span style="color: #000000;">&#125;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span><span style="color: #008000;">&lt;/</span><span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;&lt;/</span>t<span style="color: #008000;">&gt;</span></pre></td></tr></table></div>

<p>比较简单，就是获取所有的Property，然后做Assert，特别针对了double和float做了处理，因为对于浮点数，Assert.AreEqual方法需要指定一个可接受的误差值。excludedProperties这个列表保存了不需要验证的属性名字。整个测试代码如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestMethod<span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> GetPaymentAccountByOwnerID<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #FF0000;">int</span> ownerId <span style="color: #008000;">=</span> <span style="color: #FF0000;">1300100000</span><span style="color: #008000;">;</span>
	<span style="color: #008080; font-style: italic;">//Delete the account</span>
	TestHelper.<span style="color: #0000FF;">DeletePaymentAccountByOwnerId</span><span style="color: #000000;">&#40;</span>ownerId<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #008080; font-style: italic;">//Here should be create an account</span>
	PaymentAccount paymentAccount <span style="color: #008000;">=</span> PaymentGateway.<span style="color: #0000FF;">PaymentProvider</span>.<span style="color: #0000FF;">GetPaymentAccountByOwnerID</span><span style="color: #000000;">&#40;</span>ownerId, AccountOwnerType.<span style="color: #0000FF;">NormalUser</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #008080; font-style: italic;">//Verify the payment account instance</span>
	PaymentAccount expected <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> PaymentAccount<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	PaymentAccountAssertion<span style="color: #000000;">&#40;</span>expected, paymentAccount<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0600FF;">private</span> <span style="color: #0600FF;">void</span> PaymentAccountAssertion<span style="color: #000000;">&#40;</span>PaymentAccount expectedObject, PaymentAccount paymentAccount<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	Assert.<span style="color: #0000FF;">IsTrue</span><span style="color: #000000;">&#40;</span>paymentAccount.<span style="color: #0000FF;">AccountID</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>DateTime.<span style="color: #0000FF;">Now</span>.<span style="color: #0000FF;">DayOfYear</span>, paymentAccount.<span style="color: #0000FF;">CreateTime</span>.<span style="color: #0000FF;">DayOfYear</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>DateTime.<span style="color: #0000FF;">Now</span>.<span style="color: #0000FF;">DayOfYear</span>, paymentAccount.<span style="color: #0000FF;">UpdateTime</span>.<span style="color: #0000FF;">DayOfYear</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
	List<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span> ExcludedProperties <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> List<span style="color: #008000;">&lt;/</span><span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;&lt;</span><span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span> <span style="color: #000000;">&#123;</span> <span style="color: #666666;">&quot;AccountID&quot;</span>, <span style="color: #666666;">&quot;CreateTime&quot;</span>, <span style="color: #666666;">&quot;UpdateTime&quot;</span> <span style="color: #000000;">&#125;</span><span style="color: #008000;">;</span>
&nbsp;
	TestUtilityGateway.<span style="color: #0000FF;">CustomizedAssert</span>.<span style="color: #0000FF;">ObjectAreEqual</span><span style="color: #008000;">&lt;</span>paymentaccount<span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>expectedObject, paymentAccount, ExcludedProperties<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span><span style="color: #008000;">&lt;/</span>paymentaccount<span style="color: #008000;">&gt;&lt;/</span><span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span></pre></td></tr></table></div>

<p>下来说说问题：<br />
1. ObjectAreEqual这个方法的最后一个参数不好，那个ExcludedProperties的列表，其实是我懒惰的产物，应该参照 子排牛柳 的设计方法，把需要比较的属性名传递进去。我当初的想法是，那个自定义Assert方法里面的前3条语句已经验证了我那3个属性了，然后我传个参数进去告诉那个方法“你不要验证这3个属性了”。懒惰啊！这样的设计有个问题，我用个比喻吧，我让我女朋友下楼去超市帮我买点东西，我是应该告诉她，“你帮我买ABCDE”呢？还是应该说“你别给我买FGHIJK&#8230;”呢？</p>
<p>2. if (null == excludedProperties || !excludedProperties.Contains(item.Name)) 这句话写的真别扭！也不好！</p>
<p>可以看到这个简单的测试方法的进化，经过了若干个版本，测试方法的可读性，可维护性变好了；而且还写了一个对比两个对象的属性是否一致的公共方法，以后可以重用。测试代码本身也是程序，也需要被重构。</p>



Share and Enjoy:


	<a rel="nofollow"  target="_blank" href="http://magustest.com/blog/feed/" title="RSS"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/rss.png" title="RSS" alt="RSS" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.google.com/bookmarks/mark?op=edit&amp;bkmk=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Frefactoring-unit-test%2F&amp;title=%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%E9%87%8D%E6%9E%84%E5%AE%9E%E4%BE%8B&amp;annotation=Martin%20Fowler%E7%9A%84%E3%80%8A%E9%87%8D%E6%9E%84%E3%80%8B%E8%BF%99%E6%9C%AC%E4%B9%A6%E5%9F%BA%E6%9C%AC%E4%B8%8A%E6%AF%8F%E4%B8%AA%E7%A8%8B%E5%BA%8F%E5%91%98%E9%83%BD%E4%BC%9A%E7%9C%8B%EF%BC%8C%E5%AF%B9%E4%BA%8E%E5%81%9A%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%9A%84%E6%B5%8B%E8%AF%95%E5%B7%A5%E7%A8%8B%E5%B8%88%E6%9D%A5%E8%AF%B4%EF%BC%8C%E6%B5%8B%E8%AF%95%E7%9A%84%E4%BB%A3%E7%A0%81%E6%9C%AC%E8%BA%AB%E4%B9%9F%E6%98%AF%E7%A8%8B%E5%BA%8F%EF%BC%8C%E4%B9%9F%E9%9C%80%E8%A6%81%E9%87%8D%E6%9E%84%E3%80%82%E6%9C%80%E8%BF%91%E5%9C%A8%E7%9C%8B%E3%80%8AXUnit%20Test%20Patterns%E3%80%8B%EF%BC%8C%E6%8A%8A%E4%BB%A5%E5%89%8D%E7%9A%84%E5%81%9A%E7%9A%84%E4%B8%9C%E8%A5%BF%E9%87%8D%E6%96%B0%E6%A2%B3%E7%90" title="Google Bookmarks"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Frefactoring-unit-test%2F&amp;title=%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%E9%87%8D%E6%9E%84%E5%AE%9E%E4%BE%8B&amp;bodytext=Martin%20Fowler%E7%9A%84%E3%80%8A%E9%87%8D%E6%9E%84%E3%80%8B%E8%BF%99%E6%9C%AC%E4%B9%A6%E5%9F%BA%E6%9C%AC%E4%B8%8A%E6%AF%8F%E4%B8%AA%E7%A8%8B%E5%BA%8F%E5%91%98%E9%83%BD%E4%BC%9A%E7%9C%8B%EF%BC%8C%E5%AF%B9%E4%BA%8E%E5%81%9A%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%9A%84%E6%B5%8B%E8%AF%95%E5%B7%A5%E7%A8%8B%E5%B8%88%E6%9D%A5%E8%AF%B4%EF%BC%8C%E6%B5%8B%E8%AF%95%E7%9A%84%E4%BB%A3%E7%A0%81%E6%9C%AC%E8%BA%AB%E4%B9%9F%E6%98%AF%E7%A8%8B%E5%BA%8F%EF%BC%8C%E4%B9%9F%E9%9C%80%E8%A6%81%E9%87%8D%E6%9E%84%E3%80%82%E6%9C%80%E8%BF%91%E5%9C%A8%E7%9C%8B%E3%80%8AXUnit%20Test%20Patterns%E3%80%8B%EF%BC%8C%E6%8A%8A%E4%BB%A5%E5%89%8D%E7%9A%84%E5%81%9A%E7%9A%84%E4%B8%9C%E8%A5%BF%E9%87%8D%E6%96%B0%E6%A2%B3%E7%90" title="Digg"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Frefactoring-unit-test%2F&amp;title=%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%E9%87%8D%E6%9E%84%E5%AE%9E%E4%BE%8B&amp;notes=Martin%20Fowler%E7%9A%84%E3%80%8A%E9%87%8D%E6%9E%84%E3%80%8B%E8%BF%99%E6%9C%AC%E4%B9%A6%E5%9F%BA%E6%9C%AC%E4%B8%8A%E6%AF%8F%E4%B8%AA%E7%A8%8B%E5%BA%8F%E5%91%98%E9%83%BD%E4%BC%9A%E7%9C%8B%EF%BC%8C%E5%AF%B9%E4%BA%8E%E5%81%9A%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%9A%84%E6%B5%8B%E8%AF%95%E5%B7%A5%E7%A8%8B%E5%B8%88%E6%9D%A5%E8%AF%B4%EF%BC%8C%E6%B5%8B%E8%AF%95%E7%9A%84%E4%BB%A3%E7%A0%81%E6%9C%AC%E8%BA%AB%E4%B9%9F%E6%98%AF%E7%A8%8B%E5%BA%8F%EF%BC%8C%E4%B9%9F%E9%9C%80%E8%A6%81%E9%87%8D%E6%9E%84%E3%80%82%E6%9C%80%E8%BF%91%E5%9C%A8%E7%9C%8B%E3%80%8AXUnit%20Test%20Patterns%E3%80%8B%EF%BC%8C%E6%8A%8A%E4%BB%A5%E5%89%8D%E7%9A%84%E5%81%9A%E7%9A%84%E4%B8%9C%E8%A5%BF%E9%87%8D%E6%96%B0%E6%A2%B3%E7%90" title="del.icio.us"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Frefactoring-unit-test%2F&amp;t=%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%E9%87%8D%E6%9E%84%E5%AE%9E%E4%BE%8B" title="Facebook"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Frefactoring-unit-test%2F&title=%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%E9%87%8D%E6%9E%84%E5%AE%9E%E4%BE%8B" title="豆瓣"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban.png" title="豆瓣" alt="豆瓣" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Frefactoring-unit-test%2F&title=%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%E9%87%8D%E6%9E%84%E5%AE%9E%E4%BE%8B&n=1" title="豆瓣九点"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban9.png" title="豆瓣九点" alt="豆瓣九点" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.friendfeed.com/share?title=%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%E9%87%8D%E6%9E%84%E5%AE%9E%E4%BE%8B&amp;link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Frefactoring-unit-test%2F" title="FriendFeed"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Frefactoring-unit-test%2F&amp;title=%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%E9%87%8D%E6%9E%84%E5%AE%9E%E4%BE%8B" title="Live"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/live.png" title="Live" alt="Live" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://ping.fm/ref/?link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Frefactoring-unit-test%2F&amp;title=%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%E9%87%8D%E6%9E%84%E5%AE%9E%E4%BE%8B&amp;body=Martin%20Fowler%E7%9A%84%E3%80%8A%E9%87%8D%E6%9E%84%E3%80%8B%E8%BF%99%E6%9C%AC%E4%B9%A6%E5%9F%BA%E6%9C%AC%E4%B8%8A%E6%AF%8F%E4%B8%AA%E7%A8%8B%E5%BA%8F%E5%91%98%E9%83%BD%E4%BC%9A%E7%9C%8B%EF%BC%8C%E5%AF%B9%E4%BA%8E%E5%81%9A%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%9A%84%E6%B5%8B%E8%AF%95%E5%B7%A5%E7%A8%8B%E5%B8%88%E6%9D%A5%E8%AF%B4%EF%BC%8C%E6%B5%8B%E8%AF%95%E7%9A%84%E4%BB%A3%E7%A0%81%E6%9C%AC%E8%BA%AB%E4%B9%9F%E6%98%AF%E7%A8%8B%E5%BA%8F%EF%BC%8C%E4%B9%9F%E9%9C%80%E8%A6%81%E9%87%8D%E6%9E%84%E3%80%82%E6%9C%80%E8%BF%91%E5%9C%A8%E7%9C%8B%E3%80%8AXUnit%20Test%20Patterns%E3%80%8B%EF%BC%8C%E6%8A%8A%E4%BB%A5%E5%89%8D%E7%9A%84%E5%81%9A%E7%9A%84%E4%B8%9C%E8%A5%BF%E9%87%8D%E6%96%B0%E6%A2%B3%E7%90" title="Ping.fm"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/ping.png" title="Ping.fm" alt="Ping.fm" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://shuqian.qq.com/post?jumpback=1&title=%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%E9%87%8D%E6%9E%84%E5%AE%9E%E4%BE%8B&uri=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Frefactoring-unit-test%2F" title="QQ书签"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/qq.png" title="QQ书签" alt="QQ书签" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=%E6%B5%8B%E8%AF%95%E4%BB%A3%E7%A0%81%E9%87%8D%E6%9E%84%E5%AE%9E%E4%BE%8B%20-%20http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Frefactoring-unit-test%2F" title="Twitter"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>

<p>Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/unit-test-pattern/' rel='bookmark' title='Permanent Link: 单元测试中的常用测试模式'>单元测试中的常用测试模式</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/beginning-nmock/' rel='bookmark' title='Permanent Link: NMock2入门经验'>NMock2入门经验</a></li>
<li><a href='http://magustest.com/blog/automationtesting/data-driven-codedui-test/' rel='bookmark' title='Permanent Link: 实现数据驱动的CodedUI Test'>实现数据驱动的CodedUI Test</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/whiteboxtesting/refactoring-unit-test/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>单元测试中三种准备Test Fixture的方法比较</title>
		<link>http://magustest.com/blog/whiteboxtesting/three-different-test-fixture-setup-approach/</link>
		<comments>http://magustest.com/blog/whiteboxtesting/three-different-test-fixture-setup-approach/#comments</comments>
		<pubDate>Tue, 17 Mar 2009 10:09:19 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[白盒测试]]></category>
		<category><![CDATA[软件测试]]></category>
		<category><![CDATA[单元测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=375</guid>
		<description><![CDATA[首先说一下Test Fixture，我不知道怎么样翻译这个Test Fixture，没能搜到一个翻译的比较合适的。最让我气愤的是某人翻译的一本书中，直接把Test Fixture翻译成为测试夹具，这明显就是什么词霸词典硬翻译出来的，我强烈鄙视这样不负责任的翻译行为。 The test fixture is everything we need to have in place to exercise the SUT 我觉得这是一个对Test Fixture的一个很清晰明了的定义，就是运行被测软件所需要的一切东西，这个“东西”不单只是数据，同时还包括对被测软件的准备，例如实例化某个被测方法所在的类，准备数据库的ConnectionString等。通常来说，有三种方法来准备Test Fixture。 1. 内联方式：这种方式就是直接在测试方法中编写准备Test Fixture的代码。用这种方法的缺点是很容易造成代码的重复，出现很多复制粘贴的代码。同时，如果这个SETUP的过程比较复杂，也会降低测试代码的可读性，可维护性。另外的一个问题就是，这种方法很容易会带来测试数据Hard code的隐患。既然有那么多缺点，这种方法还有什么生命力呢？首先，可能对于初学者来说，这种方法是最简单的；其次，在一些只需要准备简单的Test Fixture的场合中，这种方法还是给编写测试的人提供了便利。 2. 委托方式：简单来说就是把Test Fixture的准备抽取为一个外部的方法，然后在需要的时候进行调用。这种方式的好处就是使得测试代码可读性更强，并且这部分的SETUP代码可以重用。而且这种做法可以屏蔽对SETUP过程的认知，使得测试人员的关注点落在真正的测试代码上面，而不是如何SETUP。 3. 隐式方式：很多xUnit框架的实现都提供了不同的隐式SETUP和TEARDOWN。例如MSTEST里面的[TestInitialize]和[TestCleanup]标签，就提供了一种隐式准备Test Fixture的支持。就是在每一个测试方法运行前，都会执行一次标有[TestInitialize]标签的方法。使用这种方法的好处就是写一次就能在各个测试中都实现了Test Fixture的准备，不用每次都显示地调用一个外部方法，不过缺点也不少： 可能会令测试比较难懂，因为这些隐式调用不是必须的，有可能会被遗漏掉。 不能使用哦本地变量来保存对象，只能用test class 里面的filed或者property 变相地使用了全局变量 在做单元测试的过程中，需要灵活地运用这三种Test Fixture的准备方法。例如在我的工作当中，我在以下情况使用到了隐式准备方式： 在某一个测试项目中，由于测试的数据不多，所以我使用了XmlSerializer，把测试的数据都放在一个XML文件中，然后利用XmlSerializer把XML中的数据映射到相应的配置类中。对于这样的情况，这些测试数据在测试运行的全过程中都需要用到，所以我选择了在测试类初始化的时候，只运行1次，来准备这些测试数据（Test Fixture的一部分）。 1 2 3 4 5 6 7 &#91;ClassInitialize&#40;&#41;&#93; public static void MyClassInitialize&#40;TestContext [...]


Related posts:<ol><li><a href='http://magustest.com/blog/net/automatic-generate-xml-instance-by-using-xsd/' rel='bookmark' title='Permanent Link: 用XSD自动生成XML对应的.NET实体类'>用XSD自动生成XML对应的.NET实体类</a></li>
<li><a href='http://magustest.com/blog/automationtesting/data-driven-codedui-test/' rel='bookmark' title='Permanent Link: 实现数据驱动的CodedUI Test'>实现数据驱动的CodedUI Test</a></li>
<li><a href='http://magustest.com/blog/net/aspnet-web-config-priority/' rel='bookmark' title='Permanent Link: ASP.NET中配置文件web.config的优先级'>ASP.NET中配置文件web.config的优先级</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>首先说一下Test Fixture，我不知道怎么样翻译这个Test Fixture，没能搜到一个翻译的比较合适的。最让我气愤的是某人翻译的一本书中，直接把Test Fixture翻译成为测试夹具，这明显就是什么词霸词典硬翻译出来的，我强烈鄙视这样不负责任的翻译行为。</p>
<p>The test fixture is everything we need to have in place to exercise the SUT</p>
<p>我觉得这是一个对Test Fixture的一个很清晰明了的定义，就是运行被测软件所需要的一切东西，这个“东西”不单只是数据，同时还包括对被测软件的准备，例如实例化某个被测方法所在的类，准备数据库的ConnectionString等。通常来说，有三种方法来准备Test Fixture。</p>
<p>1. 内联方式：这种方式就是直接在测试方法中编写准备Test Fixture的代码。用这种方法的缺点是很容易造成代码的重复，出现很多复制粘贴的代码。同时，如果这个SETUP的过程比较复杂，也会降低测试代码的可读性，可维护性。另外的一个问题就是，这种方法很容易会带来测试数据Hard code的隐患。既然有那么多缺点，这种方法还有什么生命力呢？首先，可能对于初学者来说，这种方法是最简单的；其次，在一些只需要准备简单的Test Fixture的场合中，这种方法还是给编写测试的人提供了便利。<br />
<span id="more-375"></span><br />
2. 委托方式：简单来说就是把Test Fixture的准备抽取为一个外部的方法，然后在需要的时候进行调用。这种方式的好处就是使得测试代码可读性更强，并且这部分的SETUP代码可以重用。而且这种做法可以屏蔽对SETUP过程的认知，使得测试人员的关注点落在真正的测试代码上面，而不是如何SETUP。</p>
<p>3. 隐式方式：很多xUnit框架的实现都提供了不同的隐式SETUP和TEARDOWN。例如MSTEST里面的[TestInitialize]和[TestCleanup]标签，就提供了一种隐式准备Test Fixture的支持。就是在每一个测试方法运行前，都会执行一次标有[TestInitialize]标签的方法。使用这种方法的好处就是写一次就能在各个测试中都实现了Test Fixture的准备，不用每次都显示地调用一个外部方法，不过缺点也不少：</p>
<ul>
<li>可能会令测试比较难懂，因为这些隐式调用不是必须的，有可能会被遗漏掉。</li>
<li> 不能使用哦本地变量来保存对象，只能用test class 里面的filed或者property</li>
<li> 变相地使用了全局变量</li>
</ul>
<p>在做单元测试的过程中，需要灵活地运用这三种Test Fixture的准备方法。例如在我的工作当中，我在以下情况使用到了隐式准备方式：</p>
<p>在某一个测试项目中，由于测试的数据不多，所以我使用了XmlSerializer，把测试的数据都放在一个XML文件中，然后利用XmlSerializer把XML中的数据映射到相应的配置类中。对于这样的情况，这些测试数据在测试运行的全过程中都需要用到，所以我选择了在测试类初始化的时候，只运行1次，来准备这些测试数据（Test Fixture的一部分）。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>ClassInitialize<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #0600FF;">void</span> MyClassInitialize<span style="color: #000000;">&#40;</span>TestContext testContext<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    XmlSerializer xmlSerializer <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> XmlSerializer<span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>Config<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    FileStream fs <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> FileStream<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Config.xml&quot;</span>, FileMode.<span style="color: #0000FF;">Open</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    config <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>Config<span style="color: #000000;">&#41;</span>xmlSerializer.<span style="color: #0000FF;">Deserialize</span><span style="color: #000000;">&#40;</span>fs<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>还是在同一个项目中，我想让每一个测试之间互相不要受到影响，所以我在[TestInitialize()]方法中对于一个Web Service的客户端进行初始化，保证每一次运行测试前，这个客户端都是“新”的</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestInitialize<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> MyTestInitialize<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
   USi18nService <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> InteropWebSerivce<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
   USi18nService.<span style="color: #0000FF;">Url</span> <span style="color: #008000;">=</span> config.<span style="color: #0000FF;">USi18nAddress</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>在另外的一个项目中，需要对一个方法进行测试，该方法的功能是根据Email地址从PreSignup表里面获取相关的资料，那么首先要做的就是完成一个PreSignup的操作，才能检查这个方法。而完成PreSignup操作并不是所有的测试都需要的，所以我不选择隐式调用，而是选择委托调用，调用一个外部的帮助方法，来帮助我完成PreSignup操作；同时这个PreSignup的操作在其他一些测试中也是需要的，所以也达到了重用的效果。</p>
<p>那么在什么时候会用到内联方法来准备Test Fixture呢？其实我自己经常用这种方法，有以下一个场景，我需要对一个方法进行测试，这个方法要做的事情就是检查一个电话号码是否符合规范，那么我就会先创建一个List，然后在List里面填充了各种不同的电话号码，然后在后面用一个foreach语句把List里面的数据遍历一遍，可能这些电话号码的数据只在这一个方法里面才有用，所以我没有选择把它抽取成一个方法。</p>
<p>其实不同的单元测试框架有不同的思想，例如在NUnit里面，一个测试类的标签就是叫[Test Fixture]，其实作者的设计思想就是一个测试类，就是一套Test Fixture；如果不是一套Test Fixture，那么不要把测试方法写到一起。其实这三种方法各有所长，在我刚开始学习和尝试做单元测试的时候，我刚接触到类似[Setup][TearDown]这样的隐式调用的时候，我觉得这就是银弹，我要充分使用它。但是随着工作的深入，发现这个隐式调用会带来一些问题，然后就慢慢转用了调外部方法，或者直接内联到测试方法中。只有结合实际情况，结合的上下文来运用这些方法，才能真正提高单元测试代码的质量，减少我们的工作量。</p>



Share and Enjoy:


	<a rel="nofollow"  target="_blank" href="http://magustest.com/blog/feed/" title="RSS"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/rss.png" title="RSS" alt="RSS" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fthree-different-test-fixture-setup-approach%2F&amp;t=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%B8%89%E7%A7%8D%E5%87%86%E5%A4%87Test%20Fixture%E7%9A%84%E6%96%B9%E6%B3%95%E6%AF%94%E8%BE%83" title="Facebook"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fthree-different-test-fixture-setup-approach%2F&title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%B8%89%E7%A7%8D%E5%87%86%E5%A4%87Test%20Fixture%E7%9A%84%E6%96%B9%E6%B3%95%E6%AF%94%E8%BE%83" title="豆瓣"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban.png" title="豆瓣" alt="豆瓣" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fthree-different-test-fixture-setup-approach%2F&title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%B8%89%E7%A7%8D%E5%87%86%E5%A4%87Test%20Fixture%E7%9A%84%E6%96%B9%E6%B3%95%E6%AF%94%E8%BE%83&n=1" title="豆瓣九点"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban9.png" title="豆瓣九点" alt="豆瓣九点" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.friendfeed.com/share?title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%B8%89%E7%A7%8D%E5%87%86%E5%A4%87Test%20Fixture%E7%9A%84%E6%96%B9%E6%B3%95%E6%AF%94%E8%BE%83&amp;link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fthree-different-test-fixture-setup-approach%2F" title="FriendFeed"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fthree-different-test-fixture-setup-approach%2F&amp;title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%B8%89%E7%A7%8D%E5%87%86%E5%A4%87Test%20Fixture%E7%9A%84%E6%96%B9%E6%B3%95%E6%AF%94%E8%BE%83" title="Live"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/live.png" title="Live" alt="Live" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/ping.png" title="Ping.fm" alt="Ping.fm" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://shuqian.qq.com/post?jumpback=1&title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%B8%89%E7%A7%8D%E5%87%86%E5%A4%87Test%20Fixture%E7%9A%84%E6%96%B9%E6%B3%95%E6%AF%94%E8%BE%83&uri=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fthree-different-test-fixture-setup-approach%2F" title="QQ书签"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/qq.png" title="QQ书签" alt="QQ书签" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%B8%89%E7%A7%8D%E5%87%86%E5%A4%87Test%20Fixture%E7%9A%84%E6%96%B9%E6%B3%95%E6%AF%94%E8%BE%83%20-%20http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fthree-different-test-fixture-setup-approach%2F" title="Twitter"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>

<p>Related posts:<ol><li><a href='http://magustest.com/blog/net/automatic-generate-xml-instance-by-using-xsd/' rel='bookmark' title='Permanent Link: 用XSD自动生成XML对应的.NET实体类'>用XSD自动生成XML对应的.NET实体类</a></li>
<li><a href='http://magustest.com/blog/automationtesting/data-driven-codedui-test/' rel='bookmark' title='Permanent Link: 实现数据驱动的CodedUI Test'>实现数据驱动的CodedUI Test</a></li>
<li><a href='http://magustest.com/blog/net/aspnet-web-config-priority/' rel='bookmark' title='Permanent Link: ASP.NET中配置文件web.config的优先级'>ASP.NET中配置文件web.config的优先级</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/whiteboxtesting/three-different-test-fixture-setup-approach/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>控制反转有助于提高程序的可测试性</title>
		<link>http://magustest.com/blog/whiteboxtesting/inversion-of-control-improve-testabilit/</link>
		<comments>http://magustest.com/blog/whiteboxtesting/inversion-of-control-improve-testabilit/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 04:11:10 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[白盒测试]]></category>
		<category><![CDATA[单元测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=372</guid>
		<description><![CDATA[控制反转，英文是Inversion of Control，简称IoC。这个概念在JAVA的Spring框架中比较常见，在.NET的开发中，Ioc或者其的变种依赖注入DI（Dependency Injection）是不太常见的。一般来说，类A要使用类B，类A会在其内部对类B进行控制，比较典型的做法就是在类A中创建一个类B的实例；而控制反转，就是把一个已经创建好的类B实例交给类A去控制。 例子： 有一个Member的类，他需要调用一个Web service的客户端接口，在这个类的构造函数里面，创建了一个WebServiceClientA对象。这里的WebServiceClientA类是实现了WebServiceClient接口的。 1 2 3 4 5 6 7 8 class Member &#123; WebServiceClient client; Member&#40;&#41; &#123; client = new WebServiceClientA&#40;&#34;10.60.0.11&#34;&#41;; &#125; &#125; 问题来了，对于这个类，我们怎么去测试？在构造函数里面已经初始化了一个WebServiceClientA，并且指定了这个WebServiceClientA的IP是10.60.0.11。那假如说开发环境不能连接到这台服务器上，那么怎么测试。这个问题可以通过对IP地址这个参数写到配置文件里面就能解决，其实这个跟IoC没有什么关系。 1 2 3 4 5 6 7 8 class Member &#123; WebServiceClient client; Member&#40;&#41; &#123; client = new WebServiceClientA&#40;ConfigurationManager.AppSettings&#91;&#34;ServerIP&#34;&#93;&#41;; &#125; &#125; 现在又有问题了，如果WebServiceClientA类没有完成，但是此时却要进行测试，怎么办？又假如说WebServiceClientA类是很难被创建的，怎么办？Mock也有劲使不上啊。 其实在构造函数里面是不应该有创建对象的操作，也就是尽可能不要有new操作，我们把WebServiceClient作为构造函数的一个参数，传递进去，这样程序的可测试性就有了提高，这时候可以对WebServiceClient使用Mock对象了。 1 2 3 [...]


Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/introduction-to-pex-automated-white-box-testing-for-dotnet/' rel='bookmark' title='Permanent Link: PEX-.NET自动化白盒测试工具的介绍(1)'>PEX-.NET自动化白盒测试工具的介绍(1)</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>控制反转，英文是Inversion of Control，简称IoC。这个概念在JAVA的Spring框架中比较常见，在.NET的开发中，Ioc或者其的变种依赖注入DI（Dependency Injection）是不太常见的。一般来说，类A要使用类B，类A会在其内部对类B进行控制，比较典型的做法就是在类A中创建一个类B的实例；而控制反转，就是把一个已经创建好的类B实例交给类A去控制。<br />
例子：<br />
<span id="more-372"></span><br />
有一个Member的类，他需要调用一个Web service的客户端接口，在这个类的构造函数里面，创建了一个WebServiceClientA对象。这里的WebServiceClientA类是实现了WebServiceClient接口的。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">class</span> Member
<span style="color: #000000;">&#123;</span>
    WebServiceClient client<span style="color: #008000;">;</span>
    Member<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        client <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> WebServiceClientA<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;10.60.0.11&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>问题来了，对于这个类，我们怎么去测试？在构造函数里面已经初始化了一个WebServiceClientA，并且指定了这个WebServiceClientA的IP是10.60.0.11。那假如说开发环境不能连接到这台服务器上，那么怎么测试。这个问题可以通过对IP地址这个参数写到配置文件里面就能解决，其实这个跟IoC没有什么关系。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">class</span> Member
<span style="color: #000000;">&#123;</span>
    WebServiceClient client<span style="color: #008000;">;</span>
    Member<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        client <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> WebServiceClientA<span style="color: #000000;">&#40;</span>ConfigurationManager.<span style="color: #0000FF;">AppSettings</span><span style="color: #000000;">&#91;</span><span style="color: #666666;">&quot;ServerIP&quot;</span><span style="color: #000000;">&#93;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>现在又有问题了，如果WebServiceClientA类没有完成，但是此时却要进行测试，怎么办？又假如说WebServiceClientA类是很难被创建的，怎么办？Mock也有劲使不上啊。<br />
其实在构造函数里面是不应该有创建对象的操作，也就是尽可能不要有new操作，我们把WebServiceClient作为构造函数的一个参数，传递进去，这样程序的可测试性就有了提高，这时候可以对WebServiceClient使用Mock对象了。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #FF0000;">class</span> Member
<span style="color: #000000;">&#123;</span>
    WebServiceClient client<span style="color: #008000;">;</span>
    Member<span style="color: #000000;">&#40;</span>WebServiceClient c<span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        client <span style="color: #008000;">=</span> c<span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>这跟著名的好莱坞原则(Hollywood Principle)有几分相似，don&#8217;t call us, we&#8217;ll call you。你不要自己创建一个实现了WebServiceClient接口的对象，我给你传一个。</p>



Share and Enjoy:


	<a rel="nofollow"  target="_blank" href="http://magustest.com/blog/feed/" title="RSS"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/rss.png" title="RSS" alt="RSS" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.google.com/bookmarks/mark?op=edit&amp;bkmk=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Finversion-of-control-improve-testabilit%2F&amp;title=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E6%9C%89%E5%8A%A9%E4%BA%8E%E6%8F%90%E9%AB%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%8F%AF%E6%B5%8B%E8%AF%95%E6%80%A7&amp;annotation=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%EF%BC%8C%E8%8B%B1%E6%96%87%E6%98%AFInversion%20of%20Control%EF%BC%8C%E7%AE%80%E7%A7%B0IoC%E3%80%82%E8%BF%99%E4%B8%AA%E6%A6%82%E5%BF%B5%E5%9C%A8JAVA%E7%9A%84Spring%E6%A1%86%E6%9E%B6%E4%B8%AD%E6%AF%94%E8%BE%83%E5%B8%B8%E8%A7%81%EF%BC%8C%E5%9C%A8.NET%E7%9A%84%E5%BC%80%E5%8F%91%E4%B8%AD%EF%BC%8CIoc%E6%88%96%E8%80%85%E5%85%B6%E7%9A%84%E5%8F%98%E7%A7%8D%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5DI%EF%BC%88Dependency%20Injection%EF%BC%89%E6%98%AF%E4%B8%8D%E5%A4%AA%E5%B8%B8%E8%A7%81%E7%9A%84%E3%80%82%E4%B8%80%E8%88%AC%E6%9D%A5%E8%AF%B4%EF%BC%8C%E7%B1%BBA%E8%A6%81%E4%BD%BF%E7%94%A8%E7%B1%BBB%EF%BC%8C" title="Google Bookmarks"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Finversion-of-control-improve-testabilit%2F&amp;title=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E6%9C%89%E5%8A%A9%E4%BA%8E%E6%8F%90%E9%AB%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%8F%AF%E6%B5%8B%E8%AF%95%E6%80%A7&amp;bodytext=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%EF%BC%8C%E8%8B%B1%E6%96%87%E6%98%AFInversion%20of%20Control%EF%BC%8C%E7%AE%80%E7%A7%B0IoC%E3%80%82%E8%BF%99%E4%B8%AA%E6%A6%82%E5%BF%B5%E5%9C%A8JAVA%E7%9A%84Spring%E6%A1%86%E6%9E%B6%E4%B8%AD%E6%AF%94%E8%BE%83%E5%B8%B8%E8%A7%81%EF%BC%8C%E5%9C%A8.NET%E7%9A%84%E5%BC%80%E5%8F%91%E4%B8%AD%EF%BC%8CIoc%E6%88%96%E8%80%85%E5%85%B6%E7%9A%84%E5%8F%98%E7%A7%8D%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5DI%EF%BC%88Dependency%20Injection%EF%BC%89%E6%98%AF%E4%B8%8D%E5%A4%AA%E5%B8%B8%E8%A7%81%E7%9A%84%E3%80%82%E4%B8%80%E8%88%AC%E6%9D%A5%E8%AF%B4%EF%BC%8C%E7%B1%BBA%E8%A6%81%E4%BD%BF%E7%94%A8%E7%B1%BBB%EF%BC%8C" title="Digg"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Finversion-of-control-improve-testabilit%2F&amp;title=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E6%9C%89%E5%8A%A9%E4%BA%8E%E6%8F%90%E9%AB%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%8F%AF%E6%B5%8B%E8%AF%95%E6%80%A7&amp;notes=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%EF%BC%8C%E8%8B%B1%E6%96%87%E6%98%AFInversion%20of%20Control%EF%BC%8C%E7%AE%80%E7%A7%B0IoC%E3%80%82%E8%BF%99%E4%B8%AA%E6%A6%82%E5%BF%B5%E5%9C%A8JAVA%E7%9A%84Spring%E6%A1%86%E6%9E%B6%E4%B8%AD%E6%AF%94%E8%BE%83%E5%B8%B8%E8%A7%81%EF%BC%8C%E5%9C%A8.NET%E7%9A%84%E5%BC%80%E5%8F%91%E4%B8%AD%EF%BC%8CIoc%E6%88%96%E8%80%85%E5%85%B6%E7%9A%84%E5%8F%98%E7%A7%8D%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5DI%EF%BC%88Dependency%20Injection%EF%BC%89%E6%98%AF%E4%B8%8D%E5%A4%AA%E5%B8%B8%E8%A7%81%E7%9A%84%E3%80%82%E4%B8%80%E8%88%AC%E6%9D%A5%E8%AF%B4%EF%BC%8C%E7%B1%BBA%E8%A6%81%E4%BD%BF%E7%94%A8%E7%B1%BBB%EF%BC%8C" title="del.icio.us"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Finversion-of-control-improve-testabilit%2F&amp;t=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E6%9C%89%E5%8A%A9%E4%BA%8E%E6%8F%90%E9%AB%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%8F%AF%E6%B5%8B%E8%AF%95%E6%80%A7" title="Facebook"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Finversion-of-control-improve-testabilit%2F&title=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E6%9C%89%E5%8A%A9%E4%BA%8E%E6%8F%90%E9%AB%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%8F%AF%E6%B5%8B%E8%AF%95%E6%80%A7" title="豆瓣"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban.png" title="豆瓣" alt="豆瓣" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Finversion-of-control-improve-testabilit%2F&title=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E6%9C%89%E5%8A%A9%E4%BA%8E%E6%8F%90%E9%AB%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%8F%AF%E6%B5%8B%E8%AF%95%E6%80%A7&n=1" title="豆瓣九点"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban9.png" title="豆瓣九点" alt="豆瓣九点" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.friendfeed.com/share?title=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E6%9C%89%E5%8A%A9%E4%BA%8E%E6%8F%90%E9%AB%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%8F%AF%E6%B5%8B%E8%AF%95%E6%80%A7&amp;link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Finversion-of-control-improve-testabilit%2F" title="FriendFeed"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Finversion-of-control-improve-testabilit%2F&amp;title=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E6%9C%89%E5%8A%A9%E4%BA%8E%E6%8F%90%E9%AB%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%8F%AF%E6%B5%8B%E8%AF%95%E6%80%A7" title="Live"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/live.png" title="Live" alt="Live" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://ping.fm/ref/?link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Finversion-of-control-improve-testabilit%2F&amp;title=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E6%9C%89%E5%8A%A9%E4%BA%8E%E6%8F%90%E9%AB%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%8F%AF%E6%B5%8B%E8%AF%95%E6%80%A7&amp;body=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%EF%BC%8C%E8%8B%B1%E6%96%87%E6%98%AFInversion%20of%20Control%EF%BC%8C%E7%AE%80%E7%A7%B0IoC%E3%80%82%E8%BF%99%E4%B8%AA%E6%A6%82%E5%BF%B5%E5%9C%A8JAVA%E7%9A%84Spring%E6%A1%86%E6%9E%B6%E4%B8%AD%E6%AF%94%E8%BE%83%E5%B8%B8%E8%A7%81%EF%BC%8C%E5%9C%A8.NET%E7%9A%84%E5%BC%80%E5%8F%91%E4%B8%AD%EF%BC%8CIoc%E6%88%96%E8%80%85%E5%85%B6%E7%9A%84%E5%8F%98%E7%A7%8D%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5DI%EF%BC%88Dependency%20Injection%EF%BC%89%E6%98%AF%E4%B8%8D%E5%A4%AA%E5%B8%B8%E8%A7%81%E7%9A%84%E3%80%82%E4%B8%80%E8%88%AC%E6%9D%A5%E8%AF%B4%EF%BC%8C%E7%B1%BBA%E8%A6%81%E4%BD%BF%E7%94%A8%E7%B1%BBB%EF%BC%8C" title="Ping.fm"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/ping.png" title="Ping.fm" alt="Ping.fm" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://shuqian.qq.com/post?jumpback=1&title=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E6%9C%89%E5%8A%A9%E4%BA%8E%E6%8F%90%E9%AB%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%8F%AF%E6%B5%8B%E8%AF%95%E6%80%A7&uri=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Finversion-of-control-improve-testabilit%2F" title="QQ书签"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/qq.png" title="QQ书签" alt="QQ书签" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=%E6%8E%A7%E5%88%B6%E5%8F%8D%E8%BD%AC%E6%9C%89%E5%8A%A9%E4%BA%8E%E6%8F%90%E9%AB%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%8F%AF%E6%B5%8B%E8%AF%95%E6%80%A7%20-%20http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Finversion-of-control-improve-testabilit%2F" title="Twitter"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>

<p>Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/introduction-to-pex-automated-white-box-testing-for-dotnet/' rel='bookmark' title='Permanent Link: PEX-.NET自动化白盒测试工具的介绍(1)'>PEX-.NET自动化白盒测试工具的介绍(1)</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/whiteboxtesting/inversion-of-control-improve-testabilit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>自动化单元测试要点</title>
		<link>http://magustest.com/blog/whiteboxtesting/unit-test-and-integration-test/</link>
		<comments>http://magustest.com/blog/whiteboxtesting/unit-test-and-integration-test/#comments</comments>
		<pubDate>Sat, 07 Mar 2009 14:13:26 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[白盒测试]]></category>
		<category><![CDATA[自动化测试]]></category>
		<category><![CDATA[软件测试]]></category>
		<category><![CDATA[单元测试]]></category>
		<category><![CDATA[接口测试]]></category>
		<category><![CDATA[集成测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=362</guid>
		<description><![CDATA[用单元测试的框架MSTEST，做单元测试，集成测试快1年了，总结一下工作中学到都东西。 单元测试，集成测试有什么用？ 1. 改进产品质量 软件测试，很多时候围绕着两个问题： Verification和Validation，常说的双V。前面的Verification就是Is the software built correctly?。后面的Validation就是Have we built the right software? 单元测试，更多的是Verification。所以有时候经过我单元测试和集成测试以后的功能模块，在交给其他同事做功能测试的时候，依然会有一些BUG，这时候开发可能会埋怨我测试得不够完全，诸如此类。但是其实很多时候，我的关注点是单个方法的功能、行为，没有站到更高的位置来测试这个模块。对于这样的问题，开发和测试应该互相体谅，我本人也会提高自身的水平。希望在单元测试和集成测试中也加入更多关于Validation的思考。 有一个提法叫Tests as Specification，单元测试本身其实就是模拟某个模块的使用者（其他的程序）来进行测试。很多时候我写的测试代码也是其他开发人员的参考，尤其在一些事实上或者只是号称自己是敏捷开发的组织里面，测试代码有可能成为详细设计的替代品，因为有可能根本没有详细设计文档。 单元测试的另一个工作就是发现并且定位BUG。对于BUG的定位和重现，在单元测试代码的编写过程中，每个Assert语句后面都要加上尽可能详细的信息，例如导致这个Assert语句失败的每个参数值，期望结果，实际结果等，这些信息可以帮助开发和测试快速定位问题，减少不必要的DEBUG时间。 2. 降低项目的风险 软件测试，其实是用有限来验证无限的一个过程，很多时候做什么样的测试，做到什么样的程度，很多时候都跟风险有关系。 作为产品的安全网，各种测试在项目中都扮演着重要的角色。例如，中美交互的几十个Web Service接口的回归测试，现在有若干个测试，每天定时做回归测试，因为没人知道在美国的服务器会发生什么事情；对于中国的Web Service，在上线前都会通过回归测试，才部署上线。还有全站的Platform Service接口，每次上线前都需要在做回归测试。软件测试的另一个有趣的结论就是：测试只能证明软件有BUG，但是无论什么样的测试，都不能证明被测软件是没有BUG的。问题出来了，我做完回归测试，都通过了，但是我却不能证明这个软件是没有BUG的。其实每次上线，团队都承担着风险，只不过这样的风险在完成回归测试之后，大家上线的信心增加，风险明显地减小。 什么样的测试才是好的测试？ 1. 容易运行 什么样的单元测试是容易运行？答案很简单，自动化的单元测试就是容易运行的测试。如果一批测试在运行之前每次都需要重装系统然后还要找一大堆需要依赖的软件来装上，最后还要输入奇怪的命令才能运行，那么就不是一个好的测试（本人真的见过这样的测试，囧）。个人认为，配置好的持续集成系统，可以实现很好的自动化测试；如果没有一个完善的CI，那么一个one click的自动化测试运行也是一个较好的选择。 2. 自动检查结果 一句话：没有自动检查结果，再好的自动化也是白搭。 3. 可重复 一句话：只能运行一次的单元测试也是白搭。 4. 独立 其实测试的独立，也有利于实现可重复。刚做单元测试的时候，曾经犯过这样的错误，我在写A测试的时候，给数据库插入了一条记录，然后我在写B测试的时候，就觉得我为什么要在两个测试中分别创建两条数据？直接用上一个测试的数据就可以了。不过结果还好，我很快就发现这样做是有问题。单元测试的独立，就是运行测试的人可以先运行A测试，也可以先运行B测试，也可以单独运行A或者B测试，甚至可以A和B测试同时运行。 5. 简单 有时候，测试的代码写的有点复杂，嵌套的语句有点多，可能有些人会觉得写出复杂的单元测试代码才能体现自己的水平，但是，我觉得对于单元测试代码来说，应该越简单越好。最好就是顺序执行下来了，不要有什么分支。因为测试代码本身就是也是代码，那么怎么去验证测试代码写的正确呢？答案可能是再写一个测试代码去验证第一个测试代码。这样就会有死循环了。一个简单的假设就是，如果测试代码足够简单，那么就可以认为测试代码是正确的，无需其他代码对之进行测试。 6. 专注 一个测试应该只测试一个点。如果在一个测试里面验证多个测试点，看起来是比较高效的一种做法，但是当测试中有Assert语句抛出异常的时候，很有可能需要花大量的时间才能找到真正错误的代码，这样不利于实现前面提及到的“定位BUG”。 7. 注释 注释其实就是把代码抽取成可阅读的测试用例，如果别人看自己的程序，可以快速理解测试代码；同时注释还能唤醒自己沉睡的记忆和当时的测试思路。 国内做单元测试的测试工程师少，做集成测试、接口测试的也不多，埋头做事,别忘抬头看路。时常总结，提高自我。 Share and Enjoy: Related [...]


Related posts:<ol><li><a href='http://magustest.com/blog/readingdaily/software-testing-note-part-three/' rel='bookmark' title='Permanent Link: 《Software Testing》第三章 &#8211; 软件测试'>《Software Testing》第三章 &#8211; 软件测试</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/exception-handling-in-unit-test/' rel='bookmark' title='Permanent Link: 单元测试中的异常处理'>单元测试中的异常处理</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>用单元测试的框架MSTEST，做单元测试，集成测试快1年了，总结一下工作中学到都东西。</p>
<p><span style="color: #ff0000;"><strong>单元测试，集成测试有什么用？</strong></span></p>
<p><strong>1. 改进产品质量</strong></p>
<p>软件测试，很多时候围绕着两个问题：</p>
<p>Verification和Validation，常说的双V。前面的Verification就是Is the software built correctly?。后面的Validation就是Have we built the right software?</p>
<p>单元测试，更多的是Verification。所以有时候经过我单元测试和集成测试以后的功能模块，在交给其他同事做功能测试的时候，依然会有一些BUG，这时候开发可能会埋怨我测试得不够完全，诸如此类。但是其实很多时候，我的关注点是单个方法的功能、行为，没有站到更高的位置来测试这个模块。对于这样的问题，开发和测试应该互相体谅，我本人也会提高自身的水平。希望在单元测试和集成测试中也加入更多关于Validation的思考。<br />
<span id="more-362"></span><br />
有一个提法叫Tests as Specification，单元测试本身其实就是模拟某个模块的使用者（其他的程序）来进行测试。很多时候我写的测试代码也是其他开发人员的参考，尤其在一些事实上或者只是号称自己是敏捷开发的组织里面，测试代码有可能成为详细设计的替代品，因为有可能根本没有详细设计文档。</p>
<p>单元测试的另一个工作就是发现并且定位BUG。对于BUG的定位和重现，在单元测试代码的编写过程中，每个Assert语句后面都要加上尽可能详细的信息，例如导致这个Assert语句失败的每个参数值，期望结果，实际结果等，这些信息可以帮助开发和测试快速定位问题，减少不必要的DEBUG时间。</p>
<p><strong>2. 降低项目的风险</strong></p>
<p>软件测试，其实是用有限来验证无限的一个过程，很多时候做什么样的测试，做到什么样的程度，很多时候都跟风险有关系。</p>
<p>作为产品的安全网，各种测试在项目中都扮演着重要的角色。例如，中美交互的几十个Web Service接口的回归测试，现在有若干个测试，每天定时做回归测试，因为没人知道在美国的服务器会发生什么事情；对于中国的Web Service，在上线前都会通过回归测试，才部署上线。还有全站的Platform Service接口，每次上线前都需要在做回归测试。软件测试的另一个有趣的结论就是：测试只能证明软件有BUG，但是无论什么样的测试，都不能证明被测软件是没有BUG的。问题出来了，我做完回归测试，都通过了，但是我却不能证明这个软件是没有BUG的。其实每次上线，团队都承担着风险，只不过这样的风险在完成回归测试之后，大家上线的信心增加，风险明显地减小。</p>
<p><span style="color: #ff0000;"><strong>什么样的测试才是好的测试？</strong></span></p>
<p><strong>1. 容易运行</strong></p>
<p>什么样的单元测试是容易运行？答案很简单，自动化的单元测试就是容易运行的测试。如果一批测试在运行之前每次都需要重装系统然后还要找一大堆需要依赖的软件来装上，最后还要输入奇怪的命令才能运行，那么就不是一个好的测试（本人真的见过这样的测试，囧）。个人认为，配置好的持续集成系统，可以实现很好的自动化测试；如果没有一个完善的CI，那么一个one click的自动化测试运行也是一个较好的选择。</p>
<p><strong>2. 自动检查结果</strong></p>
<p>一句话：没有自动检查结果，再好的自动化也是白搭。</p>
<p><strong>3. 可重复</strong></p>
<p>一句话：只能运行一次的单元测试也是白搭。</p>
<p><strong>4. 独立</strong></p>
<p>其实测试的独立，也有利于实现可重复。刚做单元测试的时候，曾经犯过这样的错误，我在写A测试的时候，给数据库插入了一条记录，然后我在写B测试的时候，就觉得我为什么要在两个测试中分别创建两条数据？直接用上一个测试的数据就可以了。不过结果还好，我很快就发现这样做是有问题。单元测试的独立，就是运行测试的人可以先运行A测试，也可以先运行B测试，也可以单独运行A或者B测试，甚至可以A和B测试同时运行。</p>
<p><strong>5. 简单</strong></p>
<p>有时候，测试的代码写的有点复杂，嵌套的语句有点多，可能有些人会觉得写出复杂的单元测试代码才能体现自己的水平，但是，我觉得对于单元测试代码来说，应该越简单越好。最好就是顺序执行下来了，不要有什么分支。因为测试代码本身就是也是代码，那么怎么去验证测试代码写的正确呢？答案可能是再写一个测试代码去验证第一个测试代码。这样就会有死循环了。一个简单的假设就是，如果测试代码足够简单，那么就可以认为测试代码是正确的，无需其他代码对之进行测试。</p>
<p><strong>6. 专注</strong></p>
<p>一个测试应该只测试一个点。如果在一个测试里面验证多个测试点，看起来是比较高效的一种做法，但是当测试中有Assert语句抛出异常的时候，很有可能需要花大量的时间才能找到真正错误的代码，这样不利于实现前面提及到的“定位BUG”。</p>
<p><strong>7. 注释</strong></p>
<p>注释其实就是把代码抽取成可阅读的测试用例，如果别人看自己的程序，可以快速理解测试代码；同时注释还能唤醒自己沉睡的记忆和当时的测试思路。</p>
<p>国内做单元测试的测试工程师少，做集成测试、接口测试的也不多，埋头做事,别忘抬头看路。时常总结，提高自我。</p>



Share and Enjoy:


	<a rel="nofollow"  target="_blank" href="http://magustest.com/blog/feed/" title="RSS"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/rss.png" title="RSS" alt="RSS" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-and-integration-test%2F&amp;title=%E8%87%AA%E5%8A%A8%E5%8C%96%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E8%A6%81%E7%82%B9&amp;bodytext=%E7%94%A8%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%9A%84%E6%A1%86%E6%9E%B6MSTEST%EF%BC%8C%E5%81%9A%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%EF%BC%8C%E9%9B%86%E6%88%90%E6%B5%8B%E8%AF%95%E5%BF%AB1%E5%B9%B4%E4%BA%86%EF%BC%8C%E6%80%BB%E7%BB%93%E4%B8%80%E4%B8%8B%E5%B7%A5%E4%BD%9C%E4%B8%AD%E5%AD%A6%E5%88%B0%E9%83%BD%E4%B8%9C%E8%A5%BF%E3%80%82%0A%0A%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%EF%BC%8C%E9%9B%86%E6%88%90%E6%B5%8B%E8%AF%95%E6%9C%89%E4%BB%80%E4%B9%88%E7%94%A8%EF%BC%9F%0A%0A1.%20%E6%94%B9%E8%BF%9B%E4%BA%A7%E5%93%81%E8%B4%A8%E9%87%8F%0A%0A%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95%EF%BC%8C%E5%BE%88%E5%A4%9A%E6%97%B6%E5%80%99%E5%9B%B4%E7%BB%95%E7%9D%80%E4%B8%A4%E4%B8%AA%E9%97%AE%E9%A2%98%EF%BC%9A%0A%0AVerification%E5" title="Digg"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-and-integration-test%2F&amp;title=%E8%87%AA%E5%8A%A8%E5%8C%96%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E8%A6%81%E7%82%B9&amp;notes=%E7%94%A8%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%9A%84%E6%A1%86%E6%9E%B6MSTEST%EF%BC%8C%E5%81%9A%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%EF%BC%8C%E9%9B%86%E6%88%90%E6%B5%8B%E8%AF%95%E5%BF%AB1%E5%B9%B4%E4%BA%86%EF%BC%8C%E6%80%BB%E7%BB%93%E4%B8%80%E4%B8%8B%E5%B7%A5%E4%BD%9C%E4%B8%AD%E5%AD%A6%E5%88%B0%E9%83%BD%E4%B8%9C%E8%A5%BF%E3%80%82%0A%0A%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%EF%BC%8C%E9%9B%86%E6%88%90%E6%B5%8B%E8%AF%95%E6%9C%89%E4%BB%80%E4%B9%88%E7%94%A8%EF%BC%9F%0A%0A1.%20%E6%94%B9%E8%BF%9B%E4%BA%A7%E5%93%81%E8%B4%A8%E9%87%8F%0A%0A%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95%EF%BC%8C%E5%BE%88%E5%A4%9A%E6%97%B6%E5%80%99%E5%9B%B4%E7%BB%95%E7%9D%80%E4%B8%A4%E4%B8%AA%E9%97%AE%E9%A2%98%EF%BC%9A%0A%0AVerification%E5" title="del.icio.us"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-and-integration-test%2F&amp;t=%E8%87%AA%E5%8A%A8%E5%8C%96%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E8%A6%81%E7%82%B9" title="Facebook"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-and-integration-test%2F&title=%E8%87%AA%E5%8A%A8%E5%8C%96%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E8%A6%81%E7%82%B9" title="豆瓣"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban.png" title="豆瓣" alt="豆瓣" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-and-integration-test%2F&title=%E8%87%AA%E5%8A%A8%E5%8C%96%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E8%A6%81%E7%82%B9&n=1" title="豆瓣九点"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban9.png" title="豆瓣九点" alt="豆瓣九点" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.friendfeed.com/share?title=%E8%87%AA%E5%8A%A8%E5%8C%96%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E8%A6%81%E7%82%B9&amp;link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-and-integration-test%2F" title="FriendFeed"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-and-integration-test%2F&amp;title=%E8%87%AA%E5%8A%A8%E5%8C%96%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E8%A6%81%E7%82%B9" title="Live"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/live.png" title="Live" alt="Live" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://ping.fm/ref/?link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-and-integration-test%2F&amp;title=%E8%87%AA%E5%8A%A8%E5%8C%96%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E8%A6%81%E7%82%B9&amp;body=%E7%94%A8%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%9A%84%E6%A1%86%E6%9E%B6MSTEST%EF%BC%8C%E5%81%9A%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%EF%BC%8C%E9%9B%86%E6%88%90%E6%B5%8B%E8%AF%95%E5%BF%AB1%E5%B9%B4%E4%BA%86%EF%BC%8C%E6%80%BB%E7%BB%93%E4%B8%80%E4%B8%8B%E5%B7%A5%E4%BD%9C%E4%B8%AD%E5%AD%A6%E5%88%B0%E9%83%BD%E4%B8%9C%E8%A5%BF%E3%80%82%0A%0A%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%EF%BC%8C%E9%9B%86%E6%88%90%E6%B5%8B%E8%AF%95%E6%9C%89%E4%BB%80%E4%B9%88%E7%94%A8%EF%BC%9F%0A%0A1.%20%E6%94%B9%E8%BF%9B%E4%BA%A7%E5%93%81%E8%B4%A8%E9%87%8F%0A%0A%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95%EF%BC%8C%E5%BE%88%E5%A4%9A%E6%97%B6%E5%80%99%E5%9B%B4%E7%BB%95%E7%9D%80%E4%B8%A4%E4%B8%AA%E9%97%AE%E9%A2%98%EF%BC%9A%0A%0AVerification%E5" title="Ping.fm"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/ping.png" title="Ping.fm" alt="Ping.fm" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://shuqian.qq.com/post?jumpback=1&title=%E8%87%AA%E5%8A%A8%E5%8C%96%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E8%A6%81%E7%82%B9&uri=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-and-integration-test%2F" title="QQ书签"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/qq.png" title="QQ书签" alt="QQ书签" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=%E8%87%AA%E5%8A%A8%E5%8C%96%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E8%A6%81%E7%82%B9%20-%20http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-and-integration-test%2F" title="Twitter"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>

<p>Related posts:<ol><li><a href='http://magustest.com/blog/readingdaily/software-testing-note-part-three/' rel='bookmark' title='Permanent Link: 《Software Testing》第三章 &#8211; 软件测试'>《Software Testing》第三章 &#8211; 软件测试</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/exception-handling-in-unit-test/' rel='bookmark' title='Permanent Link: 单元测试中的异常处理'>单元测试中的异常处理</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/whiteboxtesting/unit-test-and-integration-test/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>自动化白盒测试工具PEX应用实例 &#8211; 发现ZUNE死机的BUG</title>
		<link>http://magustest.com/blog/whiteboxtesting/using-pex-in-unit-test/</link>
		<comments>http://magustest.com/blog/whiteboxtesting/using-pex-in-unit-test/#comments</comments>
		<pubDate>Sat, 10 Jan 2009 06:26:34 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[白盒测试]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[PEX]]></category>
		<category><![CDATA[单元测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=306</guid>
		<description><![CDATA[在12月的时候，我在博客里面介绍了一个自动化单元测试工具&#8211;PEX。在上一篇博客中，又讲述了微软ZUNE在闰年最后一天死机的原因。现在把这两篇文章串起来，跟大家分享一下如何用PEX帮助改善代码的质量。 首先来看一下用PEX测试ZUNE处理日期的方法的结果，如图： 大家可以复习一下被测代码： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 while &#40;days &#62; 365&#41; &#123; if &#40;DateTime.IsLeapYear&#40;year&#41;&#41; &#123; if &#40;days &#62; 366&#41; &#123; days -= 366; year += 1; &#125; &#125; else &#123; days -= 365; year += 1; &#125; &#125; 从图中可以看到PEX总共运行了73次，产生了5个测试用例，其中2个测试用例是运行失败的，还有2个测试用例在运行过程中超出了设定的运行次数（其实这2个用例就找到了ZUNE的那个BUG）。我们分别来看看PEX生成的几个用例。第一行测试数据是days=0, year=1；这条测试数据是能够通过测试的。第二行和第三行测试数据是测试运行失败的，days是一个很大的整数，这两个测试虽然是失败的测试，但是不需要关心，因为实际中日期不可能到达那个数值，所以可以认为这是无效的测试数据。再来看最后的两条测试数据，都是超过了单个测试运行的次数，可以怀疑其中有死循环。 经过PEX初步的诊断，我们需要给PEX增加一些限制，使得生成的测试数据更加有代表性，更加有意义。 1 2 [...]


Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/100-percent-statement-coverage-not-enough/' rel='bookmark' title='Permanent Link: 微软ZUNE死机原因&#8211;单元测试百分百语句覆盖率是不够的'>微软ZUNE死机原因&#8211;单元测试百分百语句覆盖率是不够的</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/refactoring-unit-test/' rel='bookmark' title='Permanent Link: 测试代码重构实例'>测试代码重构实例</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/unit-test-pattern/' rel='bookmark' title='Permanent Link: 单元测试中的常用测试模式'>单元测试中的常用测试模式</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>在12月的时候，我在博客里面介绍了一个<a href="http://magustest.com/blog/softwaretesting/whiteboxtesting/introduction-to-pex-automated-white-box-testing-for-dotnet/" target="_blank">自动化单元测试工具&#8211;PEX</a>。在上一篇博客中，又讲述了<a href="http://magustest.com/blog/softwaretesting/whiteboxtesting/100-percent-statement-coverage-not-enough/" target="_blank">微软ZUNE在闰年最后一天死机的原因</a>。现在把这两篇文章串起来，跟大家分享一下如何用PEX帮助改善代码的质量。</p>
<p>首先来看一下用PEX测试ZUNE处理日期的方法的结果，如图：</p>
<p><a href="http://magustest.com/blog/wp-content/uploads/2009/01/no-assumtion1.png"><img class="alignnone size-full wp-image-307" title="no-assumtion" src="http://magustest.com/blog/wp-content/uploads/2009/01/no-assumtion1.png" alt="" width="500" height="198" /></a><br />
<span id="more-306"></span><br />
大家可以复习一下被测代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span>days <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">365</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>DateTime.<span style="color: #0000FF;">IsLeapYear</span><span style="color: #000000;">&#40;</span>year<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
	<span style="color: #000000;">&#123;</span>
		<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>days <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">366</span><span style="color: #000000;">&#41;</span>
		<span style="color: #000000;">&#123;</span>
			days <span style="color: #008000;">-=</span> <span style="color: #FF0000;">366</span><span style="color: #008000;">;</span>
			year <span style="color: #008000;">+=</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
		<span style="color: #000000;">&#125;</span>
	<span style="color: #000000;">&#125;</span>
	<span style="color: #0600FF;">else</span>
	<span style="color: #000000;">&#123;</span>
		days <span style="color: #008000;">-=</span> <span style="color: #FF0000;">365</span><span style="color: #008000;">;</span>
		year <span style="color: #008000;">+=</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>从图中可以看到PEX总共运行了73次，产生了5个测试用例，其中2个测试用例是运行失败的，还有2个测试用例在运行过程中超出了设定的运行次数（其实这2个用例就找到了ZUNE的那个BUG）。我们分别来看看PEX生成的几个用例。第一行测试数据是days=0, year=1；这条测试数据是能够通过测试的。第二行和第三行测试数据是测试运行失败的，days是一个很大的整数，这两个测试虽然是失败的测试，但是不需要关心，因为实际中日期不可能到达那个数值，所以可以认为这是无效的测试数据。再来看最后的两条测试数据，都是超过了单个测试运行的次数，可以怀疑其中有死循环。</p>
<p>经过PEX初步的诊断，我们需要给PEX增加一些限制，使得生成的测试数据更加有代表性，更加有意义。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>PexMethod<span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> abcd<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> days, <span style="color: #FF0000;">int</span> year<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	PexAssume.<span style="color: #0000FF;">IsTrue</span><span style="color: #000000;">&#40;</span>days <span style="color: #008000;">&lt;</span> <span style="color: #FF0000;">367</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	PexAssume.<span style="color: #0000FF;">IsTrue</span><span style="color: #000000;">&#40;</span>days <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	PexAssume.<span style="color: #0000FF;">IsTrue</span><span style="color: #000000;">&#40;</span>year <span style="color: #008000;">&lt;</span> <span style="color: #FF0000;">3001</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	PexAssume.<span style="color: #0000FF;">IsTrue</span><span style="color: #000000;">&#40;</span>year <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	Class1.<span style="color: #0000FF;">AddDay</span><span style="color: #000000;">&#40;</span>days, year<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>在调用被测方法之前，是4条PexAssume语句，这4条语句可以告诉PEX，需要生成的测试数据中days是在1到369之间取值， year是在1到2999之间取值。有了这样的限制以后，PEX产生是结果会更加好，见下图：</p>
<p><a href="http://magustest.com/blog/wp-content/uploads/2009/01/pex_result1.png"><img class="alignnone size-full wp-image-311" title="pex_result" src="http://magustest.com/blog/wp-content/uploads/2009/01/pex_result1.png" alt="" width="485" height="157" /></a></p>
<p>点击最后一条测试结果，查看Details：</p>
<p><a href="http://magustest.com/blog/wp-content/uploads/2009/01/test-case-for-endless-loop1.png"><img class="alignnone size-full wp-image-312" title="test-case-for-endless-loop" src="http://magustest.com/blog/wp-content/uploads/2009/01/test-case-for-endless-loop1.png" alt="" width="499" height="246" /></a></p>
<p>我们可以看到已经生成了普通的单元测试了。这个单元测试就可以留着以后做回归测试用了。</p>
<p>把他复制到相应的CS文件中，然后删除掉Ignore属性，Description属性可要可不要。最后测试如下：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestMethod<span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> abcd24<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">abcd</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">366</span>, <span style="color: #FF0000;">400</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>PEX可以说是一个革命性的测试工具，如果有兴趣的朋友可以上<a href="http://social.msdn.microsoft.com/Forums/en-US/pex/threads/" target="_blank">MSDN论坛的PEX版块</a>学习。</p>



Share and Enjoy:


	<a rel="nofollow"  target="_blank" href="http://magustest.com/blog/feed/" title="RSS"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/rss.png" title="RSS" alt="RSS" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fusing-pex-in-unit-test%2F&amp;t=%E8%87%AA%E5%8A%A8%E5%8C%96%E7%99%BD%E7%9B%92%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7PEX%E5%BA%94%E7%94%A8%E5%AE%9E%E4%BE%8B%20-%20%E5%8F%91%E7%8E%B0ZUNE%E6%AD%BB%E6%9C%BA%E7%9A%84BUG" title="Facebook"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fusing-pex-in-unit-test%2F&title=%E8%87%AA%E5%8A%A8%E5%8C%96%E7%99%BD%E7%9B%92%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7PEX%E5%BA%94%E7%94%A8%E5%AE%9E%E4%BE%8B%20-%20%E5%8F%91%E7%8E%B0ZUNE%E6%AD%BB%E6%9C%BA%E7%9A%84BUG" title="豆瓣"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban.png" title="豆瓣" alt="豆瓣" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fusing-pex-in-unit-test%2F&title=%E8%87%AA%E5%8A%A8%E5%8C%96%E7%99%BD%E7%9B%92%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7PEX%E5%BA%94%E7%94%A8%E5%AE%9E%E4%BE%8B%20-%20%E5%8F%91%E7%8E%B0ZUNE%E6%AD%BB%E6%9C%BA%E7%9A%84BUG&n=1" title="豆瓣九点"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban9.png" title="豆瓣九点" alt="豆瓣九点" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.friendfeed.com/share?title=%E8%87%AA%E5%8A%A8%E5%8C%96%E7%99%BD%E7%9B%92%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7PEX%E5%BA%94%E7%94%A8%E5%AE%9E%E4%BE%8B%20-%20%E5%8F%91%E7%8E%B0ZUNE%E6%AD%BB%E6%9C%BA%E7%9A%84BUG&amp;link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fusing-pex-in-unit-test%2F" title="FriendFeed"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fusing-pex-in-unit-test%2F&amp;title=%E8%87%AA%E5%8A%A8%E5%8C%96%E7%99%BD%E7%9B%92%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7PEX%E5%BA%94%E7%94%A8%E5%AE%9E%E4%BE%8B%20-%20%E5%8F%91%E7%8E%B0ZUNE%E6%AD%BB%E6%9C%BA%E7%9A%84BUG" title="Live"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/live.png" title="Live" alt="Live" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/ping.png" title="Ping.fm" alt="Ping.fm" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://shuqian.qq.com/post?jumpback=1&title=%E8%87%AA%E5%8A%A8%E5%8C%96%E7%99%BD%E7%9B%92%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7PEX%E5%BA%94%E7%94%A8%E5%AE%9E%E4%BE%8B%20-%20%E5%8F%91%E7%8E%B0ZUNE%E6%AD%BB%E6%9C%BA%E7%9A%84BUG&uri=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fusing-pex-in-unit-test%2F" title="QQ书签"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/qq.png" title="QQ书签" alt="QQ书签" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=%E8%87%AA%E5%8A%A8%E5%8C%96%E7%99%BD%E7%9B%92%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7PEX%E5%BA%94%E7%94%A8%E5%AE%9E%E4%BE%8B%20-%20%E5%8F%91%E7%8E%B0ZUNE%E6%AD%BB%E6%9C%BA%E7%9A%84BUG%20-%20http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fusing-pex-in-unit-test%2F" title="Twitter"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>

<p>Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/100-percent-statement-coverage-not-enough/' rel='bookmark' title='Permanent Link: 微软ZUNE死机原因&#8211;单元测试百分百语句覆盖率是不够的'>微软ZUNE死机原因&#8211;单元测试百分百语句覆盖率是不够的</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/refactoring-unit-test/' rel='bookmark' title='Permanent Link: 测试代码重构实例'>测试代码重构实例</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/unit-test-pattern/' rel='bookmark' title='Permanent Link: 单元测试中的常用测试模式'>单元测试中的常用测试模式</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/whiteboxtesting/using-pex-in-unit-test/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>微软ZUNE死机原因&#8211;单元测试百分百语句覆盖率是不够的</title>
		<link>http://magustest.com/blog/whiteboxtesting/100-percent-statement-coverage-not-enough/</link>
		<comments>http://magustest.com/blog/whiteboxtesting/100-percent-statement-coverage-not-enough/#comments</comments>
		<pubDate>Wed, 07 Jan 2009 08:22:33 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[白盒测试]]></category>
		<category><![CDATA[代码覆盖]]></category>
		<category><![CDATA[单元测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=269</guid>
		<description><![CDATA[微软的30GB版本Zune在08年的最后一天出现了大规模死机的现象，原因其实就是一行代码原本应该写为大于等于，但是实际上写成了大于。下面来看看具体的代码，第5行就是导致死机的代码。 while (days > 365) { if (DateTime.IsLeapYear(year)) { if (days > 366) { days -= 366; year += 1; } } else { days -= 365; year += 1; } } 这是ZUNE处理时间的一段代码，每年的最后一天（days=365）向第二年的第一天（days要加1）过度的时候会做一个处理。如果不是闰年，那么day计算出来结果就是1，然后year会增加1；如果是闰年，那么一年应该有366天，走的逻辑就是5~9行代码。2008年31号ZUNE死机的原因就是，days=366，years=2008，会出现死循环。下面来写一个单元测试，来测试一下这一段代码块。 [TestMethod()] public void AddDayTest() { int[] arrdays = new int[] { -1, 0, 1, 66, 365, 367, 367 }; int[] arryear = [...]


Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/using-pex-in-unit-test/' rel='bookmark' title='Permanent Link: 自动化白盒测试工具PEX应用实例 &#8211; 发现ZUNE死机的BUG'>自动化白盒测试工具PEX应用实例 &#8211; 发现ZUNE死机的BUG</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/unit-test-pattern/' rel='bookmark' title='Permanent Link: 单元测试中的常用测试模式'>单元测试中的常用测试模式</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/refactoring-unit-test/' rel='bookmark' title='Permanent Link: 测试代码重构实例'>测试代码重构实例</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.cnbeta.com/articles/73748.htm" target="_blank">微软的30GB版本Zune在08年的最后一天出现了大规模死机的现象</a>，原因其实就是一行代码原本应该写为大于等于，但是实际上写成了大于。下面来看看具体的代码，第5行就是导致死机的代码。</p>
<pre lang="csharp" colla="+">while (days > 365)
{
	if (DateTime.IsLeapYear(year))
	{
		if (days > 366)
		{
			days -= 366;
			year += 1;
		}
	}
	else
	{
		days -= 365;
		year += 1;
	}
}</pre>
<p><span id="more-269"></span><br />
这是ZUNE处理时间的一段代码，每年的最后一天（days=365）向第二年的第一天（days要加1）过度的时候会做一个处理。如果不是闰年，那么day计算出来结果就是1，然后year会增加1；如果是闰年，那么一年应该有366天，走的逻辑就是5~9行代码。2008年31号ZUNE死机的原因就是，days=366，years=2008，会出现死循环。下面来写一个单元测试，来测试一下这一段代码块。</p>
<pre lang="csharp"  colla="+">[TestMethod()]
public void AddDayTest()
{
    int[] arrdays = new int[] { -1, 0, 1, 66, 365, 367, 367 };
    int[] arryear = new int[] { -1, 0, 1, 66, 2008, 2008, 367 };
    for (int i = 0; i > arrdays.Length; i++)
    {
        int days = arrdays[i];
        int year = arryear[i];
        Class1.AddDay(days, year);
    }
}</pre>
<p>一段很简单的测试代码，里面的测试数据不是很讲究，大家将就着看吧，取这些测试数据就能达到VSTS里面的语句覆盖率达到100%。如图：AddDay方法语句覆盖率已经达到100%</p>
<p><a href="http://magustest.com/blog/wp-content/uploads/2009/01/100_code_coverage_21.png"><img class="alignnone size-full wp-image-273" title="100_code_coverage_2" src="http://magustest.com/blog/wp-content/uploads/2009/01/100_code_coverage_21.png" alt="" width="500" height="58" /></a></p>
<p>下图是具体代码，整个方法体的代码都是浅蓝色，代码都被覆盖到了</p>
<p><a href="http://magustest.com/blog/wp-content/uploads/2009/01/100_code_coverage1.png"><img class="alignnone size-full wp-image-274" title="100_code_coverage" src="http://magustest.com/blog/wp-content/uploads/2009/01/100_code_coverage1.png" alt="" width="448" height="410" /></a></p>
<p>回头看看测试数据，虽然达到了100%语句覆盖，但是依然遗漏了“闰年，366天”这样一条数据，只要我们用这条测试数据来测试，就能发现错误了。</p>
<p>下面来说说用VSTS做单元测试，通过一些设置来帮助我们发现类似这个死循环的BUG。在VSTS里面，可以设置每个单元测试的超时时间，默认是30分钟，这样对于发现一些出现死循环的BUG不太有利。很多人都说过，单元测试的一个特点就是&#8211;快！因为测试只是检查一小个单元是否能正常工作。如果一个“单元测试”需要几分钟，那么几乎可以很肯定地说，这不是一个单元测试，这个测试肯定跟外界有很多交互，例如读取一个外部文件？读取数据库？请求一个web service等等。在Test run config里面，把超时时间设置为10秒，如果一个测试会导致死循环，那么10秒后，就会提示我们该单元测试出现超时，如图：</p>
<p><a href="http://magustest.com/blog/wp-content/uploads/2009/01/test_config_modify1.png"><img class="alignnone size-full wp-image-276" title="test_config_modify" src="http://magustest.com/blog/wp-content/uploads/2009/01/test_config_modify1.png" alt="" width="500" height="355" /></a></p>
<p>设置好了以后运行一下单元测试：</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestMethod<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> AddDayTest1<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #FF0000;">int</span> days <span style="color: #008000;">=</span> <span style="color: #FF0000;">366</span><span style="color: #008000;">;</span>
    <span style="color: #FF0000;">int</span> year <span style="color: #008000;">=</span> <span style="color: #FF0000;">2008</span><span style="color: #008000;">;</span>
    Class1.<span style="color: #0000FF;">AddDay</span><span style="color: #000000;">&#40;</span>days, year<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>出现结果：</p>
<p><a href="http://magustest.com/blog/wp-content/uploads/2009/01/test_timeout1.png"><img class="alignnone size-full wp-image-278" title="test_timeout" src="http://magustest.com/blog/wp-content/uploads/2009/01/test_timeout1.png" alt="" width="500" height="117" /></a></p>
<p>很好，我们可以在比较短的时间内发现问题，而不是观察CPU占用率长期达到100%。</p>
<p>总结：现在的代码覆盖率工具，大部分都只有语句覆盖的功能，而语句覆盖 又是众多代码覆盖标准里面最弱的一种。有时候做白盒的测试（单元，集成……），会很容易掉进一个陷阱，就是看着代码覆盖率工具给出的结果，来提高自己测试代码覆盖率。这样代码的覆盖率上去了，但是代码的质量却不见的能有提高。以后做测试的时候，也应该把精力放在关键部分的代码逻辑的验证上，不要老盯着覆盖率往上涨。</p>



Share and Enjoy:


	<a rel="nofollow"  target="_blank" href="http://magustest.com/blog/feed/" title="RSS"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/rss.png" title="RSS" alt="RSS" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2F100-percent-statement-coverage-not-enough%2F&amp;t=%E5%BE%AE%E8%BD%AFZUNE%E6%AD%BB%E6%9C%BA%E5%8E%9F%E5%9B%A0--%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%99%BE%E5%88%86%E7%99%BE%E8%AF%AD%E5%8F%A5%E8%A6%86%E7%9B%96%E7%8E%87%E6%98%AF%E4%B8%8D%E5%A4%9F%E7%9A%84" title="Facebook"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2F100-percent-statement-coverage-not-enough%2F&title=%E5%BE%AE%E8%BD%AFZUNE%E6%AD%BB%E6%9C%BA%E5%8E%9F%E5%9B%A0--%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%99%BE%E5%88%86%E7%99%BE%E8%AF%AD%E5%8F%A5%E8%A6%86%E7%9B%96%E7%8E%87%E6%98%AF%E4%B8%8D%E5%A4%9F%E7%9A%84" title="豆瓣"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban.png" title="豆瓣" alt="豆瓣" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2F100-percent-statement-coverage-not-enough%2F&title=%E5%BE%AE%E8%BD%AFZUNE%E6%AD%BB%E6%9C%BA%E5%8E%9F%E5%9B%A0--%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%99%BE%E5%88%86%E7%99%BE%E8%AF%AD%E5%8F%A5%E8%A6%86%E7%9B%96%E7%8E%87%E6%98%AF%E4%B8%8D%E5%A4%9F%E7%9A%84&n=1" title="豆瓣九点"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban9.png" title="豆瓣九点" alt="豆瓣九点" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.friendfeed.com/share?title=%E5%BE%AE%E8%BD%AFZUNE%E6%AD%BB%E6%9C%BA%E5%8E%9F%E5%9B%A0--%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%99%BE%E5%88%86%E7%99%BE%E8%AF%AD%E5%8F%A5%E8%A6%86%E7%9B%96%E7%8E%87%E6%98%AF%E4%B8%8D%E5%A4%9F%E7%9A%84&amp;link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2F100-percent-statement-coverage-not-enough%2F" title="FriendFeed"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2F100-percent-statement-coverage-not-enough%2F&amp;title=%E5%BE%AE%E8%BD%AFZUNE%E6%AD%BB%E6%9C%BA%E5%8E%9F%E5%9B%A0--%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%99%BE%E5%88%86%E7%99%BE%E8%AF%AD%E5%8F%A5%E8%A6%86%E7%9B%96%E7%8E%87%E6%98%AF%E4%B8%8D%E5%A4%9F%E7%9A%84" title="Live"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/live.png" title="Live" alt="Live" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/ping.png" title="Ping.fm" alt="Ping.fm" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://shuqian.qq.com/post?jumpback=1&title=%E5%BE%AE%E8%BD%AFZUNE%E6%AD%BB%E6%9C%BA%E5%8E%9F%E5%9B%A0--%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%99%BE%E5%88%86%E7%99%BE%E8%AF%AD%E5%8F%A5%E8%A6%86%E7%9B%96%E7%8E%87%E6%98%AF%E4%B8%8D%E5%A4%9F%E7%9A%84&uri=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2F100-percent-statement-coverage-not-enough%2F" title="QQ书签"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/qq.png" title="QQ书签" alt="QQ书签" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=%E5%BE%AE%E8%BD%AFZUNE%E6%AD%BB%E6%9C%BA%E5%8E%9F%E5%9B%A0--%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%99%BE%E5%88%86%E7%99%BE%E8%AF%AD%E5%8F%A5%E8%A6%86%E7%9B%96%E7%8E%87%E6%98%AF%E4%B8%8D%E5%A4%9F%E7%9A%84%20-%20http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2F100-percent-statement-coverage-not-enough%2F" title="Twitter"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>

<p>Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/using-pex-in-unit-test/' rel='bookmark' title='Permanent Link: 自动化白盒测试工具PEX应用实例 &#8211; 发现ZUNE死机的BUG'>自动化白盒测试工具PEX应用实例 &#8211; 发现ZUNE死机的BUG</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/unit-test-pattern/' rel='bookmark' title='Permanent Link: 单元测试中的常用测试模式'>单元测试中的常用测试模式</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/refactoring-unit-test/' rel='bookmark' title='Permanent Link: 测试代码重构实例'>测试代码重构实例</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/whiteboxtesting/100-percent-statement-coverage-not-enough/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>在ASP.NET单元测试中进行调试</title>
		<link>http://magustest.com/blog/whiteboxtesting/how-to-debug-in-aspdotnet-unit-test/</link>
		<comments>http://magustest.com/blog/whiteboxtesting/how-to-debug-in-aspdotnet-unit-test/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 13:10:07 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[白盒测试]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[单元测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=237</guid>
		<description><![CDATA[在前一篇关于在单元测试中使用HttpContext的文章中，本人提到了用ASP.NET单元测试的一个缺点是不能调试，今天我推翻我自己错误的论调，其实在ASP.NET单元测试中也是能调试的。 以前我以为ASP.NET单元测试就运行于WEB服务器上，所以我用Debug来运行，那么ASP.NET单元测试就自动Attach到Web服务器，就能调试了。但是实际上要让ASP.NET单元测试可以调试的话，正确的做法应该是： 在Web.config中，找到&#60;compilation debug=&#8221;false&#8221;/&#62;这个节点，然后把debug属性改为true 在ASP.NET单元测试代码的最开始处添加这样一句话“System.Diagnostics.Debugger.Break()” 运行该ASP.NET单元测试 在运行单元测试的时候，会有一个提示框出来，说程序遇到一个断点，是否进入调试，当然是选择调试啦。如图： 选中Debug这个程序以后，会有第二个提示框出来，让我们选择用哪个程序来进行调试，可以选择一个合适的VSTS，如图： 选上一个VSTS的实例以后，程序就会停在System.Diagnostics.Debugger.Break()这条语句上，这时候再按一下F5，让程序继续运行，当程序遇到下一个断点，就会停下来了，从此就可以调试ASP.NET的单元测试了。 Share and Enjoy: No related posts.


No related posts.]]></description>
			<content:encoded><![CDATA[<p>在前一篇关于<a href="http://magustest.com/blog/softwaretesting/using-httpcontext-in-unittest/" target="_blank">在单元测试中使用HttpContext</a>的文章中，本人提到了用ASP.NET单元测试的一个缺点是不能调试，今天我推翻我自己错误的论调，其实在ASP.NET单元测试中也是能调试的。</p>
<p>以前我以为ASP.NET单元测试就运行于WEB服务器上，所以我用Debug来运行，那么ASP.NET单元测试就自动Attach到Web服务器，就能调试了。但是实际上要让ASP.NET单元测试可以调试的话，正确的做法应该是：</p>
<ol>
<li>在Web.config中，找到&lt;compilation debug=&#8221;false&#8221;/&gt;这个节点，然后把debug属性改为true</li>
<li>在ASP.NET单元测试代码的最开始处添加这样一句话“System.Diagnostics.Debugger.Break()”</li>
<li>运行该ASP.NET单元测试</li>
</ol>
<p>在运行单元测试的时候，会有一个提示框出来，说程序遇到一个断点，是否进入调试，当然是选择调试啦。如图：<br />
<span id="more-237"></span><br />
<a href="http://magustest.com/blog/wp-content/uploads/2008/12/asddotnet-unit-test-prompt1.png"><img class="alignnone size-full wp-image-240" title="asddotnet-unit-test-prompt" src="http://magustest.com/blog/wp-content/uploads/2008/12/asddotnet-unit-test-prompt1.png" alt="" width="500" height="295" /></a></p>
<p>选中Debug这个程序以后，会有第二个提示框出来，让我们选择用哪个程序来进行调试，可以选择一个合适的VSTS，如图：</p>
<p><a href="http://magustest.com/blog/wp-content/uploads/2008/12/asddotnet-unit-test-select-vsts1.png"><img class="alignnone size-full wp-image-241" title="asddotnet-unit-test-select-vsts" src="http://magustest.com/blog/wp-content/uploads/2008/12/asddotnet-unit-test-select-vsts1.png" alt="" width="408" height="441" /></a></p>
<p>选上一个VSTS的实例以后，程序就会停在System.Diagnostics.Debugger.Break()这条语句上，这时候再按一下F5，让程序继续运行，当程序遇到下一个断点，就会停下来了，从此就可以调试ASP.NET的单元测试了。</p>



Share and Enjoy:


	<a rel="nofollow"  target="_blank" href="http://magustest.com/blog/feed/" title="RSS"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/rss.png" title="RSS" alt="RSS" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fhow-to-debug-in-aspdotnet-unit-test%2F&amp;title=%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E8%BF%9B%E8%A1%8C%E8%B0%83%E8%AF%95&amp;bodytext=%E5%9C%A8%E5%89%8D%E4%B8%80%E7%AF%87%E5%85%B3%E4%BA%8E%E5%9C%A8%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E6%96%87%E7%AB%A0%E4%B8%AD%EF%BC%8C%E6%9C%AC%E4%BA%BA%E6%8F%90%E5%88%B0%E4%BA%86%E7%94%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%9A%84%E4%B8%80%E4%B8%AA%E7%BC%BA%E7%82%B9%E6%98%AF%E4%B8%8D%E8%83%BD%E8%B0%83%E8%AF%95%EF%BC%8C%E4%BB%8A%E5%A4%A9%E6%88%91%E6%8E%A8%E7%BF%BB%E6%88%91%E8%87%AA%E5%B7%B1%E9%94%99%E8%AF%AF%E7%9A%84%E8%AE%BA%E8%B0%83%EF%BC%8C%E5%85%B6%E5%AE%9E%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%B9%9F%E6%98%AF%E8%83%BD%E8%B0%83%E8%AF%95%E7%9A%84%E3%80%82%0A%0A%E4%BB%A5%E5%89%8D%E6%88%91%E4%BB%A5%E4%B8%BAA" title="Digg"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fhow-to-debug-in-aspdotnet-unit-test%2F&amp;title=%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E8%BF%9B%E8%A1%8C%E8%B0%83%E8%AF%95&amp;notes=%E5%9C%A8%E5%89%8D%E4%B8%80%E7%AF%87%E5%85%B3%E4%BA%8E%E5%9C%A8%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E6%96%87%E7%AB%A0%E4%B8%AD%EF%BC%8C%E6%9C%AC%E4%BA%BA%E6%8F%90%E5%88%B0%E4%BA%86%E7%94%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%9A%84%E4%B8%80%E4%B8%AA%E7%BC%BA%E7%82%B9%E6%98%AF%E4%B8%8D%E8%83%BD%E8%B0%83%E8%AF%95%EF%BC%8C%E4%BB%8A%E5%A4%A9%E6%88%91%E6%8E%A8%E7%BF%BB%E6%88%91%E8%87%AA%E5%B7%B1%E9%94%99%E8%AF%AF%E7%9A%84%E8%AE%BA%E8%B0%83%EF%BC%8C%E5%85%B6%E5%AE%9E%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%B9%9F%E6%98%AF%E8%83%BD%E8%B0%83%E8%AF%95%E7%9A%84%E3%80%82%0A%0A%E4%BB%A5%E5%89%8D%E6%88%91%E4%BB%A5%E4%B8%BAA" title="del.icio.us"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fhow-to-debug-in-aspdotnet-unit-test%2F&amp;t=%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E8%BF%9B%E8%A1%8C%E8%B0%83%E8%AF%95" title="Facebook"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fhow-to-debug-in-aspdotnet-unit-test%2F&title=%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E8%BF%9B%E8%A1%8C%E8%B0%83%E8%AF%95" title="豆瓣"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban.png" title="豆瓣" alt="豆瓣" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fhow-to-debug-in-aspdotnet-unit-test%2F&title=%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E8%BF%9B%E8%A1%8C%E8%B0%83%E8%AF%95&n=1" title="豆瓣九点"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban9.png" title="豆瓣九点" alt="豆瓣九点" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.friendfeed.com/share?title=%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E8%BF%9B%E8%A1%8C%E8%B0%83%E8%AF%95&amp;link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fhow-to-debug-in-aspdotnet-unit-test%2F" title="FriendFeed"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fhow-to-debug-in-aspdotnet-unit-test%2F&amp;title=%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E8%BF%9B%E8%A1%8C%E8%B0%83%E8%AF%95" title="Live"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/live.png" title="Live" alt="Live" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://ping.fm/ref/?link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fhow-to-debug-in-aspdotnet-unit-test%2F&amp;title=%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E8%BF%9B%E8%A1%8C%E8%B0%83%E8%AF%95&amp;body=%E5%9C%A8%E5%89%8D%E4%B8%80%E7%AF%87%E5%85%B3%E4%BA%8E%E5%9C%A8%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E6%96%87%E7%AB%A0%E4%B8%AD%EF%BC%8C%E6%9C%AC%E4%BA%BA%E6%8F%90%E5%88%B0%E4%BA%86%E7%94%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E7%9A%84%E4%B8%80%E4%B8%AA%E7%BC%BA%E7%82%B9%E6%98%AF%E4%B8%8D%E8%83%BD%E8%B0%83%E8%AF%95%EF%BC%8C%E4%BB%8A%E5%A4%A9%E6%88%91%E6%8E%A8%E7%BF%BB%E6%88%91%E8%87%AA%E5%B7%B1%E9%94%99%E8%AF%AF%E7%9A%84%E8%AE%BA%E8%B0%83%EF%BC%8C%E5%85%B6%E5%AE%9E%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%B9%9F%E6%98%AF%E8%83%BD%E8%B0%83%E8%AF%95%E7%9A%84%E3%80%82%0A%0A%E4%BB%A5%E5%89%8D%E6%88%91%E4%BB%A5%E4%B8%BAA" title="Ping.fm"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/ping.png" title="Ping.fm" alt="Ping.fm" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://shuqian.qq.com/post?jumpback=1&title=%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E8%BF%9B%E8%A1%8C%E8%B0%83%E8%AF%95&uri=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fhow-to-debug-in-aspdotnet-unit-test%2F" title="QQ书签"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/qq.png" title="QQ书签" alt="QQ书签" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=%E5%9C%A8ASP.NET%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E8%BF%9B%E8%A1%8C%E8%B0%83%E8%AF%95%20-%20http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fhow-to-debug-in-aspdotnet-unit-test%2F" title="Twitter"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/whiteboxtesting/how-to-debug-in-aspdotnet-unit-test/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>在C#单元测试中使用HttpContext的简单解决办法</title>
		<link>http://magustest.com/blog/softwaretesting/using-httpcontext-in-unittest/</link>
		<comments>http://magustest.com/blog/softwaretesting/using-httpcontext-in-unittest/#comments</comments>
		<pubDate>Sat, 20 Dec 2008 07:31:59 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[软件测试]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[单元测试]]></category>
		<category><![CDATA[白盒测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=233</guid>
		<description><![CDATA[场景：最近在测试一个.NET的Http Module，这个Module是用来做URL重写的。刚开始进展的比较顺利，因为该Module里面的方法参数基本上都是String，后来这个Module进行了一下重构，所有参数都变成了HttpContext了，这就直接导致原来的单元测试都跑不起来了，接着就开始了弄HttpContext了。 1. 采用Visual Studio自带的ASP.NET单元测试 刚开始我看了一下被测试的代码，虽然说用到了HttpContext，但是有很多地方我都可以绕过去的，意思就是这个HttpContext只是名以上需要的一个参数，只要它不是NULL就可以了，并不影响我的测试，所以我采用了ASP.NET Unit Test的办法来获取一个HttpContext，这个方法实现起来是最简单的，但是会有一些问题，后面会提及到。 首先新建一个WEB项目，然后把被测的Http Module挂到这个新建的WEB项目中。然后就可以配置ASP.NET单元测试，把原来一般的单元测试改造成为一个ASP.NET的单元测试。步骤如下，在测试方法前面加上以下属性 1 2 3 &#91;HostType&#40;&#34;ASP.NET&#34;&#41;&#93; &#91;UrlToTest&#40;&#34;http://localhost:6988/Default.aspx&#34;&#41;&#93; &#91;AspNetDevelopmentServerHost&#40;&#34;D:\\MS_Code\\Public\\UrlRouter.WebTest&#34;, &#34;/&#34;&#41;&#93; [UrlToTest] &#8212; 这个属性指定了运行该单元测试时的URL [HostType] &#8212; 一般的单元测试是在VSTest的宿主进程下运行，所以是没有HttpContext的；如果作为ASP.NET单元测试，那么必须要在ASP.NET宿主进程下运行 [AspNetDevelopmentServerHost] &#8212; 由于我使用了ASP.NET Development Server 作为测试的主机服务器，而不是IIS；所以我需要设置这个属性来指定Web应用程序的完整路径。这里我需要把目录指向刚才新建的WEB项目的路径中。这样子就可以在单元测试中直接使用HttpContext.Current来获取一个HttpContext了。 1 2 3 4 5 6 7 8 9 10 11 &#91;&#91;TestMethod&#93; &#91;HostType&#40;&#34;ASP.NET&#34;&#41;&#93; &#91;AspNetDevelopmentServerHost&#40;&#34;D:\\MS_Code\\Public\\UrlRouter.WebTest&#34;, &#34;/&#34;&#41;&#93; &#91;UrlToTest&#40;&#34;http://localhost:6988/Default.aspx&#34;&#41;&#93; public void Fuseaction_PUT&#40;&#41; &#123; handler = new UrlMapHandler&#40;HttpContext.Current&#41;; Assert.IsNotNull&#40;handler&#41;; result [...]


Related posts:<ol><li><a href='http://magustest.com/blog/net/introduction-to-dotnet-memcached-client/' rel='bookmark' title='Permanent Link: .NET平台上的Memcached客户端介绍'>.NET平台上的Memcached客户端介绍</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/three-different-test-fixture-setup-approach/' rel='bookmark' title='Permanent Link: 单元测试中三种准备Test Fixture的方法比较'>单元测试中三种准备Test Fixture的方法比较</a></li>
<li><a href='http://magustest.com/blog/net/serialize-deserialize-implement-deep-copy/' rel='bookmark' title='Permanent Link: 利用序列化和反序列化实现深拷贝'>利用序列化和反序列化实现深拷贝</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>场景：最近在测试一个.NET的Http Module，这个Module是用来做URL重写的。刚开始进展的比较顺利，因为该Module里面的方法参数基本上都是String，后来这个Module进行了一下重构，所有参数都变成了HttpContext了，这就直接导致原来的单元测试都跑不起来了，接着就开始了弄HttpContext了。</p>
<p><strong><span style="font-size: medium; color: #3366ff;">1. 采用Visual Studio自带的ASP.NET单元测试</span></strong></p>
<p>刚开始我看了一下被测试的代码，虽然说用到了HttpContext，但是有很多地方我都可以绕过去的，意思就是这个HttpContext只是名以上需要的一个参数，只要它不是NULL就可以了，并不影响我的测试，所以我采用了ASP.NET Unit Test的办法来获取一个HttpContext，这个方法实现起来是最简单的，但是会有一些问题，后面会提及到。<br />
<span id="more-233"></span><br />
首先新建一个WEB项目，然后把被测的Http Module挂到这个新建的WEB项目中。然后就可以配置ASP.NET单元测试，把原来一般的单元测试改造成为一个ASP.NET的单元测试。步骤如下，在测试方法前面加上以下属性</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>HostType<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;ASP.NET&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
<span style="color: #000000;">&#91;</span>UrlToTest<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;http://localhost:6988/Default.aspx&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
<span style="color: #000000;">&#91;</span>AspNetDevelopmentServerHost<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;D:<span style="color: #008080; font-weight: bold;">\\</span>MS_Code<span style="color: #008080; font-weight: bold;">\\</span>Public<span style="color: #008080; font-weight: bold;">\\</span>UrlRouter.WebTest&quot;</span>, <span style="color: #666666;">&quot;/&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span></pre></td></tr></table></div>

<p>[UrlToTest] &#8212; 这个属性指定了运行该单元测试时的URL</p>
<p>[HostType] &#8212; 一般的单元测试是在VSTest的宿主进程下运行，所以是没有HttpContext的；如果作为ASP.NET单元测试，那么必须要在ASP.NET宿主进程下运行</p>
<p>[AspNetDevelopmentServerHost] &#8212; 由于我使用了ASP.NET Development Server 作为测试的主机服务器，而不是IIS；所以我需要设置这个属性来指定Web应用程序的完整路径。这里我需要把目录指向刚才新建的WEB项目的路径中。这样子就可以在单元测试中直接使用HttpContext.Current来获取一个HttpContext了。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#91;</span>TestMethod<span style="color: #000000;">&#93;</span>
<span style="color: #000000;">&#91;</span>HostType<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;ASP.NET&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
<span style="color: #000000;">&#91;</span>AspNetDevelopmentServerHost<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;D:<span style="color: #008080; font-weight: bold;">\\</span>MS_Code<span style="color: #008080; font-weight: bold;">\\</span>Public<span style="color: #008080; font-weight: bold;">\\</span>UrlRouter.WebTest&quot;</span>, <span style="color: #666666;">&quot;/&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
<span style="color: #000000;">&#91;</span>UrlToTest<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;http://localhost:6988/Default.aspx&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> Fuseaction_PUT<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
    handler <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> UrlMapHandler<span style="color: #000000;">&#40;</span>HttpContext.<span style="color: #0000FF;">Current</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    Assert.<span style="color: #0000FF;">IsNotNull</span><span style="color: #000000;">&#40;</span>handler<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    result <span style="color: #008000;">=</span> handler.<span style="color: #0000FF;">ExecuteUrlMap</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    StringAssert.<span style="color: #0000FF;">Contains</span><span style="color: #000000;">&#40;</span>result.<span style="color: #0000FF;">Url</span>, <span style="color: #666666;">&quot;expected string&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>这样子初步解决了需要HttpContext的困难，但是会有以下问题：</p>
<ol>
<li>对HttpContext的内容不可控</li>
<li>需要运行ASP.NET Development Server</li>
<li>不能进行调试</li>
</ol>
<p><strong><span style="font-size: medium; color: #3366ff;">2. 直接创建HttpContext实例</span></strong></p>
<p>基于刚才提到的3个不足，我决定直接创建一个HttpContext来解决问题。还好，HttpContext有公开的构造函数，这个构造函数需要接受一个HttpWorkerRequest作为参数，HttpWorkerRequest是一个抽象类，就是不能直接对之实例化啦，不过好消息是，微软有一个简单的类“SimpleWorkerRequest”，这个类实现了HttpWorkerRequest类；下面是一段简单的代码</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;">TextWriter tw <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> StringWriter<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
HttpWorkerRequest wr <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> SimpleWorkerRequest
<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;default.aspx&quot;</span>, <span style="color: #666666;">&quot;friendId=1300000000&quot;</span>, tw<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
HttpContext.<span style="color: #0000FF;">Current</span> <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> HttpContext<span style="color: #000000;">&#40;</span>wr<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span></pre></td></tr></table></div>

<p>这样子就能在单元测试里面用到HttpContext了，好处有：</p>
<ol>
<li>可以控制HttpContext的内容了，对于URL重写这部分来说，会比较关心请求路径，还有<span class="parameter">queryString</span>，这两个可以在实例化SimpleWorkerRequest的时候，作为参数传递进去。</li>
<li>不需要ASP.NET Development Server。这个很重要，因为可以满足一个自包含(self-contained)的单元测试的要求</li>
<li>可以调试</li>
</ol>
<p><strong><span style="font-size: medium; color: #3366ff;">3.改良后的方案</span></strong></p>
<p>到此，世界很美好，测试进行的很顺利。好日子没过多久，我又遇到一个问题，这个URL重写模块，还应用了一个规则引擎，其中进行了大量对HOST判断的操作，很不幸，用刚才的方法创建的HttpContext，它返回的Request.Url中，HOST永远都是127.0.0.1，很郁闷。这时候，一个所有做.NET的人都需要的屠龙刀派上用场了！.NET Reflector，用Reflector打开System.Web.dll，找到System.Web.Hosting这个命名空间，然后找到SimpleWorkerRequest这个类，发现里面的GetLocalAddress()方法，发现里面就是Hard-Code了一个地址：127.0.0.1；好了，知道问题在哪里了，着手写一个新的类，这个类继承SimpleWorkerRequest，然后重写他的GetLocalAddress()方法：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> MyWorkerRequest <span style="color: #008000;">:</span> SimpleWorkerRequest
<span style="color: #000000;">&#123;</span> 
    <span style="color: #0600FF;">private</span> <span style="color: #FF0000;">string</span> localAdd <span style="color: #008000;">=</span> <span style="color: #FF0000;">string</span>.<span style="color: #0000FF;">Empty</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #0600FF;">public</span> MyWorkerRequest<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> page, <span style="color: #FF0000;">string</span> query, TextWriter output, <span style="color: #FF0000;">string</span> address<span style="color: #000000;">&#41;</span>
        <span style="color: #008000;">:</span> <span style="color: #0600FF;">base</span><span style="color: #000000;">&#40;</span>page, query, output<span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>  
        <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">localAdd</span> <span style="color: #008000;">=</span> address<span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
&nbsp;
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">override</span> <span style="color: #FF0000;">string</span> GetLocalAddress<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">return</span> <span style="color: #0600FF;">this</span>.<span style="color: #0000FF;">localAdd</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>这样子，实例化HttpContext的时候就是这样子：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;">Thread.<span style="color: #0000FF;">GetDomain</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">SetData</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;.appPath&quot;</span>, <span style="color: #666666;">&quot;c:<span style="color: #008080; font-weight: bold;">\\</span>inetpub<span style="color: #008080; font-weight: bold;">\\</span>wwwroot<span style="color: #008080; font-weight: bold;">\\</span>webapp<span style="color: #008080; font-weight: bold;">\\</span>&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
Thread.<span style="color: #0000FF;">GetDomain</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">SetData</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;.appVPath&quot;</span>, <span style="color: #666666;">&quot;/&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
TextWriter tw <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> StringWriter<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #FF0000;">String</span> address <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;home.myspace.cn&quot;</span><span style="color: #008000;">;</span>
HttpWorkerRequest wr <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> MyWorkerRequest
<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;default.aspx&quot;</span>, <span style="color: #666666;">&quot;friendId=1300000000&quot;</span>, tw, address<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
HttpContext.<span style="color: #0000FF;">Current</span> <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> HttpContext<span style="color: #000000;">&#40;</span>wr<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span></pre></td></tr></table></div>

<p>需要注意的是，对于.appPath和.appVPath的设置是必须的，因为在SimpleWorkerRequest的构造函数中，会取这两个数值。<br />
经过这样的改造，基本上已经满足了测试的需求了。</p>
<p><strong><span style="color: #3366ff;">总结一下：</span></strong></p>
<ol>
<li>这个事情居然用了1天多时间，后来发现解决的办法就在我订阅的博客里面就有，以后遇到什么难题先找一个Google Reader。</li>
<li>多用.NET Reflector，Visual Studio经常让你看meta data，那些meta data对我们来说一点用处都没有，还是Reflector好啊。</li>
</ol>



Share and Enjoy:


	<a rel="nofollow"  target="_blank" href="http://magustest.com/blog/feed/" title="RSS"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/rss.png" title="RSS" alt="RSS" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://digg.com/submit?phase=2&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fsoftwaretesting%2Fusing-httpcontext-in-unittest%2F&amp;title=%E5%9C%A8C%23%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E7%AE%80%E5%8D%95%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95&amp;bodytext=%E5%9C%BA%E6%99%AF%EF%BC%9A%E6%9C%80%E8%BF%91%E5%9C%A8%E6%B5%8B%E8%AF%95%E4%B8%80%E4%B8%AA.NET%E7%9A%84Http%20Module%EF%BC%8C%E8%BF%99%E4%B8%AAModule%E6%98%AF%E7%94%A8%E6%9D%A5%E5%81%9AURL%E9%87%8D%E5%86%99%E7%9A%84%E3%80%82%E5%88%9A%E5%BC%80%E5%A7%8B%E8%BF%9B%E5%B1%95%E7%9A%84%E6%AF%94%E8%BE%83%E9%A1%BA%E5%88%A9%EF%BC%8C%E5%9B%A0%E4%B8%BA%E8%AF%A5Module%E9%87%8C%E9%9D%A2%E7%9A%84%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E5%9F%BA%E6%9C%AC%E4%B8%8A%E9%83%BD%E6%98%AFString%EF%BC%8C%E5%90%8E%E6%9D%A5%E8%BF%99%E4%B8%AAModule%E8%BF%9B%E8%A1%8C%E4%BA%86%E4%B8%80%E4%B8%8B%E9%87%8D%E6%9E%84%EF%BC%8C%E6%89%80%E6%9C%89%E5%8F%82%E6%95%B0%E9%83%BD%E5%8F%98%E6%88%90%E4%BA%86H" title="Digg"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fsoftwaretesting%2Fusing-httpcontext-in-unittest%2F&amp;title=%E5%9C%A8C%23%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E7%AE%80%E5%8D%95%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95&amp;notes=%E5%9C%BA%E6%99%AF%EF%BC%9A%E6%9C%80%E8%BF%91%E5%9C%A8%E6%B5%8B%E8%AF%95%E4%B8%80%E4%B8%AA.NET%E7%9A%84Http%20Module%EF%BC%8C%E8%BF%99%E4%B8%AAModule%E6%98%AF%E7%94%A8%E6%9D%A5%E5%81%9AURL%E9%87%8D%E5%86%99%E7%9A%84%E3%80%82%E5%88%9A%E5%BC%80%E5%A7%8B%E8%BF%9B%E5%B1%95%E7%9A%84%E6%AF%94%E8%BE%83%E9%A1%BA%E5%88%A9%EF%BC%8C%E5%9B%A0%E4%B8%BA%E8%AF%A5Module%E9%87%8C%E9%9D%A2%E7%9A%84%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E5%9F%BA%E6%9C%AC%E4%B8%8A%E9%83%BD%E6%98%AFString%EF%BC%8C%E5%90%8E%E6%9D%A5%E8%BF%99%E4%B8%AAModule%E8%BF%9B%E8%A1%8C%E4%BA%86%E4%B8%80%E4%B8%8B%E9%87%8D%E6%9E%84%EF%BC%8C%E6%89%80%E6%9C%89%E5%8F%82%E6%95%B0%E9%83%BD%E5%8F%98%E6%88%90%E4%BA%86H" title="del.icio.us"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fmagustest.com%2Fblog%2Fsoftwaretesting%2Fusing-httpcontext-in-unittest%2F&amp;t=%E5%9C%A8C%23%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E7%AE%80%E5%8D%95%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95" title="Facebook"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fsoftwaretesting%2Fusing-httpcontext-in-unittest%2F&title=%E5%9C%A8C%23%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E7%AE%80%E5%8D%95%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95" title="豆瓣"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban.png" title="豆瓣" alt="豆瓣" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fsoftwaretesting%2Fusing-httpcontext-in-unittest%2F&title=%E5%9C%A8C%23%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E7%AE%80%E5%8D%95%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95&n=1" title="豆瓣九点"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban9.png" title="豆瓣九点" alt="豆瓣九点" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.friendfeed.com/share?title=%E5%9C%A8C%23%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E7%AE%80%E5%8D%95%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95&amp;link=http%3A%2F%2Fmagustest.com%2Fblog%2Fsoftwaretesting%2Fusing-httpcontext-in-unittest%2F" title="FriendFeed"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fsoftwaretesting%2Fusing-httpcontext-in-unittest%2F&amp;title=%E5%9C%A8C%23%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E7%AE%80%E5%8D%95%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95" title="Live"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/live.png" title="Live" alt="Live" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://ping.fm/ref/?link=http%3A%2F%2Fmagustest.com%2Fblog%2Fsoftwaretesting%2Fusing-httpcontext-in-unittest%2F&amp;title=%E5%9C%A8C%23%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E7%AE%80%E5%8D%95%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95&amp;body=%E5%9C%BA%E6%99%AF%EF%BC%9A%E6%9C%80%E8%BF%91%E5%9C%A8%E6%B5%8B%E8%AF%95%E4%B8%80%E4%B8%AA.NET%E7%9A%84Http%20Module%EF%BC%8C%E8%BF%99%E4%B8%AAModule%E6%98%AF%E7%94%A8%E6%9D%A5%E5%81%9AURL%E9%87%8D%E5%86%99%E7%9A%84%E3%80%82%E5%88%9A%E5%BC%80%E5%A7%8B%E8%BF%9B%E5%B1%95%E7%9A%84%E6%AF%94%E8%BE%83%E9%A1%BA%E5%88%A9%EF%BC%8C%E5%9B%A0%E4%B8%BA%E8%AF%A5Module%E9%87%8C%E9%9D%A2%E7%9A%84%E6%96%B9%E6%B3%95%E5%8F%82%E6%95%B0%E5%9F%BA%E6%9C%AC%E4%B8%8A%E9%83%BD%E6%98%AFString%EF%BC%8C%E5%90%8E%E6%9D%A5%E8%BF%99%E4%B8%AAModule%E8%BF%9B%E8%A1%8C%E4%BA%86%E4%B8%80%E4%B8%8B%E9%87%8D%E6%9E%84%EF%BC%8C%E6%89%80%E6%9C%89%E5%8F%82%E6%95%B0%E9%83%BD%E5%8F%98%E6%88%90%E4%BA%86H" title="Ping.fm"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/ping.png" title="Ping.fm" alt="Ping.fm" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://shuqian.qq.com/post?jumpback=1&title=%E5%9C%A8C%23%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E7%AE%80%E5%8D%95%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95&uri=http%3A%2F%2Fmagustest.com%2Fblog%2Fsoftwaretesting%2Fusing-httpcontext-in-unittest%2F" title="QQ书签"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/qq.png" title="QQ书签" alt="QQ书签" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=%E5%9C%A8C%23%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E4%BD%BF%E7%94%A8HttpContext%E7%9A%84%E7%AE%80%E5%8D%95%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95%20-%20http%3A%2F%2Fmagustest.com%2Fblog%2Fsoftwaretesting%2Fusing-httpcontext-in-unittest%2F" title="Twitter"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>

<p>Related posts:<ol><li><a href='http://magustest.com/blog/net/introduction-to-dotnet-memcached-client/' rel='bookmark' title='Permanent Link: .NET平台上的Memcached客户端介绍'>.NET平台上的Memcached客户端介绍</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/three-different-test-fixture-setup-approach/' rel='bookmark' title='Permanent Link: 单元测试中三种准备Test Fixture的方法比较'>单元测试中三种准备Test Fixture的方法比较</a></li>
<li><a href='http://magustest.com/blog/net/serialize-deserialize-implement-deep-copy/' rel='bookmark' title='Permanent Link: 利用序列化和反序列化实现深拷贝'>利用序列化和反序列化实现深拷贝</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/softwaretesting/using-httpcontext-in-unittest/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>单元测试中的常用测试模式</title>
		<link>http://magustest.com/blog/whiteboxtesting/unit-test-pattern/</link>
		<comments>http://magustest.com/blog/whiteboxtesting/unit-test-pattern/#comments</comments>
		<pubDate>Mon, 15 Dec 2008 13:15:44 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[白盒测试]]></category>
		<category><![CDATA[单元测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=223</guid>
		<description><![CDATA[单元测试跟软件设计一样，有一些常用的模式，这篇文章是介绍一些常用的模式，其中的示例是C#代码，都比较简单，我想大家都能看懂。下面进入正题： 1. 准备，执行，断言(Arrange, Act, Assert)。这种模式是非常常见的，套用这种模式进行单元测试通常的做法如下： 准备测试环境，测试数据等 执行被测试方法 用断言来验证执行结果 下面是一段测试代码，被测方法的功能是把字符串中每个单词的首字母转为大写，特殊字符用下划线替代。 1 2 3 4 5 6 7 8 9 10 11 12 &#91;TestMethod&#40;&#41;&#93; public void CapitalizeTest&#40;&#41; &#123; //准备数据 string input = &#34;hello world!&#34;; string expected = &#34;HelloWorld_&#34;; //执行测试 string actual; actual = TextHelper.Capitalize&#40;input&#41;; //验证结果 Assert.AreEqual&#40;expected, actual&#41;; &#125; 2. 构造函数测试。这种模式适合对类中某些特殊的属性进行测试，被测的属性都有一个特点&#8211;它们都是不变量；例如数组的初始化以后，其容量是不会变化的，无论这个数组对象被什么样的外部方法调用。一般的做法如下： 创建一个实例 对该实例进行外部调用 用断言来验证执行结果 下面是一段代码；首先创建一个数组，然后使用该数组，最后验证该数组的大小有没有变化 1 2 3 [...]


Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/refactoring-unit-test/' rel='bookmark' title='Permanent Link: 测试代码重构实例'>测试代码重构实例</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/data-driven-test-in-unit-test/' rel='bookmark' title='Permanent Link: 在单元测试中应用数据驱动'>在单元测试中应用数据驱动</a></li>
<li><a href='http://magustest.com/blog/automationtesting/data-driven-codedui-test/' rel='bookmark' title='Permanent Link: 实现数据驱动的CodedUI Test'>实现数据驱动的CodedUI Test</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>单元测试跟软件设计一样，有一些常用的模式，这篇文章是介绍一些常用的模式，其中的示例是C#代码，都比较简单，我想大家都能看懂。下面进入正题：</p>
<p><span style="color: #0000ff;"><strong>1. 准备，执行，断言(Arrange, Act, Assert)。</strong><span style="color: #000000;">这种模式是非常常见的，套用这种模式进行单元测试通常的做法如下：</span></span></p>
<ol>
<li> 准备测试环境，测试数据等</li>
<li>执行被测试方法</li>
<li>用断言来验证执行结果</li>
</ol>
<p>下面是一段测试代码，被测方法的功能是把字符串中每个单词的首字母转为大写，特殊字符用下划线替代。<br />
<span id="more-223"></span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestMethod<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> CapitalizeTest<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
<span style="color: #008080; font-style: italic;">//准备数据</span>
<span style="color: #FF0000;">string</span> input <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;hello world!&quot;</span><span style="color: #008000;">;</span>
<span style="color: #FF0000;">string</span> expected <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;HelloWorld_&quot;</span><span style="color: #008000;">;</span>
<span style="color: #008080; font-style: italic;">//执行测试</span>
<span style="color: #FF0000;">string</span> actual<span style="color: #008000;">;</span>
actual <span style="color: #008000;">=</span> TextHelper.<span style="color: #0000FF;">Capitalize</span><span style="color: #000000;">&#40;</span>input<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008080; font-style: italic;">//验证结果</span>
Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>expected, actual<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p><span style="color: #0000ff;"><strong>2. 构造函数测试。</strong></span>这种模式适合对类中某些特殊的属性进行测试，被测的属性都有一个特点&#8211;它们都是不变量；例如数组的初始化以后，其容量是不会变化的，无论这个数组对象被什么样的外部方法调用。一般的做法如下：</p>
<ol>
<li>创建一个实例</li>
<li>对该实例进行外部调用</li>
<li>用断言来验证执行结果</li>
</ol>
<p>下面是一段代码；首先创建一个数组，然后使用该数组，最后验证该数组的大小有没有变化</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestMethod<span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> TestInvariant<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
<span style="color: #008080; font-style: italic;">//创建一个实例</span>
<span style="color: #FF0000;">int</span> capacity <span style="color: #008000;">=</span> <span style="color: #FF0000;">5</span><span style="color: #008000;">;</span>
<span style="color: #FF0000;">int</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> intArray <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> <span style="color: #FF0000;">int</span><span style="color: #000000;">&#91;</span>capacity<span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
<span style="color: #008080; font-style: italic;">//进行调用</span>
<span style="color: #0600FF;">for</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">int</span> i <span style="color: #008000;">=</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span> i <span style="color: #008000;">&amp;</span>lt<span style="color: #008000;">;</span> intArray.<span style="color: #0000FF;">Length</span><span style="color: #008000;">;</span> i<span style="color: #008000;">++</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
intArray.<span style="color: #0000FF;">SetValue</span><span style="color: #000000;">&#40;</span>i, i<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span>
<span style="color: #008080; font-style: italic;">//验证结果</span>
Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>capacity, intArray.<span style="color: #0000FF;">Length</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p><span style="color: #0000ff;"><strong>3. 反向关联(Roundtrip)。</strong></span>这种模式适合于被测方法有一个可逆方法的情况下使用。它的数学证明是：<strong>f<sup>-1</sup>(f(x)) = x</strong></p>
<p>下面是一段示例代码：</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestMethod<span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> RoundTripTest<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
<span style="color: #FF0000;">string</span> str <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;10&quot;</span><span style="color: #008000;">;</span>
<span style="color: #008080; font-style: italic;">//把字符串转换为整数，然后再转换为字符串</span>
<span style="color: #FF0000;">int</span> i <span style="color: #008000;">=</span> Int32.<span style="color: #0000FF;">Parse</span><span style="color: #000000;">&#40;</span>str<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #FF0000;">string</span> finalString <span style="color: #008000;">=</span> i.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008080; font-style: italic;">//验证结果</span>
Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>str, finalString<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p><strong><span style="color: #0000ff;">4. 经过处理的反向关联(Sanitized Roundtrip)。</span></strong>上面说的反向关联有一个缺点，就是如果输入的字符串为&#8221; 10&#8243;，那么就有点问题了，因为整数10转换为字符串是不会转换为&#8221; 10&#8243;的，这个模式的数学证明是：<strong>f<sup>-1</sup>(f(f<sup>-1</sup>(x)))=f<sup>-1</sup>(x)</strong></p>
<p>以下示例可以看做是上一段代码的加强版</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestMethod<span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> SanitizedRoundTripTest<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
<span style="color: #FF0000;">string</span> str <span style="color: #008000;">=</span> <span style="color: #666666;">&quot; 10 &quot;</span><span style="color: #008000;">;</span>
<span style="color: #008080; font-style: italic;">//先把字符串转换为整数，然后把整数转换为字符串，最后把字符串转换为整数</span>
<span style="color: #FF0000;">int</span> i <span style="color: #008000;">=</span> Int32.<span style="color: #0000FF;">Parse</span><span style="color: #000000;">&#40;</span>str<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #FF0000;">string</span> intermediate <span style="color: #008000;">=</span> i.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #FF0000;">int</span> roundtripped <span style="color: #008000;">=</span> Int32.<span style="color: #0000FF;">Parse</span><span style="color: #000000;">&#40;</span>intermediate<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008080; font-style: italic;">//验证结果</span>
Assert.<span style="color: #0000FF;">AreEqual</span><span style="color: #000000;">&#40;</span>i, roundtripped<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p><span style="color: #0000ff;"><strong>5. 状态关联。</strong></span>这种模式很常见，就是对于调用某个类的方法，会改变这个类内部的状态，而这个改变可以用其他方法来间接地验证。</p>
<p>一段对列表进行简单测试的代码</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestMethod<span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> InsertContains<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
<span style="color: #FF0000;">string</span> input <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;some string&quot;</span><span style="color: #008000;">;</span>
List<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span> list <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> List<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
list.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span>input<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
Assert.<span style="color: #0000FF;">IsTrue</span><span style="color: #000000;">&#40;</span>list.<span style="color: #0000FF;">Contains</span><span style="color: #000000;">&#40;</span>input<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
list.<span style="color: #0000FF;">Remove</span><span style="color: #000000;">&#40;</span>input<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
Assert.<span style="color: #0000FF;">IsFalse</span><span style="color: #000000;">&#40;</span>list.<span style="color: #0000FF;">Contains</span><span style="color: #000000;">&#40;</span>input<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p><span style="color: #0000ff;"><strong>6. 异常允许。</strong></span>如果需要测试异常是否在适当的时候抛出的时候，应该应用该模式。</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>TestMethod,ExpectedException<span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>IndexOutOfRangeException<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">void</span> ExpectedException<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
<span style="color: #008080; font-style: italic;">//创建一个长度为5的数组</span>
<span style="color: #FF0000;">int</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> array <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> <span style="color: #FF0000;">int</span><span style="color: #000000;">&#91;</span><span style="color: #FF0000;">5</span><span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
<span style="color: #008080; font-style: italic;">//尝试给该数组的第六位赋值，应该抛出IndexOutOfRangeException异常</span>
array<span style="color: #000000;">&#91;</span><span style="color: #FF0000;">6</span><span style="color: #000000;">&#93;</span> <span style="color: #008000;">=</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></td></tr></table></div>

<p>以上六种模式是单元测试中比较常见的，但并不是单元测试的全部。了解这些模式，对于平时的工作是很有帮助的。</p>



Share and Enjoy:


	<a rel="nofollow"  target="_blank" href="http://magustest.com/blog/feed/" title="RSS"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/rss.png" title="RSS" alt="RSS" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/googlebookmark.png" title="Google Bookmarks" alt="Google Bookmarks" class="sociable-hovers" /></a>
	><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/digg.png" title="Digg" alt="Digg" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://delicious.com/post?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-pattern%2F&amp;title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%B8%B8%E7%94%A8%E6%B5%8B%E8%AF%95%E6%A8%A1%E5%BC%8F&amp;notes=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E8%B7%9F%E8%BD%AF%E4%BB%B6%E8%AE%BE%E8%AE%A1%E4%B8%80%E6%A0%B7%EF%BC%8C%E6%9C%89%E4%B8%80%E4%BA%9B%E5%B8%B8%E7%94%A8%E7%9A%84%E6%A8%A1%E5%BC%8F%EF%BC%8C%E8%BF%99%E7%AF%87%E6%96%87%E7%AB%A0%E6%98%AF%E4%BB%8B%E7%BB%8D%E4%B8%80%E4%BA%9B%E5%B8%B8%E7%94%A8%E7%9A%84%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%85%B6%E4%B8%AD%E7%9A%84%E7%A4%BA%E4%BE%8B%E6%98%AFC%23%E4%BB%A3%E7%A0%81%EF%BC%8C%E9%83%BD%E6%AF%94%E8%BE%83%E7%AE%80%E5%8D%95%EF%BC%8C%E6%88%91%E6%83%B3%E5%A4%A7%E5%AE%B6%E9%83%BD%E8%83%BD%E7%9C%8B%E6%87%82%E3%80%82%E4%B8%8B%E9%9D%A2%E8%BF%9B%E5%85%A5%E6%AD%A3%E9%A2%98%EF%BC%9A%0D%0A%0D%0A1.%20%E5%87%86%E5%A4%87%EF%BC%8C%E6%89%A7%E8%A1%8C%EF%BC%8C%E6%96%AD%E8%A8%80%28Arrange%2C%20Act%2C%20A" title="del.icio.us"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/delicious.png" title="del.icio.us" alt="del.icio.us" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.facebook.com/share.php?u=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-pattern%2F&amp;t=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%B8%B8%E7%94%A8%E6%B5%8B%E8%AF%95%E6%A8%A1%E5%BC%8F" title="Facebook"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/facebook.png" title="Facebook" alt="Facebook" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-pattern%2F&title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%B8%B8%E7%94%A8%E6%B5%8B%E8%AF%95%E6%A8%A1%E5%BC%8F" title="豆瓣"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban.png" title="豆瓣" alt="豆瓣" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.douban.com/recommend/?url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-pattern%2F&title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%B8%B8%E7%94%A8%E6%B5%8B%E8%AF%95%E6%A8%A1%E5%BC%8F&n=1" title="豆瓣九点"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/douban9.png" title="豆瓣九点" alt="豆瓣九点" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://www.friendfeed.com/share?title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%B8%B8%E7%94%A8%E6%B5%8B%E8%AF%95%E6%A8%A1%E5%BC%8F&amp;link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-pattern%2F" title="FriendFeed"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/friendfeed.png" title="FriendFeed" alt="FriendFeed" class="sociable-hovers" /></a>
	<img src="http://magustest.com/blog/wp-content/plugins/sociable/images/linkedin.png" title="LinkedIn" alt="LinkedIn" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="https://favorites.live.com/quickadd.aspx?marklet=1&amp;url=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-pattern%2F&amp;title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%B8%B8%E7%94%A8%E6%B5%8B%E8%AF%95%E6%A8%A1%E5%BC%8F" title="Live"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/live.png" title="Live" alt="Live" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://ping.fm/ref/?link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-pattern%2F&amp;title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%B8%B8%E7%94%A8%E6%B5%8B%E8%AF%95%E6%A8%A1%E5%BC%8F&amp;body=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E8%B7%9F%E8%BD%AF%E4%BB%B6%E8%AE%BE%E8%AE%A1%E4%B8%80%E6%A0%B7%EF%BC%8C%E6%9C%89%E4%B8%80%E4%BA%9B%E5%B8%B8%E7%94%A8%E7%9A%84%E6%A8%A1%E5%BC%8F%EF%BC%8C%E8%BF%99%E7%AF%87%E6%96%87%E7%AB%A0%E6%98%AF%E4%BB%8B%E7%BB%8D%E4%B8%80%E4%BA%9B%E5%B8%B8%E7%94%A8%E7%9A%84%E6%A8%A1%E5%BC%8F%EF%BC%8C%E5%85%B6%E4%B8%AD%E7%9A%84%E7%A4%BA%E4%BE%8B%E6%98%AFC%23%E4%BB%A3%E7%A0%81%EF%BC%8C%E9%83%BD%E6%AF%94%E8%BE%83%E7%AE%80%E5%8D%95%EF%BC%8C%E6%88%91%E6%83%B3%E5%A4%A7%E5%AE%B6%E9%83%BD%E8%83%BD%E7%9C%8B%E6%87%82%E3%80%82%E4%B8%8B%E9%9D%A2%E8%BF%9B%E5%85%A5%E6%AD%A3%E9%A2%98%EF%BC%9A%0D%0A%0D%0A1.%20%E5%87%86%E5%A4%87%EF%BC%8C%E6%89%A7%E8%A1%8C%EF%BC%8C%E6%96%AD%E8%A8%80%28Arrange%2C%20Act%2C%20A" title="Ping.fm"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/ping.png" title="Ping.fm" alt="Ping.fm" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://shuqian.qq.com/post?jumpback=1&title=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%B8%B8%E7%94%A8%E6%B5%8B%E8%AF%95%E6%A8%A1%E5%BC%8F&uri=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-pattern%2F" title="QQ书签"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/qq.png" title="QQ书签" alt="QQ书签" class="sociable-hovers" /></a>
	<a rel="nofollow"  target="_blank" href="http://twitter.com/home?status=%E5%8D%95%E5%85%83%E6%B5%8B%E8%AF%95%E4%B8%AD%E7%9A%84%E5%B8%B8%E7%94%A8%E6%B5%8B%E8%AF%95%E6%A8%A1%E5%BC%8F%20-%20http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Funit-test-pattern%2F" title="Twitter"><img src="http://magustest.com/blog/wp-content/plugins/sociable/images/twitter.png" title="Twitter" alt="Twitter" class="sociable-hovers" /></a>


<br/><br/>

<p>Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/refactoring-unit-test/' rel='bookmark' title='Permanent Link: 测试代码重构实例'>测试代码重构实例</a></li>
<li><a href='http://magustest.com/blog/whiteboxtesting/data-driven-test-in-unit-test/' rel='bookmark' title='Permanent Link: 在单元测试中应用数据驱动'>在单元测试中应用数据驱动</a></li>
<li><a href='http://magustest.com/blog/automationtesting/data-driven-codedui-test/' rel='bookmark' title='Permanent Link: 实现数据驱动的CodedUI Test'>实现数据驱动的CodedUI Test</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/whiteboxtesting/unit-test-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
