<?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/white-box-testing/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/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>自动化白盒测试工具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>在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>
		<item>
		<title>PEX-.NET自动化白盒测试工具的介绍(1)</title>
		<link>http://magustest.com/blog/whiteboxtesting/introduction-to-pex-automated-white-box-testing-for-dotnet/</link>
		<comments>http://magustest.com/blog/whiteboxtesting/introduction-to-pex-automated-white-box-testing-for-dotnet/#comments</comments>
		<pubDate>Thu, 11 Dec 2008 08:20:22 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[白盒测试]]></category>
		<category><![CDATA[PEX]]></category>
		<category><![CDATA[单元测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=157</guid>
		<description><![CDATA[PEX的全称是(Program EXploration)，是一款在.NET下可应用的自动化白盒测试工具，来自于微软研究院。PEX通过分析代码来自动生成测试用例。对于程序里面的每一行代码，PEX都会尽可能地生成合适的输入值来达到提高覆盖率的目标。同时PEX还会分析代码中的分支，生成覆盖更多分支的测试代码（输入数据）；PEX在执行代码的同时会监控和分析代码的控制流和数据流，了解程序的行为。每运行完单一个测试以后，PEX会选择一条在前面的测试中没有覆盖到的路径，并且尝试执行它。这一切都是约束求解算法来实现的，官方文档中提到的是一个叫Z3的约束求解器。因为PEX了解被测代码内部结构和行为，所以它不是一个简单地输入随机参数的黑盒测试工具。PEX不会尝试枚举所有可能的输入，事实上也不可能枚举完所有的可能输入。 下面来看看如何利用PEX来帮助提高软件的质量吧。 1. 首先，安装PEX。PEX现在有2个Flavor，支持2个版本的Visual Studio，分别是VSTS2010和VSTS2008，这两个版本的PEX在功能上没有区别，只是在许可证上有区别。本文是以VSTS2008版本作为示例。 2. 建立一个C#的Class Library项目 3. 新建一个类，并且添加一个静态方法。这个方法是把输入的字符串格式化为首字母大写的格式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public static string Capitalize&#40;string value&#41; &#123; var sb = new StringBuilder&#40;&#41;; bool word = false; // are we writing [...]


Related posts:<ol><li><a href='http://magustest.com/blog/whiteboxtesting/how-to-debug-in-aspdotnet-unit-test/' rel='bookmark' title='Permanent Link: 在ASP.NET单元测试中进行调试'>在ASP.NET单元测试中进行调试</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/automationtesting/data-driven-codedui-test/' rel='bookmark' title='Permanent Link: 实现数据驱动的CodedUI Test'>实现数据驱动的CodedUI Test</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><a href="http://research.microsoft.com/Pex/" target="_blank">PEX</a>的全称是(Program EXploration)，是一款在.NET下可应用的自动化白盒测试工具，来自于微软研究院。PEX通过分析代码来自动生成测试用例。对于程序里面的每一行代码，PEX都会尽可能地生成合适的输入值来达到提高覆盖率的目标。同时PEX还会分析代码中的分支，生成覆盖更多分支的测试代码（输入数据）；PEX在执行代码的同时会监控和分析代码的控制流和数据流，了解程序的行为。每运行完单一个测试以后，PEX会选择一条在前面的测试中没有覆盖到的路径，并且尝试执行它。这一切都是约束求解算法来实现的，官方文档中提到的是一个叫Z3的约束求解器。因为PEX了解被测代码内部结构和行为，所以它不是一个简单地输入随机参数的黑盒测试工具。PEX不会尝试枚举所有可能的输入，事实上也不可能枚举完所有的可能输入。<br />
<span id="more-157"></span><br />
下面来看看如何利用PEX来帮助提高软件的质量吧。</p>
<p><strong><span style="color: #ff6600;">1. 首先，安装PEX。</span></strong>PEX现在有2个Flavor，支持2个版本的Visual Studio，分别是VSTS2010和VSTS2008，这两个版本的PEX在功能上没有区别，只是在许可证上有区别。本文是以VSTS2008版本作为示例。</p>
<p><span style="color: #ff6600;"><strong>2. 建立一个C#的Class Library项目</strong> </span></p>
<div id="attachment_158" class="wp-caption alignnone" style="width: 510px"><a href="http://magustest.com/blog/wp-content/uploads/2008/12/create-a-class-project1.png"><img class="size-full wp-image-158" title="create-a-class-project" src="http://magustest.com/blog/wp-content/uploads/2008/12/create-a-class-project1.png" alt="create a class project" width="500" height="360" /></a><p class="wp-caption-text">create a class project</p></div>
<p><span style="color: #ff6600;"><strong>3. 新建一个类，并且添加一个静态方法。</strong><span style="color: #000000;">这个方法是把输入的字符串格式化为首字母大写的格式</span></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
23
24
25
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">string</span> Capitalize<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> value<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	var sb <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> StringBuilder<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #FF0000;">bool</span> word <span style="color: #008000;">=</span> false<span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">// are we writing a word</span>
	<span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var c <span style="color: #0600FF;">in</span> value<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: #FF0000;">char</span>.<span style="color: #0000FF;">IsLetter</span><span style="color: #000000;">&#40;</span>c<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><span style="color: #008000;">!</span>word<span style="color: #000000;">&#41;</span>
			<span style="color: #000000;">&#123;</span>
				sb.<span style="color: #0000FF;">Append</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">char</span>.<span style="color: #0000FF;">ToUpper</span><span style="color: #000000;">&#40;</span>c<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
				word <span style="color: #008000;">=</span> true<span style="color: #008000;">;</span>
			<span style="color: #000000;">&#125;</span>
			<span style="color: #0600FF;">else</span>
				sb.<span style="color: #0000FF;">Append</span><span style="color: #000000;">&#40;</span>c<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>
			<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">char</span>.<span style="color: #0000FF;">IsPunctuation</span><span style="color: #000000;">&#40;</span>c<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
				sb.<span style="color: #0000FF;">Append</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">'_'</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
			word <span style="color: #008000;">=</span> false<span style="color: #008000;">;</span>
		<span style="color: #000000;">&#125;</span>
	<span style="color: #000000;">&#125;</span>
	<span style="color: #0600FF;">return</span> sb.<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: #000000;">&#125;</span></pre></td></tr></table></div>

<p><strong><span style="color: #ff6600;">4. 这时候，可以创建一个传统的单元测试，但有了PEX，我们希望用PEX</span></strong><br />
<img class="alignnone size-full wp-image-159" title="trandition-unit-test" src="http://magustest.com/blog/wp-content/uploads/2008/12/trandition-unit-test1.png" alt="" width="214" height="198" /></p>
<p><span style="color: #ff6600;"><strong>5. 在该静态方法体内，点击右键，选择“Run Pex Explorations”，就可以运行PEX</strong></span><br />
<a href="http://magustest.com/blog/wp-content/uploads/2008/12/run-pex-explorations1.png"><img class="alignnone size-full wp-image-160" title="run-pex-explorations" src="http://magustest.com/blog/wp-content/uploads/2008/12/run-pex-explorations1.png" alt="" width="360" height="194" /></a></p>
<p><strong><span style="color: #ff6600;">6. PEX会编译这个类，并且运行这个方法</span></strong>，监控测试的运行，对于这个简单的方法，很快就会获得结果。在标题栏可以看到，运行了123次测试，其中有1个测试是失败的；失败的用例就是图中被圈出来的那一条。<br />
<a href="http://magustest.com/blog/wp-content/uploads/2008/12/pex-result1.png"><img class="alignnone size-full wp-image-161" title="pex-result" src="http://magustest.com/blog/wp-content/uploads/2008/12/pex-result1.png" alt="" width="500" height="289" /></a></p>
<p><strong><span style="color: #ff6600;">7. 点击选中测试结果中有异常的测试行</span></strong>，会看到以下菜单，可以做以下操作：</p>
<p>(1)保存该测试为普通的单元测试<br />
(2)自动添加代码来避免该错误的发生<br />
(3)允许此异常在程序中出现<br />
(4)把所有信息发送到文本或者剪切板，这里所有信息包括Detail和Stack trace，如果TFS里面配置了Work Item，还能直接发送到相应的Work Item中</p>
<p><a href="http://magustest.com/blog/wp-content/uploads/2008/12/menu1.png"><img class="alignnone size-full wp-image-162" title="menu" src="http://magustest.com/blog/wp-content/uploads/2008/12/menu1.png" alt="" width="500" height="266" /></a></p>
<p><span style="color: #ff6600;"><strong>8. 现在我们让PEX帮我们修正一个错。</strong></span>选择Add Precondition，会看到如下菜单。上半部分告诉用户，PEX会做那些操作，下半部分就是选中操作的具体内容，这里就是加上一段对输入是否为空的判断</p>
<p><a href="http://magustest.com/blog/wp-content/uploads/2008/12/add-code-as-precondition1.png"><img class="alignnone size-full wp-image-163" title="add-code-as-precondition" src="http://magustest.com/blog/wp-content/uploads/2008/12/add-code-as-precondition1.png" alt="" width="499" height="402" /></a></p>
<p><strong><span style="color: #ff6600;">9. 点击Apply就能把这段代码段加到我们的代码中</span></strong></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
25
26
27
28
29
30
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">string</span> Capitalize<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> value<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
	<span style="color: #008080; font-style: italic;">//</span>
&nbsp;
	<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>value <span style="color: #008000;">==</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#41;</span><span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
		<span style="color: #0600FF;">throw</span> <span style="color: #008000;">new</span> ArgumentNullException<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;value&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #008080; font-style: italic;">//</span>
	var sb <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> StringBuilder<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #FF0000;">bool</span> word <span style="color: #008000;">=</span> false<span style="color: #008000;">;</span> <span style="color: #008080; font-style: italic;">// are we writing a word</span>
	<span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span>var c <span style="color: #0600FF;">in</span> value<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: #FF0000;">char</span>.<span style="color: #0000FF;">IsLetter</span><span style="color: #000000;">&#40;</span>c<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><span style="color: #008000;">!</span>word<span style="color: #000000;">&#41;</span>
			<span style="color: #000000;">&#123;</span>
				sb.<span style="color: #0000FF;">Append</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">char</span>.<span style="color: #0000FF;">ToUpper</span><span style="color: #000000;">&#40;</span>c<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
				word <span style="color: #008000;">=</span> true<span style="color: #008000;">;</span>
			<span style="color: #000000;">&#125;</span>
			<span style="color: #0600FF;">else</span>
				sb.<span style="color: #0000FF;">Append</span><span style="color: #000000;">&#40;</span>c<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>
			<span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">char</span>.<span style="color: #0000FF;">IsPunctuation</span><span style="color: #000000;">&#40;</span>c<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
				sb.<span style="color: #0000FF;">Append</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">'_'</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
			word <span style="color: #008000;">=</span> false<span style="color: #008000;">;</span>
		<span style="color: #000000;">&#125;</span>
	<span style="color: #000000;">&#125;</span>
	<span style="color: #0600FF;">return</span> sb.<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: #000000;">&#125;</span></pre></td></tr></table></div>

<p> OK！PEX帮助我们找到一个Bug并且修复了它。</p>
<p>本文对PEX进行一个简单的介绍，当然PEX不仅仅是那么简单，还有很多丰富的内容，例如Parameterized Unit Test，Code Contracts等等，后面打算深入研究一下PEX，挖掘一下相关的功能。预告一下，下一篇会介绍如果利用PEX写参数化单元测试(Parameterized Unit Test)</p>
<p>更多的参考：</p>
<p><a href="http://research.microsoft.com/Pex/" target="_blank">Pex官方网站</a></p>
<p><a href="http://social.msdn.microsoft.com/Forums/en-US/pex/threads/" target="_blank">Pex在MSDN上的论坛</a></p>
<p>主要参考文档：<a href="http://research.microsoft.com/pex/articles/pexcodediggertutorial.pdf" target="_blank">Code Digger Tutorial</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%2Fintroduction-to-pex-automated-white-box-testing-for-dotnet%2F&amp;t=PEX-.NET%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%B7%E7%9A%84%E4%BB%8B%E7%BB%8D%281%29" 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%2Fintroduction-to-pex-automated-white-box-testing-for-dotnet%2F&title=PEX-.NET%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%B7%E7%9A%84%E4%BB%8B%E7%BB%8D%281%29" 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%2Fintroduction-to-pex-automated-white-box-testing-for-dotnet%2F&title=PEX-.NET%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%B7%E7%9A%84%E4%BB%8B%E7%BB%8D%281%29&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=PEX-.NET%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%B7%E7%9A%84%E4%BB%8B%E7%BB%8D%281%29&amp;link=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fintroduction-to-pex-automated-white-box-testing-for-dotnet%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%2Fintroduction-to-pex-automated-white-box-testing-for-dotnet%2F&amp;title=PEX-.NET%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%B7%E7%9A%84%E4%BB%8B%E7%BB%8D%281%29" 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=PEX-.NET%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%B7%E7%9A%84%E4%BB%8B%E7%BB%8D%281%29&uri=http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fintroduction-to-pex-automated-white-box-testing-for-dotnet%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=PEX-.NET%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%B7%E7%9A%84%E4%BB%8B%E7%BB%8D%281%29%20-%20http%3A%2F%2Fmagustest.com%2Fblog%2Fwhiteboxtesting%2Fintroduction-to-pex-automated-white-box-testing-for-dotnet%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/how-to-debug-in-aspdotnet-unit-test/' rel='bookmark' title='Permanent Link: 在ASP.NET单元测试中进行调试'>在ASP.NET单元测试中进行调试</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/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/introduction-to-pex-automated-white-box-testing-for-dotnet/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
