<?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; .NET</title>
	<atom:link href="http://magustest.com/blog/category/net/feed/" rel="self" type="application/rss+xml" />
	<link>http://magustest.com/blog</link>
	<description>软件测试，自动化测试，白盒测试，Python</description>
	<lastBuildDate>Wed, 04 Jan 2012 09:09:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>调试部署在IIS上的ASP.NET程序实用小技巧</title>
		<link>http://magustest.com/blog/net/tips-debugging-asp-net-on-iis/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=tips-debugging-asp-net-on-iis</link>
		<comments>http://magustest.com/blog/net/tips-debugging-asp-net-on-iis/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 08:07:46 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=566</guid>
		<description><![CDATA[远程调试ASP.NET程序，似乎是每一个做ASP.NET的人都肯定要掌握的技能，大家都知道，从IIS6开始，就有了application pool(应用程序池)的概念，每个应用程序池都会有单独的worker process，这样可以保障不同的应用程序池之间互相不会影响，就好像MySpace上有博客应用，有论坛应用等等……如果这些应用都用的同一个应用程序池，那么只要一个挂了，其他的也跟着挂。但是如果每个站点都单独使用一个应用程序池，那么A站点挂了对B站点不会有影响。同时如果A站点有部署更新，需要回收应用程序池，B站点不受影响，照常工作。 创建多个应用程序池虽然好处多多，不过却增大了调试的难度。假如一台服务器上有5个站点，那么正常运行的情况下就会有5个w3wp.exe进程，要找到合适的进程进行调试就是一个问题，以前比较笨，就看哪个进程的ID比较小，或者哪个进程占用的内存较多来“判断”，今天发现其实微软有一个非常靠谱的方法。 1. 打开一个命令行窗口 2. 浏览到“Windows &#62; System32” 3. 运行“cscript iisapp.vbs” 得到如图结果，哪个应用程序池对应哪个W3WP.EXE一目了然，从此告别瞎猜 No related posts.
No related posts.]]></description>
			<content:encoded><![CDATA[<p>远程调试ASP.NET程序，似乎是每一个做ASP.NET的人都肯定要掌握的技能，大家都知道，从IIS6开始，就有了application pool(应用程序池)的概念，每个应用程序池都会有单独的worker process，这样可以保障不同的应用程序池之间互相不会影响，就好像MySpace上有博客应用，有论坛应用等等……如果这些应用都用的同一个应用程序池，那么只要一个挂了，其他的也跟着挂。但是如果每个站点都单独使用一个应用程序池，那么A站点挂了对B站点不会有影响。同时如果A站点有部署更新，需要回收应用程序池，B站点不受影响，照常工作。</p>
<p>创建多个应用程序池虽然好处多多，不过却增大了调试的难度。假如一台服务器上有5个站点，那么正常运行的情况下就会有5个w3wp.exe进程，要找到合适的进程进行调试就是一个问题，以前比较笨，就看哪个进程的ID比较小，或者哪个进程占用的内存较多来“判断”，今天发现其实微软有一个非常靠谱的方法。</p>
<p>1. 打开一个命令行窗口</p>
<p>2. 浏览到“Windows &gt; System32”</p>
<p>3. 运行“cscript iisapp.vbs”</p>
<p>得到如图结果，哪个应用程序池对应哪个W3WP.EXE一目了然，从此告别瞎猜</p>
<p><img class="alignnone size-full wp-image-567" title="IIS-WORKER-PROCESS" src="http://magustest.com/blog/wp-content/uploads/2009/07/IIS-WORKER-PROCESS1.png" alt="IIS-WORKER-PROCESS" width="553" height="111" /></p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/net/tips-debugging-asp-net-on-iis/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Linq to Object在测试中的应用</title>
		<link>http://magustest.com/blog/whiteboxtesting/using-linq-to-object-in-testing/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-linq-to-object-in-testing</link>
		<comments>http://magustest.com/blog/whiteboxtesting/using-linq-to-object-in-testing/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 03:34:50 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[白盒测试]]></category>
		<category><![CDATA[LINQ]]></category>
		<category><![CDATA[集成测试]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=563</guid>
		<description><![CDATA[.NET Framework 3.5中引入了一个新特性LINQ（集成语言查询），据说.NET Framework 3.5中很多特性都是为LINQ而服务的，例如Lambda表达式的支持，匿名类型，等等……这篇文章会讲述一个把Linq to Object应用于测试的例子。 前一阵子需要测试一个搜索在线会员的功能，如果一个用户是在线的，那么他所能够被搜索到的信息都会作为一条记录，保存在一个表中，主要的字段有5个，也就是根据这5个字段的信息可以查询出用户想要的在线会员。一个简单的方案就是写一个比较复杂的存储过程，然后根据5个输入来查询出不同的结果，不过DBA说在SQL SERVER中进行逻辑运算的性能不是很好，所以开发人员写了12条存储过程，分别对应不同的组合，那么对于我做集成测试来说，我起码要有12个测试方法对应这12条存储过程。同时我还要设计一定数量的测试数据，供我查询测试，而比较要命的是，这些测试数据随着我对这个功能的理解的深入，在不断地增加，结果就是如果我写第一个测试的时候，我准备的数据是30条，OK，测试通过；等我写到第五个测试的时候，测试数据可能有40条了，当我用这40条测试数据重新指向第一个测试的时候，FAILED!!!这让人非常郁闷。所以我想到了能不能用round trip的方法来进行测试。做一个比喻，假如说我想证明WIN7的计算器程序是正确的，那么可以把相同的计算在WIN XP的计算器中跑一遍，如果两者结果一样，那么我可以认为WIN7的计算器程序也是正确的（如果XP的计算器有错怎么办？先别较真，有风险，但很小）。 我的做法就是，准备一些数据，首先用SUT进行查询，然后用LINQ进行查询，如果两者查询结果一致，那么可以认为程序是正确的，否则就是两者之一存在问题。 首先准备一些测试数据，保存为XML文件，第一方便对测试数据进行CRUD，第二可以用XmlSerializer把这些数据转换为对象，方便用LINQ查询。 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 &#60; ?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34; ?&#62; &#60;onlinefriends&#62; &#60;friends&#62; &#60;onlinefrienddata&#62; &#60;friendid&#62;1300010000&#60;/friendid&#62; &#60;province&#62;北京市&#60;/province&#62; &#60;city&#62;北京市&#60;/city&#62; &#60;age&#62;18&#60;/age&#62; &#60;gender&#62;2&#60;/gender&#62; <a href='http://magustest.com/blog/whiteboxtesting/using-linq-to-object-in-testing/'>[...]</a>
No related posts.]]></description>
			<content:encoded><![CDATA[<p>.NET Framework 3.5中引入了一个新特性<a href="http://msdn.microsoft.com/en-us/netframework/aa904594.aspx" target="_blank">LINQ</a>（集成语言查询），据说.NET Framework 3.5中很多特性都是为LINQ而服务的，例如<a href="http://en.wikipedia.org/wiki/Lambda" target="_blank">Lambda表达式</a>的支持，<a href="http://msdn.microsoft.com/zh-cn/library/bb397696.aspx" target="_blank">匿名类型</a>，等等……这篇文章会讲述一个把Linq to Object应用于测试的例子。</p>
<p>前一阵子需要测试一个搜索在线会员的功能，如果一个用户是在线的，那么他所能够被搜索到的信息都会作为一条记录，保存在一个表中，主要的字段有5个，也就是根据这5个字段的信息可以查询出用户想要的在线会员。一个简单的方案就是写一个比较复杂的存储过程，然后根据5个输入来查询出不同的结果，不过DBA说在SQL SERVER中进行逻辑运算的性能不是很好，所以开发人员写了12条存储过程，分别对应不同的组合，那么对于我做集成测试来说，我起码要有12个测试方法对应这12条存储过程。同时我还要设计一定数量的测试数据，供我查询测试，而比较要命的是，这些测试数据随着我对这个功能的理解的深入，在不断地增加，结果就是如果我写第一个测试的时候，我准备的数据是30条，OK，测试通过；等我写到第五个测试的时候，测试数据可能有40条了，当我用这40条测试数据重新指向第一个测试的时候，FAILED!!!这让人非常郁闷。所以我想到了能不能用round trip的方法来进行测试。做一个比喻，假如说我想证明WIN7的计算器程序是正确的，那么可以把相同的计算在WIN XP的计算器中跑一遍，如果两者结果一样，那么我可以认为WIN7的计算器程序也是正确的（如果XP的计算器有错怎么办？先别较真，有风险，但很小）。</p>
<p>我的做法就是，准备一些数据，首先用SUT进行查询，然后用LINQ进行查询，如果两者查询结果一致，那么可以认为程序是正确的，否则就是两者之一存在问题。</p>
<p>首先准备一些测试数据，保存为XML文件，第一方便对测试数据进行CRUD，第二可以用XmlSerializer把这些数据转换为对象，方便用LINQ查询。<br />
<span id="more-563"></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
26
27
28
29
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;">&lt; ?xml <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;onlinefriends<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;friends<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;onlinefrienddata<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;friendid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1300010000<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/friendid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;province<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>北京市<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/province<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;city<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>北京市<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/city<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;age<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>18<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/age<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;gender<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/gender<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;hasphoto<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/hasphoto<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/onlinefrienddata<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;onlinefrienddata<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;friendid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1300010002<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/friendid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;province<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>北京市<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/province<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;city<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>北京市<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/city<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;age<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>27<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/age<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;gender<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/gender<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;hasphoto<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>false<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/hasphoto<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/onlinefrienddata<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;onlinefrienddata<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;friendid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1300010004<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/friendid<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;province<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>广东省<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/province<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;city<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>广州市<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/city<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;age<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>45<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/age<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;gender<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/gender<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;hasphoto<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/hasphoto<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/onlinefrienddata<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/friends<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/onlinefriends<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>然后需要有一个类，利用XmlSerializer来反序列化这些测试数据</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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #008000;">&#91;</span>XmlRoot<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;OnlineFriends&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">class</span> OnlineFriends
<span style="color: #008000;">&#123;</span>
	<span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">bool</span> IsEmpty <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">true</span><span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #0600FF; font-weight: bold;">static</span> OnlineFriends fs <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> OnlineFriends<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #0600FF; font-weight: bold;">private</span> OnlineFriends<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">static</span> OnlineFriends Instance
	<span style="color: #008000;">&#123;</span>
		get
		<span style="color: #008000;">&#123;</span>
			<span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>fs<span style="color: #008000;">.</span><span style="color: #0000FF;">IsEmpty</span><span style="color: #008000;">&#41;</span>
			<span style="color: #008000;">&#123;</span>
				fs<span style="color: #008000;">.</span><span style="color: #0000FF;">Deserialize</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
			<span style="color: #008000;">&#125;</span>
			<span style="color: #0600FF; font-weight: bold;">return</span> fs<span style="color: #008000;">;</span>
		<span style="color: #008000;">&#125;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">void</span> Deserialize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		var serialzer <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> XmlSerializer<span style="color: #008000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #008000;">&#40;</span>OnlineFriends<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
		<span style="color: #0600FF; font-weight: bold;">using</span> <span style="color: #008000;">&#40;</span>XmlReader xmlreader <span style="color: #008000;">=</span> XmlReader<span style="color: #008000;">.</span><span style="color: #0000FF;">Create</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;OnlineFriends.xml&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			fs <span style="color: #008000;">=</span> serialzer<span style="color: #008000;">.</span><span style="color: #0000FF;">Deserialize</span><span style="color: #008000;">&#40;</span>xmlreader<span style="color: #008000;">&#41;</span> <span style="color: #0600FF; font-weight: bold;">as</span> OnlineFriends<span style="color: #008000;">;</span>
			fs<span style="color: #008000;">.</span><span style="color: #0000FF;">IsEmpty</span> <span style="color: #008000;">=</span> <span style="color: #0600FF; font-weight: bold;">false</span><span style="color: #008000;">;</span>
		<span style="color: #008000;">&#125;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">class</span> OnlineFriendData
	<span style="color: #008000;">&#123;</span>
		<span style="color: #008000;">&#91;</span>XmlElement<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;FriendId&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
		<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">int</span> FriendId <span style="color: #008000;">&#123;</span> get<span style="color: #008000;">;</span> set<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
		<span style="color: #008000;">&#91;</span>XmlElement<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;Province&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
		<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">string</span> Province <span style="color: #008000;">&#123;</span> get<span style="color: #008000;">;</span> set<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
		<span style="color: #008000;">&#91;</span>XmlElement<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;City&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
		<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">string</span> City <span style="color: #008000;">&#123;</span> get<span style="color: #008000;">;</span> set<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
		<span style="color: #008000;">&#91;</span>XmlElement<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;Age&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
		<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">int</span> Age <span style="color: #008000;">&#123;</span> get<span style="color: #008000;">;</span> set<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
		<span style="color: #008000;">&#91;</span>XmlElement<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;Gender&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
		<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">byte</span> Gender <span style="color: #008000;">&#123;</span> get<span style="color: #008000;">;</span> set<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
		<span style="color: #008000;">&#91;</span>XmlElement<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;HasPhoto&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
		<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">bool</span> HasPhoto <span style="color: #008000;">&#123;</span> get<span style="color: #008000;">;</span> set<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	<span style="color: #008000;">&#91;</span>XmlArray<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;Friends&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
	<span style="color: #008000;">&#91;</span>XmlArrayItem<span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;OnlineFriendData&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#93;</span>
	<span style="color: #0600FF; font-weight: bold;">public</span> OnlineFriendData<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> Friends <span style="color: #008000;">&#123;</span> get<span style="color: #008000;">;</span> set<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>数据的准备工作就差不多了，看一个简单的测试。首先这个测试方法会重新初始化测试数据，然后查询27岁的在线会员，查询出来的结果保存在ids的INT列表中。OnlineFriends.Instance.Friends对象中保存了所有在线好友的数据，它是一个实现了IEnumerable<t>接口的类，所以可以使用LINQ相关的<a href="http://msdn.microsoft.com/en-us/library/bb383977.aspx" target="_blank">扩展方法</a>。</p>
<p>在OnlineFriends.Instance.Friends.Where(x => x.Age == age)语句中，“x => x.Age == age”是一个应用了Lambda表达式的匿名委托，整个语句的意思就是在OnlineFriends.Instance.Friends这个集合中，找到年龄==age的元素。</p>
<p>不过找到了以后还不行啊，SUT返回的是INT列表，而刚才查到的是OnlineFriendData对象的集合，接下来可以用Select(y => y.FriendId).ToList<int>()对集合做一个投影，只取出FriendId属性，并且转换为INT列表。</p>
<p>最后用CollectionAssert.AreEquivalent()方法对两个INT列表进行比较，看列表是否相等。</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: #008000;">&#91;</span>TestMethod<span style="color: #008000;">&#93;</span>
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">void</span> GetOnlineFriendsIdList_Query_Age_LowerUpperDiffOne<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #008080; font-style: italic;">//重新初始化测试数据</span>
	TestHelp<span style="color: #008000;">.</span><span style="color: #0000FF;">InitForSearch</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #6666cc; font-weight: bold;">int</span> age <span style="color: #008000;">=</span> <span style="color: #FF0000;">27</span><span style="color: #008000;">;</span>
	OnlineFriendQuery query <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> OnlineFriendQuery<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	query<span style="color: #008000;">.</span><span style="color: #0000FF;">AgeLowerBound</span> <span style="color: #008000;">=</span> age<span style="color: #008000;">;</span>
	query<span style="color: #008000;">.</span><span style="color: #0000FF;">AgeUpperBound</span> <span style="color: #008000;">=</span> age<span style="color: #008000;">;</span>
             <span style="color: #008080; font-style: italic;">//根据条件查询在线会员，在这里就是要查询27岁的会员</span>
	List<span style="color: #008000;">&lt;</span><span style="color: #6666cc; font-weight: bold;">int</span><span style="color: #008000;">&gt;</span> ids <span style="color: #008000;">=</span> FriendListGateway<span style="color: #008000;">.</span><span style="color: #0000FF;">FriendListProvider</span><span style="color: #008000;">.</span><span style="color: #0000FF;">GetOnlineFriendsIdList</span><span style="color: #008000;">&#40;</span>query, MyAllPc<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
	<span style="color: #008080; font-style: italic;">//Two collects are equivalent</span>
	CollectionAssert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEquivalent</span><span style="color: #008000;">&#40;</span>OnlineFriends<span style="color: #008000;">.</span><span style="color: #0000FF;">Instance</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Friends</span><span style="color: #008000;">.</span><span style="color: #0600FF; font-weight: bold;">Where</span><span style="color: #008000;">&#40;</span>x <span style="color: #008000;">=&gt;</span> x<span style="color: #008000;">.</span><span style="color: #0000FF;">Age</span> <span style="color: #008000;">==</span> age<span style="color: #008000;">&#41;</span><span style="color: #008000;">.</span><span style="color: #0600FF; font-weight: bold;">Select</span><span style="color: #008000;">&#40;</span>y <span style="color: #008000;">=&gt;</span> y<span style="color: #008000;">.</span><span style="color: #0000FF;">FriendId</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">.</span><span style="color: #0000FF;">ToList</span><span style="color: #008000;">&lt;/</span><span style="color: #6666cc; font-weight: bold;">int</span><span style="color: #008000;">&gt;&lt;</span><span style="color: #6666cc; font-weight: bold;">int</span><span style="color: #008000;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>, ids<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&lt;/</span><span style="color: #6666cc; font-weight: bold;">int</span><span style="color: #008000;">&gt;</span></pre></td></tr></table></div>

<p>假如使用我最开始的测试方法（就是先准备测试数据，然后人工统计一下里面有多少个27岁的数据，最后进行比较），我在完成了这一条测试以后，接下来还要小心翼翼地添加测试数据，不能再添加年龄是27岁的数据，要不然就会影响到测试结果。但是应用了LINQ以后，我在后续的测试数据设计中就无需要担心新设计的测试数据会对老的测试造成影响。甚至我还可以用程序生成各种不同的数据，填入数据库，供我测试用。</int></t></p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/whiteboxtesting/using-linq-to-object-in-testing/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>自己动手创建Web测试验证规则</title>
		<link>http://magustest.com/blog/automationtesting/adding-web-test-verifaction-rule/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=adding-web-test-verifaction-rule</link>
		<comments>http://magustest.com/blog/automationtesting/adding-web-test-verifaction-rule/#comments</comments>
		<pubDate>Tue, 26 May 2009 02:32:25 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[自动化测试]]></category>
		<category><![CDATA[VSTS]]></category>
		<category><![CDATA[WebTest]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=516</guid>
		<description><![CDATA[”Web测试”是由一系列 HTTP 请求组成，通过发出 HTTP 请求在协议层工作的测试类型。在VSTS中自带了若干个预先定义好的验证规则，例如在返回的页面上寻找某些字符，返回的文档中是否包含某些Tag，等等。前一段时间在测试一个安全过滤器，这个过滤器的基本功能就是过滤用户输入中的一些有可能构成安全隐患的内容，例如&#60;script&#62;标签的内容，JS内容等等。按照预先给出的测试用例执行完测试以后，OK，没有问题，不过在上线一个小时后发现一个问题，就是经过安全过滤器输出的内容会比原来输入的内容多了两个字符&#8211;“rn”，这个问题一下就修复好了，Trim一下。然后我就要给原来的测试加上对于这个问题的回归测试实现。很不巧，Web测试没有一个对返回内容长度进行验证的验证规则，不过微软提供了创建自定义验证规则的接口，我们可以创建一个验证ContentLength的规则。 1. 创建一个新的类库项目，这个项目是一个独立的可重用的类库，所创建的Web测试插件可以在不同的包含有Web测试的项目中使用。其实可以跟上一篇文章说的WebTest Plugin公用一个类库项目 2. 在该类库项目中添加对“Microsoft.VisualStudio.QualityTools.WebTestFramework”的引用 3. 在该类库项目中创建一个从ValidationRule派生出的类 4. 重写基类的Validate方法 5. 打开包含有Web Test的项目，并且在该项目中引用刚才添加的包含有自定义验证规则的类库项目 6. 打开需要调用自定义验证规则的Web测试，点击”Add Validation Rule”，选择刚才编写好的验证规则。 现在看看在自定义验证规则中添加参数，让用户输入相应的参数，从而使得验证规则更加灵活。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class ResponseContentLength : ValidationRule &#123; public int Length &#123; get; set; &#125; //输入的长度 public bool <a href='http://magustest.com/blog/automationtesting/adding-web-test-verifaction-rule/'>[...]</a>
No related posts.]]></description>
			<content:encoded><![CDATA[<p>”Web测试”是由一系列 HTTP 请求组成，通过发出 HTTP 请求在协议层工作的测试类型。在VSTS中自带了若干个预先定义好的验证规则，例如在返回的页面上寻找某些字符，返回的文档中是否包含某些Tag，等等。前一段时间在测试一个安全过滤器，这个过滤器的基本功能就是过滤用户输入中的一些有可能构成安全隐患的内容，例如&lt;script&gt;标签的内容，JS内容等等。按照预先给出的测试用例执行完测试以后，OK，没有问题，不过在上线一个小时后发现一个问题，就是经过安全过滤器输出的内容会比原来输入的内容多了两个字符&#8211;“rn”，这个问题一下就修复好了，Trim一下。然后我就要给原来的测试加上对于这个问题的回归测试实现。很不巧，Web测试没有一个对返回内容长度进行验证的验证规则，不过微软提供了创建自定义验证规则的接口，我们可以创建一个验证ContentLength的规则。</p>
<p>1. 创建一个新的类库项目，这个项目是一个独立的可重用的类库，所创建的Web测试插件可以在不同的包含有Web测试的项目中使用。其实可以跟上一篇文章说的WebTest Plugin公用一个类库项目</p>
<p>2. 在该类库项目中添加对“Microsoft.VisualStudio.QualityTools.WebTestFramework”的引用</p>
<p>3. 在该类库项目中创建一个从ValidationRule派生出的类</p>
<p>4. 重写基类的Validate方法</p>
<p>5. 打开包含有Web Test的项目，并且在该项目中引用刚才添加的包含有自定义验证规则的类库项目</p>
<p>6. 打开需要调用自定义验证规则的Web测试，点击”Add Validation Rule”，选择刚才编写好的验证规则。</p>
<p>现在看看在自定义验证规则中添加参数，让用户输入相应的参数，从而使得验证规则更加灵活。<br />
<span id="more-516"></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
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">class</span> ResponseContentLength <span style="color: #008000;">:</span> ValidationRule
<span style="color: #008000;">&#123;</span>
	<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">int</span> Length <span style="color: #008000;">&#123;</span> get<span style="color: #008000;">;</span> set<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>                   <span style="color: #008080; font-style: italic;">//输入的长度</span>
	<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">bool</span> PassIfEqualsToContentLength <span style="color: #008000;">&#123;</span> get<span style="color: #008000;">;</span> set<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
	<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">override</span> <span style="color: #6666cc; font-weight: bold;">void</span> Validate<span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">object</span> sender, ValidationEventArgs e<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>e<span style="color: #008000;">.</span><span style="color: #0000FF;">Response</span> <span style="color: #008000;">!=</span> <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			e<span style="color: #008000;">.</span><span style="color: #0000FF;">IsValid</span> <span style="color: #008000;">=</span> <span style="color: #008000;">!</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>e<span style="color: #008000;">.</span><span style="color: #0000FF;">Response</span><span style="color: #008000;">.</span><span style="color: #0000FF;">ContentLength</span> <span style="color: #008000;">==</span> Length<span style="color: #008000;">&#41;</span> <span style="color: #008000;">^</span> PassIfEqualsToContentLength<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
		<span style="color: #008000;">&#125;</span>
		<span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #008000;">!</span>e<span style="color: #008000;">.</span><span style="color: #0000FF;">IsValid</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			e<span style="color: #008000;">.</span><span style="color: #0000FF;">Message</span> <span style="color: #008000;">=</span> <span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Format</span><span style="color: #008000;">&#40;</span><span style="color: #666666;">&quot;The length of the ContentLength: {0} is not equal to the expected result: {1}.&quot;</span>, e<span style="color: #008000;">.</span><span style="color: #0000FF;">Response</span><span style="color: #008000;">.</span><span style="color: #0000FF;">ContentLength</span>, Length<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
		<span style="color: #008000;">&#125;</span>
	<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>如果我们添加该自定义规则，那么会提示我们输入两个参数，一个是Length，另一个是一个布尔值；如果Response中的ContentLength和设置的Length相等，并且该布尔值设置为True，那么这个验证规则就算是通过。如图：</p>
<p><img src="http://magustest.com/blog/wp-content/uploads/2009/05/5-26-2009-10-26-01-am1.png" alt="5-26-2009-10-26-01-am" title="5-26-2009-10-26-01-am" width="560" height="426" class="alignnone size-full wp-image-517" /></p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/automationtesting/adding-web-test-verifaction-rule/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VSTS 2010 Test Edition文章收集</title>
		<link>http://magustest.com/blog/softwaretesting/vsts2010-test-edition-article-collection/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=vsts2010-test-edition-article-collection</link>
		<comments>http://magustest.com/blog/softwaretesting/vsts2010-test-edition-article-collection/#comments</comments>
		<pubDate>Thu, 21 May 2009 01:45:38 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[性能测试]]></category>
		<category><![CDATA[软件测试]]></category>
		<category><![CDATA[CodedUI Test]]></category>
		<category><![CDATA[VSTS]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=495</guid>
		<description><![CDATA[STS 2010 BETA 1在近期已经开始发布了，各路高手纷纷出动，在这里我就把我看到的一些不错的关于VSTS2010测试人员版本的文章收集一下，希望对其他人有帮助，也便于我以后复习用 文章： 《Automated User Interface Testing with Coded UI Test》VSTT官方博客出品，Coded UI Test入门 《VSTS 2010 Load Test Feature: Saving Test Logs》如何在VS的负载测试中记录日志，帮助定位问题 《VSTS 2010 Feature: Load test virtual user activity visualization》如果在用VSTS进行性能测试进行的过程中，CPU突然有一个不寻常的峰值出现，在以前是比较难找到原因的，此文给我们介绍了VSTS 2010的最新功能virtual user activity visualization 是如何帮助测试工程师找到问题的根源 《VSTS 2010 Feature: Web Test Recorder Plugins》如何在VSTS 2010中利用Web Test Recorder Plugins来做自定义的关联 《VSTS 2010: Enabling Test Impact Analysis》文章介绍了如何使用Test Impact <a href='http://magustest.com/blog/softwaretesting/vsts2010-test-edition-article-collection/'>[...]</a>
No related posts.]]></description>
			<content:encoded><![CDATA[<p>STS 2010 BETA 1在近期已经开始发布了，各路高手纷纷出动，在这里我就把我看到的一些不错的关于VSTS2010测试人员版本的文章收集一下，希望对其他人有帮助，也便于我以后复习用 <img src='http://magustest.com/blog/wp-includes/images/smilies/icon_lol.gif' alt=':lol:' class='wp-smiley' /> </p>
<p><strong>文章：</strong></p>
<p>《<a href="http://blogs.msdn.com/vstsqualitytools/archive/2009/06/12/automated-user-interface-testing-with-coded-ui-test.aspx" target="_blank">Automated User Interface Testing with Coded UI Test</a>》VSTT官方博客出品，Coded UI Test入门</p>
<p>《<a href="http://blogs.msdn.com/billbar/archive/2009/06/09/vsts-2010-load-test-feature-saving-test-logs.aspx" target="_blank">VSTS 2010 Load Test Feature: Saving Test Logs</a>》如何在VS的负载测试中记录日志，帮助定位问题</p>
<p>《<a href="http://blogs.msdn.com/slumley/archive/2009/06/09/vsts-2010-feature-load-test-virtual-user-activity-visualization.aspx" target="_blank">VSTS 2010 Feature: Load test virtual user activity visualization</a>》如果在用VSTS进行性能测试进行的过程中，CPU突然有一个不寻常的峰值出现，在以前是比较难找到原因的，此文给我们介绍了VSTS 2010的最新功能virtual user activity visualization 是如何帮助测试工程师找到问题的根源</p>
<p>《<a href="http://blogs.msdn.com/slumley/pages/vsts-2010-feature-web-test-recorder-plugins.aspx" target="_blank">VSTS 2010 Feature: Web Test Recorder Plugins</a>》如何在VSTS 2010中利用Web Test Recorder Plugins来做自定义的关联</p>
<p>《<a href="http://geekswithblogs.net/jakob/archive/2009/06/04/vsts-2010-enabling-test-impact-analysis.aspx" target="_blank">VSTS 2010: Enabling Test Impact Analysis</a>》文章介绍了如何使用Test Impact Analysis</p>
<p>《<a href="http://blogs.msdn.com/vstsqualitytools/archive/2009/05/29/the-evolution-of-the-ui-design-of-test-and-lab-manager.aspx" target="_blank">The Evolution of the UI Design of Test and Lab Manager</a>》一篇概要介绍 Lab Manager的文章</p>
<p>《<a href="http://msdn.microsoft.com/zh-cn/library/dd380763(en-us,VS.100).aspx" target="_blank">Quick Start Guide for Manual Testing</a>》MSDN上一篇讲述手动测试工程师如何用Lab Manager开展工作的文章</p>
<p>《<a href="http://blogs.msdn.com/jasonz/archive/2009/05/26/vs2010-tutorial-testing-tutorial-step-2.aspx" target="_blank">VS2010 Tutorial: Testing Tutorial (Step 2)</a>》文章极其详细地讲述了如何用VSTS 2010来提交一个BUG，并且展示一系列的新功能，来说明VSTS 2010如何帮助消除开发和测试之间的隔阂，减少那些不可重现的BUG。</p>
<p>《<a href="http://www.clemensreijnen.nl/post/Testing-in-the-Application-Lifecycle-with-Visual-Studio-2010-Test-Edition.aspx" target="_blank">Testing in the Application Lifecycle with Visual Studio 2010 Test Edition</a>》此文详细介绍了在VSTS2010中，测试工程师在整个应用开发生命周期中如何利用VSTS来帮助开展工作</p>
<p>《<a href="http://blogs.msdn.com/ratnaditya/archive/2009/06/01/running-automated-tests-in-manual-test-and-lab-manager-vsts-2010.aspx" target="_blank">Running automated tests in Manual Test and Lab Manager</a>》此文介绍了在Lab Manger中如何运行各种测试的方法</p>
<p>《<a href="http://blogs.msdn.com/slumley/pages/vs-2010-feature-web-test-playback-enhancements.aspx" target="_blank">VSTS 2010 Feature: Web Test Playback Enhancements</a>》文章介绍Web Test在UI方面的更新</p>
<p>《<a href="http://blogs.msdn.com/edglas/archive/2009/05/24/read-this-before-running-a-load-test-with-dev10-beta-1.aspx" target="_blank">Read this Before Running a Load Test with Dev10 Beta 1</a>》如果你的VSTS2010和2008是安装在同一台机器上，并且你又实用了VS的负载测试，那么这篇文章会告诉你如果对数据库进行设置，使得两个版本的负载测试数据能够共存互不影响</p>
<p>《<a href="http://blogs.infosupport.com/blogs/marcelv/archive/2009/05/22/how-to-enable-code-coverage-in-visual-studio-2010-unit-tests.aspx" target="_blank">How to enable code coverage in Visual Studio 2010 Unit tests</a>》，由于VSTS2010对于测试运行的一些改变，所以要打开代码覆盖率的操作与VS2008有所不同，这篇文章给我们讲述了操作细节</p>
<p>《<a href="http://blogs.msdn.com/mathew_aniyan/archive/2009/05/26/coded-ui-test-from-microsoft-test-lab-manager.aspx" target="_blank">Coded UI Test from Microsoft Test &amp; Lab Manager</a>》如何在VSTS的最新的Lab Manager中运行CodedUI Test</p>
<p>《<a href="http://blogs.msdn.com/mathew_aniyan/archive/2009/05/26/coded-ui-test-in-a-team-build.aspx" target="_blank">Coded UI Test in a Team Build</a>》这篇文章讲述了如何把一个CodedUI Test加到TEAM BUILD里面</p>
<p>《<a href="http://blogs.msdn.com/amit_chatterjee/archive/2009/05/24/the-lab-management-product-an-overview.aspx" target="_blank">The Lab Management Product – An Overview</a>》 Lab Management产品介绍。</p>
<p>《<a href="http://blogs.msdn.com/amit_chatterjee/archive/2009/05/14/official-names-for-the-2010-test-products-now-announced.aspx" target="_blank">Official Names for the 2010 Test Products now announced!</a> 》介绍了VSTS2010中，3个不同版本所包含的不同功能。</p>
<p>《<a href="http://blogs.msdn.com/slumley/pages/dev-10-feature-creating-excel-reports-for-load-test-data.aspx" target="_blank">VSTS 2010 Feature: Creating excel reports for Load Test Data</a>》，一篇介绍在VSTS2010中，如何创建一个Excel格式的性能报告的文章。</p>
<p>《<a href="http://blogs.msdn.com/edglas/archive/2009/05/24/read-this-before-running-a-load-test-with-dev10-beta-1.aspx" target="_blank">Rename load test database name before running a long test with VSTS2010 beta1</a>》，这篇文章告诉我们，如果VSTS2008和2010都安装在同一台机子上，那么在2010中运行负载测试的时候会更新数据库的schema，为了让VSTS2008的负载测试数据库和VS2010的共存，需要修改数据库的名字。</p>
<p>《<a href="http://blog.dynatrace.com/2009/05/20/how-to-extend-visual-studio-2010-web-and-load-testing-with-transactional-tracing/" target="_blank">How to extend Visual Studio 2010 Web- and Load-Testing with Transactional Tracing</a>》这篇文章讲述了如何给WEB测试做扩展。图文并茂！</p>
<p>《<a href="http://blogs.msdn.com/edglas/archive/2009/05/19/elevating-the-role-of-the-tester-with-visual-studio-2010.aspx" target="_blank">Elevating the Role of the Tester with Visual Studio 2010</a>》这篇文章详细讲述了各种各样测试工程师可以利用VSTS2010做什么样的东西，作者是VSTS测试人员版本的经理</p>
<p>《<a href="http://blogs.msdn.com/edglas/archive/2009/05/18/dev10-beta-1-available.aspx" target="_blank">Dev10 Beta 1 Available!</a>》这篇文章详细列出了VSTS2010 BETA1中，有关测试部分的更新。</p>
<p><strong>视频：</strong></p>
<p><a href="http://videos.visitmix.com/MIX09/T83M" target="_blank">Automated User Interface (UI) Testing with Microsoft Visual Studio Team System 2010</a>。一个微软的人介绍CodedUI Test，还有Test Impact，17分钟。</p>
<p><a href="http://channel9.msdn.com/shows/10-4/10-4-Episode-23-An-Introduction-to-Manual-Testing/" target="_blank">An Introduction to Manual Testing</a>。</p>
<p><strong>博客：</strong></p>
<p><a href="http://blogs.msdn.com/amit_chatterjee/default.aspx" target="_blank">Amit Chatterjee&#8217;s Blog</a>，VSTS的一个产品经理，这里经常会有关于VSTS测试部分的更新介绍</p>
<p><a href="http://blogs.msdn.com/edglas/default.aspx" target="_blank">Ed Glas&#8217;s blog on VSTS load testing</a>，也是VSTS的一个经理，他的博客主要关注Load Test和Web Test</p>
<p><a href="http://blogs.msdn.com/mathew_aniyan/" target="_blank">Mathew Aniyan&#8217;s Blog</a>，来路不明，Coded UI Test之霸！</p>
<p><a href="http://blogs.gotdotnet.com/lab_management/default.aspx" target="_blank">VSTS Lab Management team blog</a>，Lab Management官方博客</p>
<p><a href="http://blogs.msdn.com/vstsqualitytools/default.aspx" target="_blank">VS Team System Test</a>，VSTT官方博客</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/softwaretesting/vsts2010-test-edition-article-collection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>用VSPerfMon在测试ASP.NET程序的过程中收集代码覆盖率信息</title>
		<link>http://magustest.com/blog/softwaretesting/collecting-aspnet-code-coverage-date-using-vsperfmon/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=collecting-aspnet-code-coverage-date-using-vsperfmon</link>
		<comments>http://magustest.com/blog/softwaretesting/collecting-aspnet-code-coverage-date-using-vsperfmon/#comments</comments>
		<pubDate>Sat, 25 Apr 2009 15:27:20 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[软件测试]]></category>
		<category><![CDATA[Profiler]]></category>
		<category><![CDATA[VSTS]]></category>
		<category><![CDATA[代码覆盖]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=454</guid>
		<description><![CDATA[前两篇文章介绍了VSTS性能分析工具Profiler和如何用Profiler发现性能问题并且进行优化。今天想分享一下如何在测试ASP.NET程序的过程中获取代码覆盖率的信息。 设想如下场景，测试人员介入到项目的需求，分析，设计的阶段，得到了很多有用的文档和信息。接下来就到了编码的阶段，在这个时候测试工程师开始根据前面获得的信息来设计测试用例，做用例评审，力求测试用例覆盖能覆盖系统的每一个角落。不幸的是，系统实在是太大，没有人能确切地知道手上的测试用例对系统的覆盖（这里指定为代码的行覆盖）能达到什么样的程度。对于系统的关键部分，没有人希望在经过几轮测试以后，还有相当部分的代码是没有被执行过的。 解决这个问题的其中一个方法，就是对关键部分的代码进行代码覆盖率的统计。平时我做单元测试和接口测试的时候，得益于IDE的帮助，代码覆盖率信息很容易就能得到，但是对于部署在IIS上的ASP.NET代码，又如何去收集代码覆盖率信息呢？曾经找过好多.NET的代码覆盖率工具，没有合适的。不过就在最近，让我发现了VSPerfMon，VSTS自带的性能数据收集工具。真是众里寻他千百度，蓦然回首，那工具却在灯火阑珊处。 1. 首先要对需要进行代码覆盖率信息收集的二进制文件(DLL, EXE)用VSInstr进行处理，记得带上/COVERAGE参数 VSInstr “D:\Websites\somewhere\bin\MySpace.Web.UserHome.dll” /COVERAGE 2. 停掉IIS iisreset /stop 3. 用VSPerfClrEnv 设置相关的环境变量 VSPerfClrEnv /globaltraceon 4. 启动VSPerfMon；参数/COVERAGE代表本次监控收集的数据是代码覆盖率；/user:”NETWORK SERVICE”，指定用户名;/CS 启用跨域会话分析；/output:”d:\magus\0422.coverage”，指定输出文件的名字和路径，记得用.coverage作为扩展名。 VSPerfMon /COVERAGE /user:”NETWORK SERVICE” /CS /output:”d:\magus\0422.coverage” 在运行完上面这条命令以后，CMD窗口就提示： Started in Stand Alone Mode Filename: d:\magus\0422.coverage 这时候需要打开一个新的CMD进行余下的操作(原来的CMD就叫CMD_A，新开的就叫CMD_B吧) 5. 停止收集代码覆盖率信息数据，因为不想让代码覆盖率信息受到影响。 VSPerfCmd /globaloff 6. 启动IIS iisreset /start 7. 对ASP.NET程序进行预热 8. 重新开启代码覆盖率信息的收集 VSPerfCmd /globalon 9. 运行测试用例，手工OR自动都可以 10. 停止代码覆盖率信息的收集 <a href='http://magustest.com/blog/softwaretesting/collecting-aspnet-code-coverage-date-using-vsperfmon/'>[...]</a>
No related posts.]]></description>
			<content:encoded><![CDATA[<p>前两篇文章介绍了<a href="http://magustest.com/blog/net/intruduction-to-vsts-profile/" target="_blank">VSTS性能分析工具Profiler</a>和<a href="http://magustest.com/blog/net/using-vsts-profiler-find-bottleneck-and-optimize/" target="_blank">如何用Profiler发现性能问题并且进行优化</a>。今天想分享一下如何在测试ASP.NET程序的过程中获取代码覆盖率的信息。</p>
<p>设想如下场景，测试人员介入到项目的需求，分析，设计的阶段，得到了很多有用的文档和信息。接下来就到了编码的阶段，在这个时候测试工程师开始根据前面获得的信息来设计测试用例，做用例评审，力求测试用例覆盖能覆盖系统的每一个角落。不幸的是，系统实在是太大，没有人能确切地知道手上的测试用例对系统的覆盖（这里指定为代码的行覆盖）能达到什么样的程度。对于系统的关键部分，没有人希望在经过几轮测试以后，还有相当部分的代码是没有被执行过的。</p>
<p>解决这个问题的其中一个方法，就是对关键部分的代码进行代码覆盖率的统计。平时我做单元测试和接口测试的时候，得益于IDE的帮助，代码覆盖率信息很容易就能得到，但是对于部署在IIS上的ASP.NET代码，又如何去收集代码覆盖率信息呢？曾经找过好多.NET的代码覆盖率工具，没有合适的。不过就在最近，让我发现了VSPerfMon，VSTS自带的性能数据收集工具。真是众里寻他千百度，蓦然回首，那工具却在灯火阑珊处。</p>
<p><strong>1. 首先要对需要进行代码覆盖率信息收集的二进制文件(DLL, EXE)用VSInstr进行处理，记得带上/COVERAGE参数</strong></p>
<p><em><span style="text-decoration: underline;">VSInstr “D:\Websites\somewhere\bin\MySpace.Web.UserHome.dll” /COVERAGE</span></em></p>
<p><strong>2. 停掉IIS</strong></p>
<p><em><span style="text-decoration: underline;">iisreset /stop</span></em></p>
<p><strong>3. 用VSPerfClrEnv 设置相关的环境变量</strong></p>
<p><em><span style="text-decoration: underline;">VSPerfClrEnv /globaltraceon</span></em></p>
<p><strong>4. 启动VSPerfMon；参数/COVERAGE代表本次监控收集的数据是代码覆盖率；/user:”NETWORK SERVICE”，指定用户名;/CS 启用跨域会话分析；/output:”d:\magus\0422.coverage”，指定输出文件的名字和路径，记得用.coverage作为扩展名。</strong><br />
<span id="more-454"></span><br />
<em><span style="text-decoration: underline;">VSPerfMon /COVERAGE /user:”NETWORK SERVICE” /CS /output:”d:\magus\0422.coverage”</span></em></p>
<p>在运行完上面这条命令以后，CMD窗口就提示：</p>
<blockquote><p>Started in Stand Alone Mode<br />
Filename: d:\magus\0422.coverage</p></blockquote>
<p>这时候<span style="text-decoration: underline;"><strong>需要打开一个新的CMD进行余下的操作(原来的CMD就叫CMD_A，新开的就叫CMD_B吧)</strong></span></p>
<p><strong>5. 停止</strong><strong>收集</strong><strong>代码覆盖率信息数据，因为不想让代码覆盖率信息受到影响。</strong></p>
<p><em><span style="text-decoration: underline;">VSPerfCmd /globaloff</span></em></p>
<p><strong>6. 启动IIS</strong></p>
<p><em><span style="text-decoration: underline;">iisreset /start</span></em></p>
<p><strong>7. 对ASP.NET程序进行预热</strong></p>
<p><strong>8. 重新开启代码覆盖率信息的收集</strong></p>
<p><em><span style="text-decoration: underline;">VSPerfCmd /globalon</span></em></p>
<p><strong>9. 运行测试用例，手工OR自动都可以</strong></p>
<p><strong>10. 停止代码覆盖率信息的收集</strong></p>
<p><em><span style="text-decoration: underline;">VSPerfCmd /globaloff</span></em></p>
<p><strong>11. 停止IIS</strong></p>
<p><em><span style="text-decoration: underline;">iisreset /stop</span></em></p>
<p>这时候在CMD_A中会提示“UnRegistering process (7784)”，还是保持CMD_A不动，继续操作CMD_B</p>
<p><strong>12. 结束代码覆盖率的收集，并且生成.coverage文件</strong></p>
<p><em><span style="text-decoration: underline;">VSPerfCmd /shutdown</span></em></p>
<p>这时候在原来的CMD_A中就会出现如下信息：</p>
<blockquote><p>Shutting Down Named Pipe Server<br />
Shutting Down Buffer Writer<br />
Shutting Down Process Deamon</p></blockquote>
<p>如果没有看到错误提示信息，那么本次代码覆盖率收集就应该成功了。</p>
<p><strong>13. 在VSTS IDE中打开刚才生成的.coverage查看代码覆盖率。</strong></p>
<p>如图：</p>
<p><img class="alignnone size-full wp-image-455" title="coverage" src="http://magustest.com/blog/wp-content/uploads/2009/04/coverage1.png" alt="coverage" width="610" height="212" /></p>
<p>正如以前讨论过的，<a href="http://magustest.com/blog/softwaretesting/whiteboxtesting/100-percent-statement-coverage-not-enough/" target="_blank">100%的代码覆盖率是不够的</a>，那么我们在拿到代码覆盖率数据以后，应该看一下在运行完测试用例以后以后，系统的哪些代码还没有被执行过，然后回头设计一些新的测试用例来测试那些未被测试的代码。这就要求<a href="http://magustest.com/blog/softwaretesting/do-software-tester-needs-to-know-how-to-code/" target="_blank">测试工程师要能看懂代码</a>了。</p>
<p>本文思路得益于大半年前看到这篇博客“<a href="http://www.51testing.com/?uid-13997-action-viewspace-itemid-87396" target="_blank">如何引入代码覆盖率度量提高测试质量</a>”，一直惦记于心，终于找到了适用于.NET程序的解决方法了，呵呵。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/softwaretesting/collecting-aspnet-code-coverage-date-using-vsperfmon/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>用VSTS Profiler发现性能问题并且进行优化实例</title>
		<link>http://magustest.com/blog/net/using-vsts-profiler-find-bottleneck-and-optimize/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=using-vsts-profiler-find-bottleneck-and-optimize</link>
		<comments>http://magustest.com/blog/net/using-vsts-profiler-find-bottleneck-and-optimize/#comments</comments>
		<pubDate>Thu, 23 Apr 2009 04:11:50 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[性能测试]]></category>
		<category><![CDATA[Profiler]]></category>
		<category><![CDATA[VSTS]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=439</guid>
		<description><![CDATA[上一篇文章介绍了如何使用VSTS的Profiler，今天想分享一下对于一个ASP.NET应用程序，用Profiler找到性能问题并且对之进行优化。 由于ASP.NET程序运行在一个硕大的框架上，所以一般用Sample模式收集到的数据，对发现性能问题帮助不大，以下是一个用Sample模式收集的结果： 从这个报告中我们可以看到，前5个工作量最大的函数和执行单独工作最多的函数都是系统函数。 下面看一下有针对性地用检测模式收集的数据： 本文就采用“检测”模式收集性能数据来进行分析和处理。 首先，把本次测试的目标DLL用VSInstr工具进行处理，使得Profiler能够收集相关的性能数据，这一个步骤非常关键，通常来说不需要设置额外的参数，就是默认的方式就可以了，例如：VSInstr “D:\Websites\xxxx\bin\xxxx.dll”，在处理的过程中可能会提示一些错误，具体错误的信息可以在这里查找。把相应的DLL处理完毕以后，就在命令行输入以下指令（命令行的指令用斜体加下划线表示；说明文字加黑） 停止IIS iisreset /stop 设置分析.NET应用程序所需要的环境变量，在运行完这个命令以后需要重启。由于使用检测方式进行数据采集，所以这里我用globaltraceon参数。 VSPerfClrEnv /globaltraceon 启动性能数据收集。/start:trace，告诉收集器要收集检测数据；/user:”NETWORK SERVICE” ，由于是要对IIS进行的数据进行采集，所以需要制定用户NETWORK SERVICE；/CS，启用跨进程分析，看了一些文章说是分析ASP.NET程序一般都把这个选项打开，原因不详；/output:”d:\magus\0422.vsp”，指定输出文件的路径和名称；/wincounter:”\Processor(_Total)\% Processor Time”，收集处理器的参数，这里需要注意的是，wincouter后面的性能计数器名字一定要是全名，有一个方法可以查询系统的性能计数器的全称，就是用VSTS的Server Explorer，然后找到相应的服务器(一般是本机)，下面有一个“Performance Counters”；如果要收集多个性能计数器的数据，只需要多加几个 /wincounter 参数即可，例如我在收集处理器时间的同时，还想知道Context Switcher每秒的数据。 VSPerfCmd /start:trace /user:”NETWORK SERVICE” /CS /output:”d:\magus\0422.vsp” /wincounter:”\Processor(_Total)\% Processor Time” /wincounter:”\System\Context Switches/sec” 在IIS起来之前先停止性能数据的收集 VSPerfCmd /globaloff 启动IIS iisreset /start 对程序进行预热，这一步也是很关键，因为IIS启动以后，程序需要预热才能达到稳定的状态，因为程序首次被访问的时候有些代码会被编译，所以为了降低对性能测试的影响，应该现对被测的程序进行预热。在预热完毕以后重新启动性能数据的收集。 VSPerfCmd /globalon &#8211; 运行性能测试场景 &#8211; 测试运行完毕以后，停止性能数据的收集 VSPerfCmd /globaloff 停掉IIS iisreset /stop 关闭性能数据收集器，这一步完成以后就能生成包含数据的文件了 VSPerfCmd <a href='http://magustest.com/blog/net/using-vsts-profiler-find-bottleneck-and-optimize/'>[...]</a>
No related posts.]]></description>
			<content:encoded><![CDATA[<p>上一篇文章介绍了<a href="http://magustest.com/blog/net/intruduction-to-vsts-profile/" target="_blank">如何使用VSTS的Profiler</a>，今天想分享一下对于一个ASP.NET应用程序，用Profiler找到性能问题并且对之进行优化。</p>
<p>由于ASP.NET程序运行在一个硕大的框架上，所以一般用Sample模式收集到的数据，对发现性能问题帮助不大，以下是一个用Sample模式收集的结果：</p>
<p><img class="alignnone size-full wp-image-442" title="iis-sample" src="http://magustest.com/blog/wp-content/uploads/2009/04/iis-sample1.png" alt="iis-sample" width="549" height="236" /></p>
<p>从这个报告中我们可以看到，前5个工作量最大的函数和执行单独工作最多的函数都是系统函数。</p>
<p>下面看一下有针对性地用检测模式收集的数据：</p>
<p><img class="alignnone size-full wp-image-444" title="instr-function-with-indi-work1" src="http://magustest.com/blog/wp-content/uploads/2009/04/instr-function-with-indi-work11.png" alt="instr-function-with-indi-work1" width="532" height="139" /></p>
<p>本文就采用“检测”模式收集性能数据来进行分析和处理。</p>
<p>首先，把本次测试的目标DLL用VSInstr工具进行处理，使得Profiler能够收集相关的性能数据，这一个步骤非常关键，通常来说不需要设置额外的参数，就是默认的方式就可以了，例如：VSInstr “D:\Websites\xxxx\bin\xxxx.dll”，在处理的过程中可能会提示一些错误，具体错误的信息可以在<a href="http://msdn.microsoft.com/en-us/library/ms242734.aspx" target="_blank">这里</a>查找。把相应的DLL处理完毕以后，就在命令行输入以下指令（命令行的指令用斜体加下划线表示；说明文字加黑）<br />
<span id="more-439"></span><br />
<strong>停止IIS</strong></p>
<p><span style="text-decoration: underline;"><em>iisreset /stop</em></span></p>
<p><strong>设置分析.NET应用程序所需要的环境变量，在运行完这个命令以后需要重启。由于使用检测方式进行数据采集，所以这里我用globaltraceon参数。</strong></p>
<p><span style="text-decoration: underline;"><em>VSPerfClrEnv /globaltraceon</em></span></p>
<p><strong>启动性能数据收集。<span style="text-decoration: underline;">/start:trace</span>，告诉收集器要收集检测数据；/user:”NETWORK SERVICE” ，由于是要对IIS进行的数据进行采集，所以需要制定用户NETWORK SERVICE；<span style="text-decoration: underline;">/CS</span>，启用跨进程分析，看了一些文章说是分析ASP.NET程序一般都把这个选项打开，原因不详；<span style="text-decoration: underline;">/output:”d:\magus\0422.vsp”</span>，指定输出文件的路径和名称；<span style="text-decoration: underline;">/wincounter:”\Processor(_Total)\% Processor Time”</span>，收集处理器的参数，这里需要注意的是，wincouter后面的性能计数器名字一定要是全名，有一个方法可以查询系统的性能计数器的全称，就是用VSTS的Server Explorer，然后找到相应的服务器(一般是本机)，下面有一个“Performance Counters”；如果要收集多个性能计数器的数据，只需要多加几个 /wincounter 参数即可，例如我在收集处理器时间的同时，还想知道Context Switcher每秒的数据。</strong></p>
<p><span style="text-decoration: underline;"><em>VSPerfCmd /start:trace /user:”NETWORK SERVICE” /CS /output:”d:\magus\0422.vsp” /wincounter:”\Processor(_Total)\% Processor Time” /wincounter:”\System\Context Switches/sec”</em></span></p>
<p><strong>在IIS起来之前先停止性能数据的收集</strong></p>
<p><span style="text-decoration: underline;"><em>VSPerfCmd /globaloff</em></span></p>
<p><strong>启动IIS</strong></p>
<p><em><span style="text-decoration: underline;">iisreset /start</span></em></p>
<p><strong>对程序进行预热，这一步也是很关键，因为IIS启动以后，程序需要预热才能达到稳定的状态，因为程序首次被访问的时候有些代码会被编译，所以为了降低对性能测试的影响，应该现对被测的程序进行预热。在预热完毕以后重新启动性能数据的收集。</strong></p>
<p><em><span style="text-decoration: underline;">VSPerfCmd /globalon</span></em></p>
<p><strong>&#8211; 运行性能测试场景 &#8211;<br />
</strong></p>
<p><strong>测试运行完毕以后，停止性能数据的收集</strong></p>
<p><em><span style="text-decoration: underline;">VSPerfCmd /globaloff</span></em></p>
<p><strong>停掉IIS</strong></p>
<p><em><span style="text-decoration: underline;">iisreset /stop</span></em></p>
<p><strong>关闭性能数据收集器，这一步完成以后就能生成包含数据的文件了</strong></p>
<p><em><span style="text-decoration: underline;">VSPerfCmd /shutdown</span></em></p>
<p>首先来看看收集到的报告</p>
<p><img class="alignnone size-full wp-image-447" title="time-before-opt1" src="http://magustest.com/blog/wp-content/uploads/2009/04/time-before-opt11.png" alt="time-before-opt1" width="547" height="55" /></p>
<p>在这个方法里面有一段不知名方法（其实是因为没有相应的Symbol，⊙﹏⊙b汗）占用了大量的计算时间，然后就找到相应的代码，原来该不知名方法是一个动态生成的代码，该段代码大概就是会创建一个新的Client对象，然后向另外一台服务器发起一个请求。其实不用每次调用该方法都创建一个新的Client对象。然后我尝试着把这个Client改为静态变量，经过优化以后的报告对比如下：</p>
<p><img class="alignnone size-full wp-image-448" title="time-after-opt" src="http://magustest.com/blog/wp-content/uploads/2009/04/time-after-opt1.png" alt="time-after-opt" width="523" height="251" /></p>
<p>效果还是挺明显的，但是当我重新测试一下性能的时候，被打击了一下，改动前后的性能对比相差很小，小的都可以认为是误差：P，因为在一个颇为庞大的项目中，这点小小的改动的确不可能影响大局。不过这次试验让我学会了用Profiler来找到ASP.NET运行中执行较慢的语句，并且看看这些语句有什么问题（可能是一个调用存储过程的方法很慢，而真正的原因是数据库有问题），定位问题所在，然后解决问题，最后回测一下对比改动前后的结果。看是否达到预期的优化效果。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/net/using-vsts-profiler-find-bottleneck-and-optimize/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VSTS性能分析工具Profiler的介绍</title>
		<link>http://magustest.com/blog/net/intruduction-to-vsts-profile/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=intruduction-to-vsts-profile</link>
		<comments>http://magustest.com/blog/net/intruduction-to-vsts-profile/#comments</comments>
		<pubDate>Wed, 22 Apr 2009 08:41:23 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[性能测试]]></category>
		<category><![CDATA[Profiler]]></category>
		<category><![CDATA[VSTS]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=426</guid>
		<description><![CDATA[在MSDN文档中，对于VSTS中的Development Edition的介绍主要分两大块，第一是“编写高质量的代码”，第二就是“使用分析工具对应用程序性能进行分析”。在VSTS里面有一个工具，叫Profiler，这个工具可以帮助研发人员在程序运行的过程中收集相关的数据，并且对之进行分析，从而达到帮助实现性能调优的目的。本文讲述如何在使用命令行工具来对ASP.NET程序进行性能测试相关数据的收集。 在VSTS的Profiler中，有两种(VSTS2010好像有5种了)Profiling的方法，第一种是采样(Sampling)，第二种是检测(Instrumentation)。对于采样模式，它的工作原理是Profiler定期中断CPU并且收集函数的调用堆栈信息。在网上找到一个图，对于采样工作方式的描述非常清晰： 对于检测模式，他的工作原理是用VSInstr程序在原始的代码中插入一些用于计算时间的代码，例如A函数调用B函数，那么在调用B函数的前后都会被插入用于计算时间的代码，具体可以看下图： 下面我自己写了一个小的Sample类，然后把编译好的代码用Reflector来查看，很容易地就能看出区别。第一个图是没有经过VSInstr处理的原始代码： 下图就是经过VSInstr处理后，反编译后的代码： 可以看到VSInstr程序修改了原来的DLL。在检测模式下，只有经过修改后的DLL才能收集到数据。 在VSTS中，一般可以通过Analyze菜单下的Launch Performance Wizard来新建一个性能会话，然后进行性能数据的采集。 对于ASP.NET程序，可以通过以下步骤来进行“采样” iisreset /stop VSPerfClrEnv /globalsampleon VSPerfCmd /start:sample /user:”NETWORK SERVICE” /output:”d:\somewhere\xxxx.vsp” VSPerfCmd /globaloff iisreset /start VSPerfCmd /attach:xxxx VSPerfCmd /globalon &#8211;run the test scenario&#8211; VSPerfCmd /globaloff VSPerfCmd /detach iisreset /stop VSPerfCmd /shutdown 第一步是停掉IIS 然后通过VSPerfClrEnv对环境变量进行设置，具体可以查文档，做完这一步以后通常需要重启一下电脑 第三步就是通过VSPerfCmd启动性能数据收集 接下来的VSPerfCmd /globaloff就是暂停性能数据的收集 然后重启IIS，并且访问一下这个服务器上的页面，使得W3WP进程启动 查看W3WP.EXE的进程ID，然后通过VSPerfCmd /attach:xxxx把Profiler attach到IIS中 通过VSPerfCmd /globalon重新让Profiler进行性能数据的采集 然后就可以运行性能测试的场景 运行测试完毕以后就用VSPerfCmd /globaloff停止性能数据的采集 接着用VSPerfCmd <a href='http://magustest.com/blog/net/intruduction-to-vsts-profile/'>[...]</a>
No related posts.]]></description>
			<content:encoded><![CDATA[<p>在<a href="http://msdn.microsoft.com/zh-cn/library/47f7hz7y.aspx" target="_blank">MSDN文档</a>中，对于VSTS中的Development Edition的介绍主要分两大块，第一是“编写高质量的代码”，第二就是“使用分析工具对应用程序性能进行分析”。在VSTS里面有一个工具，叫Profiler，这个工具可以帮助研发人员在程序运行的过程中收集相关的数据，并且对之进行分析，从而达到帮助实现性能调优的目的。本文讲述如何在使用命令行工具来对ASP.NET程序进行性能测试相关数据的收集。</p>
<p>在VSTS的Profiler中，有两种(VSTS2010好像有5种了)Profiling的方法，第一种是采样(Sampling)，第二种是检测(Instrumentation)。对于采样模式，它的工作原理是Profiler定期中断CPU并且收集函数的调用堆栈信息。在网上找到一个图，对于采样工作方式的描述非常清晰：</p>
<p><img class="alignnone size-full wp-image-429" title="how-sampling-works" src="http://magustest.com/blog/wp-content/uploads/2009/04/how-sampling-works1.jpg" alt="how-sampling-works" width="500" height="330" /></p>
<p>对于检测模式，他的工作原理是用VSInstr程序在原始的代码中插入一些用于计算时间的代码，例如A函数调用B函数，那么在调用B函数的前后都会被插入用于计算时间的代码，具体可以看下图：<br />
<span id="more-426"></span><br />
<img class="alignnone size-full wp-image-430" title="how-instr-works" src="http://magustest.com/blog/wp-content/uploads/2009/04/how-instr-works1.jpg" alt="how-instr-works" width="600" height="300" /></p>
<p>下面我自己写了一个小的Sample类，然后把编译好的代码用Reflector来查看，很容易地就能看出区别。第一个图是没有经过VSInstr处理的原始代码：</p>
<p><img class="alignnone size-full wp-image-431" title="before-instr" src="http://magustest.com/blog/wp-content/uploads/2009/04/before-instr1.png" alt="before-instr" width="351" height="274" /></p>
<p>下图就是经过VSInstr处理后，反编译后的代码：</p>
<p><img class="alignnone size-full wp-image-432" title="after-instr" src="http://magustest.com/blog/wp-content/uploads/2009/04/after-instr1.png" alt="after-instr" width="600" height="356" /></p>
<p>可以看到VSInstr程序修改了原来的DLL。在检测模式下，只有经过修改后的DLL才能收集到数据。</p>
<p>在VSTS中，一般可以通过Analyze菜单下的Launch Performance Wizard来新建一个性能会话，然后进行性能数据的采集。</p>
<p><span style="font-size: medium;"><strong>对于ASP.NET程序，可以通过以下步骤来进行“采样”</strong></span></p>
<blockquote><p>iisreset /stop<br />
VSPerfClrEnv /globalsampleon<br />
VSPerfCmd /start:sample /user:”NETWORK SERVICE” /output:”d:\somewhere\xxxx.vsp”<br />
VSPerfCmd /globaloff<br />
iisreset /start<br />
VSPerfCmd /attach:xxxx<br />
VSPerfCmd /globalon</p>
<p>&#8211;run the test scenario&#8211;</p>
<p>VSPerfCmd /globaloff<br />
VSPerfCmd /detach<br />
iisreset /stop<br />
VSPerfCmd /shutdown</p></blockquote>
<ol>
<li>第一步是停掉IIS</li>
<li>然后通过VSPerfClrEnv对环境变量进行设置，具体可以查文档，做完这一步以后通常需要重启一下电脑</li>
<li>第三步就是通过VSPerfCmd启动性能数据收集</li>
<li>接下来的VSPerfCmd /globaloff就是暂停性能数据的收集</li>
<li>然后重启IIS，并且访问一下这个服务器上的页面，使得W3WP进程启动</li>
<li>查看W3WP.EXE的进程ID，然后通过VSPerfCmd /attach:xxxx把Profiler attach到IIS中</li>
<li>通过VSPerfCmd /globalon重新让Profiler进行性能数据的采集</li>
<li>然后就可以运行性能测试的场景</li>
<li>运行测试完毕以后就用VSPerfCmd /globaloff停止性能数据的采集</li>
<li>接着用VSPerfCmd /detach让Profiler不要附着在IIS上</li>
<li>停掉IIS &#8212; iisreset /stop</li>
<li>执行VSPerfCmd /shutdown，这一步执行完毕以后，在d:\somewhere\下就有一个xxxx.vsp的性能报告。</li>
</ol>
<p><span style="font-size: medium;"><strong>对于ASP.NET程序，可以通过以下步骤来进行“检测”</strong></span></p>
<p>检测和采样其实是大同小异的，但是有一个关键的步骤就是在进行检测之前，一定要记得用VSInstr命令对需要进行检测的DLL或者EXE文件进行处理，建议一次不要检测太多文件，检测时间不要太长，因为检测所产生的数量是非常大的，产生的文件大小都是按G级别计算了。</p>
<blockquote><p>iisreset /stop<br />
VSPerfClrEnv /globaltraceon<br />
VSPerfCmd /start:trace /user:”NETWORK SERVICE” /CS /output:”d:\xxx\0422.vsp”<br />
VSPerfCmd /globaloff<br />
iisreset /start<br />
&#8211; 预热 &#8211;<br />
VSPerfCmd /globalon</p>
<p>&#8211;run code&#8211;</p>
<p>VSPerfCmd /globaloff<br />
iisreset /stop<br />
VSPerfCmd /shutdown</p></blockquote>
<p>重复一次，在做以上的步骤之前必须要用VSInstr对目标二进制文件进行处理。这里详细步骤就不做解释了，命令的主要区别就是在做检测的时候，就免去了Attach到IIS这个步骤了。</p>
<p>采样和检测，前者是宏观的性能数据采集，后者是微观的性能数据采集。对于CPU负载较高的程序，用采样会得到比较好的效果；但是如果程序运行过程中并没有消耗很多的CPU资源，那么用采样可能就不能收集到太多有用的信息。所以在不同的场景下需要应用不同的性能数据收集方法。</p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/net/intruduction-to-vsts-profile/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>VSTS测试人员版本快速指南已经发布</title>
		<link>http://magustest.com/blog/net/vstt-quick-reference-guide-download/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=vstt-quick-reference-guide-download</link>
		<comments>http://magustest.com/blog/net/vstt-quick-reference-guide-download/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 01:43:24 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[VSTS]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=404</guid>
		<description><![CDATA[今天从VSTS LOAD TEST TEAM的一位成员的博客得知，他们今天发布了VSTS测试人员版本快速指南，我下载了浏览了一下，WEB TEST和LOAD TEST的内容讲的较多，这个指南是以问答的形式出现，个人感觉比较好。引用他们的一句原话就是“This doc is a must have for anyone working in VSTT”。可见这个分量多重。 这本指南有别于MSDN文档，这个PDF更加注重实用，主要是总结了在使用VSTT的过程中出现的问题，以及解决这些问题的方法，推荐用MSTEST的同行都下一个哦。 下载地址：VSTT Quick Reference Guide 1.0 No related posts.
No related posts.]]></description>
			<content:encoded><![CDATA[<p>今天从<a href="http://blogs.msdn.com/edglas/default.aspx" target="_blank">VSTS LOAD TEST TEAM的一位成员的博客</a>得知，他们今天发布了VSTS测试人员版本快速指南，我下载了浏览了一下，WEB TEST和LOAD TEST的内容讲的较多，这个指南是以问答的形式出现，个人感觉比较好。引用他们的一句原话就是“This doc is a <span style="color: #ff0000;"><strong>must </strong></span>have for anyone working in VSTT”。可见这个分量多重。</p>
<p>这本指南有别于MSDN文档，这个PDF更加注重实用，主要是总结了在使用VSTT的过程中出现的问题，以及解决这些问题的方法，推荐用MSTEST的同行都下一个哦。</p>
<p><strong>下载地址</strong>：<a href="http://vstt2008qrg.codeplex.com/" target="_blank">VSTT Quick Reference Guide 1.0</a></p>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/net/vstt-quick-reference-guide-download/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>利用序列化和反序列化实现深拷贝</title>
		<link>http://magustest.com/blog/net/serialize-deserialize-implement-deep-copy/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=serialize-deserialize-implement-deep-copy</link>
		<comments>http://magustest.com/blog/net/serialize-deserialize-implement-deep-copy/#comments</comments>
		<pubDate>Wed, 25 Mar 2009 06:24:05 +0000</pubDate>
		<dc:creator>magus</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://magustest.com/blog/?p=389</guid>
		<description><![CDATA[假如说有一个简单的类，只有2个属性，那么可以用比较简单的方法实现深拷贝。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 &#91;Serializable&#93; public class Person &#123; public int Height &#123; get; set; &#125; public string FirstName &#123; get; set; &#125; &#125; &#160; class Program &#123; static void Main&#40;string&#91;&#93; args&#41; &#123; //实例化一个对象 Person PersonOne = new Person&#40;&#41;; <a href='http://magustest.com/blog/net/serialize-deserialize-implement-deep-copy/'>[...]</a>
Related posts:<ol>
<li><a href='http://magustest.com/blog/whiteboxtesting/introduction-to-pex-automated-white-box-testing-for-dotnet/' rel='bookmark' title='PEX-.NET自动化白盒测试工具的介绍(1)'>PEX-.NET自动化白盒测试工具的介绍(1)</a></li>
<li><a href='http://magustest.com/blog/net/automatic-generate-xml-instance-by-using-xsd/' rel='bookmark' title='用XSD自动生成XML对应的.NET实体类'>用XSD自动生成XML对应的.NET实体类</a></li>
<li><a href='http://magustest.com/blog/net/linq-type-convert/' rel='bookmark' title='LINQ查询操作中的类型关系'>LINQ查询操作中的类型关系</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>假如说有一个简单的类，只有2个属性，那么可以用比较简单的方法实现深拷贝。</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
</pre></td><td class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #008000;">&#91;</span>Serializable<span style="color: #008000;">&#93;</span>
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">class</span> Person
<span style="color: #008000;">&#123;</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">int</span> Height <span style="color: #008000;">&#123;</span> get<span style="color: #008000;">;</span> set<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
    <span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">string</span> FirstName <span style="color: #008000;">&#123;</span> get<span style="color: #008000;">;</span> set<span style="color: #008000;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #6666cc; font-weight: bold;">class</span> Program <span style="color: #008000;">&#123;</span>
    <span style="color: #0600FF; font-weight: bold;">static</span> <span style="color: #6666cc; font-weight: bold;">void</span> Main<span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> args<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #008080; font-style: italic;">//实例化一个对象</span>
        Person PersonOne <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Person<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
        PersonOne<span style="color: #008000;">.</span><span style="color: #0000FF;">FirstName</span> <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;John&quot;</span><span style="color: #008000;">;</span>
        PersonOne<span style="color: #008000;">.</span><span style="color: #0000FF;">Height</span> <span style="color: #008000;">=</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
        <span style="color: #008080; font-style: italic;">//深拷贝</span>
        Person DeepCopyPerson <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Person<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
        DeepCopyPerson<span style="color: #008000;">.</span><span style="color: #0000FF;">FirstName</span> <span style="color: #008000;">=</span> PersonOne<span style="color: #008000;">.</span><span style="color: #0000FF;">FirstName</span><span style="color: #008000;">;</span>
        DeepCopyPerson<span style="color: #008000;">.</span><span style="color: #0000FF;">Height</span> <span style="color: #008000;">=</span> PersonOne<span style="color: #008000;">.</span><span style="color: #0000FF;">Height</span><span style="color: #008000;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p><span id="more-389"></span><br />
代码中的DeepCopyPerson对象就是对PersonOne对象的一个深拷贝。其实还可以用序列化和反序列化的方法来实现对对象的深拷贝。Person类的[Serializable]属性是为了下面介绍序列化反序列化方法做深拷贝而做的准备，在这里没什么特别含义。</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; font-weight: bold;">public</span> <span style="color: #0600FF; font-weight: bold;">static</span> T DeepCopy<span style="color: #008000;">&lt;</span>t<span style="color: #008000;">&gt;</span><span style="color: #008000;">&#40;</span>T obj<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
    <span style="color: #6666cc; font-weight: bold;">object</span> retval<span style="color: #008000;">;</span>
    <span style="color: #0600FF; font-weight: bold;">using</span> <span style="color: #008000;">&#40;</span>MemoryStream ms <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> MemoryStream<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
    <span style="color: #008000;">&#123;</span>
        BinaryFormatter bf <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> BinaryFormatter<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #008080; font-style: italic;">//序列化成流</span>
        bf<span style="color: #008000;">.</span><span style="color: #0000FF;">Serialize</span><span style="color: #008000;">&#40;</span>ms, obj<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
        ms<span style="color: #008000;">.</span><span style="color: #0000FF;">Seek</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">0</span>, SeekOrigin<span style="color: #008000;">.</span><span style="color: #0000FF;">Begin</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #008080; font-style: italic;">//反序列化成对象</span>
        retval <span style="color: #008000;">=</span> bf<span style="color: #008000;">.</span><span style="color: #0000FF;">Deserialize</span><span style="color: #008000;">&#40;</span>ms<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
        ms<span style="color: #008000;">.</span><span style="color: #0000FF;">Close</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #008000;">&#125;</span>
    <span style="color: #0600FF; font-weight: bold;">return</span> <span style="color: #008000;">&#40;</span>T<span style="color: #008000;">&#41;</span>retval<span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&lt;/</span>t<span style="color: #008000;">&gt;</span></pre></td></tr></table></div>

<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: #6666cc; font-weight: bold;">class</span> Program <span style="color: #008000;">&#123;</span>
    <span style="color: #0600FF; font-weight: bold;">static</span> <span style="color: #6666cc; font-weight: bold;">void</span> Main<span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> args<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #008080; font-style: italic;">//实例化一个对象</span>
        Person PersonOne <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> Person<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
        PersonOne<span style="color: #008000;">.</span><span style="color: #0000FF;">FirstName</span> <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;John&quot;</span><span style="color: #008000;">;</span>
        PersonOne<span style="color: #008000;">.</span><span style="color: #0000FF;">Height</span> <span style="color: #008000;">=</span> <span style="color: #FF0000;">1</span><span style="color: #008000;">;</span>
        <span style="color: #008080; font-style: italic;">//深拷贝</span>
        Person DeepCopyPerson <span style="color: #008000;">=</span> DeepCopy<span style="color: #008000;">&lt;</span>person<span style="color: #008000;">&gt;</span><span style="color: #008000;">&#40;</span>PersonOne<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&lt;/</span>person<span style="color: #008000;">&gt;</span></pre></td></tr></table></div>

<p>只要一个类被声明为可序列化的（就是带有[Serializable]标签），就可以用这个方法来进行深拷贝。记下来，免得以后自己忘记了。</p>
<p>Related posts:<ol>
<li><a href='http://magustest.com/blog/whiteboxtesting/introduction-to-pex-automated-white-box-testing-for-dotnet/' rel='bookmark' title='PEX-.NET自动化白盒测试工具的介绍(1)'>PEX-.NET自动化白盒测试工具的介绍(1)</a></li>
<li><a href='http://magustest.com/blog/net/automatic-generate-xml-instance-by-using-xsd/' rel='bookmark' title='用XSD自动生成XML对应的.NET实体类'>用XSD自动生成XML对应的.NET实体类</a></li>
<li><a href='http://magustest.com/blog/net/linq-type-convert/' rel='bookmark' title='LINQ查询操作中的类型关系'>LINQ查询操作中的类型关系</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/net/serialize-deserialize-implement-deep-copy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>测试代码重构实例</title>
		<link>http://magustest.com/blog/whiteboxtesting/refactoring-unit-test/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=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 <a href='http://magustest.com/blog/whiteboxtesting/refactoring-unit-test/'>[...]</a>
No related posts.]]></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: #008000;">&#91;</span>TestMethod<span style="color: #008000;">&#93;</span>
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">void</span> GetPaymentAccountByOwnerID<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #6666cc; font-weight: bold;">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: #008000;">.</span><span style="color: #0000FF;">DeletePaymentAccountByOwnerId</span><span style="color: #008000;">&#40;</span>ownerId<span style="color: #008000;">&#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: #008000;">.</span><span style="color: #0000FF;">PaymentProvider</span><span style="color: #008000;">.</span><span style="color: #0000FF;">GetPaymentAccountByOwnerID</span><span style="color: #008000;">&#40;</span>ownerId, AccountOwnerType<span style="color: #008000;">.</span><span style="color: #0000FF;">NormalUser</span><span style="color: #008000;">&#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: #008000;">.</span><span style="color: #0000FF;">IsTrue</span><span style="color: #008000;">&#40;</span>paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">AccountID</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span>DateTime<span style="color: #008000;">.</span><span style="color: #0000FF;">Now</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">CreateTime</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span>DateTime<span style="color: #008000;">.</span><span style="color: #0000FF;">Now</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">UpdateTime</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">0</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">Balance</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">0</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">AvailableBalance</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">0</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">FreezeAccount</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#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: #008000;">&#91;</span>TestMethod<span style="color: #008000;">&#93;</span>
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">void</span> GetPaymentAccountByOwnerID<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #6666cc; font-weight: bold;">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: #008000;">.</span><span style="color: #0000FF;">DeletePaymentAccountByOwnerId</span><span style="color: #008000;">&#40;</span>ownerId<span style="color: #008000;">&#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: #008000;">.</span><span style="color: #0000FF;">PaymentProvider</span><span style="color: #008000;">.</span><span style="color: #0000FF;">GetPaymentAccountByOwnerID</span><span style="color: #008000;">&#40;</span>ownerId, AccountOwnerType<span style="color: #008000;">.</span><span style="color: #0000FF;">NormalUser</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #008080; font-style: italic;">//Verify the payment account instance</span>
	PaymentAccountAssertion<span style="color: #008000;">&#40;</span>paymentAccount<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">void</span> PaymentAccountAssertion<span style="color: #008000;">&#40;</span>PaymentAccount paymentAccount<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">IsTrue</span><span style="color: #008000;">&#40;</span>paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">AccountID</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span>DateTime<span style="color: #008000;">.</span><span style="color: #0000FF;">Now</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">CreateTime</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span>DateTime<span style="color: #008000;">.</span><span style="color: #0000FF;">Now</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">UpdateTime</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">0</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">Balance</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">0</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">AvailableBalance</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">0</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">FreezeAccount</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#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: #008000;">&#91;</span>TestMethod<span style="color: #008000;">&#93;</span>
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">void</span> GetPaymentAccountByOwnerID<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #6666cc; font-weight: bold;">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: #008000;">.</span><span style="color: #0000FF;">DeletePaymentAccountByOwnerId</span><span style="color: #008000;">&#40;</span>ownerId<span style="color: #008000;">&#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: #008000;">.</span><span style="color: #0000FF;">PaymentProvider</span><span style="color: #008000;">.</span><span style="color: #0000FF;">GetPaymentAccountByOwnerID</span><span style="color: #008000;">&#40;</span>ownerId, AccountOwnerType<span style="color: #008000;">.</span><span style="color: #0000FF;">NormalUser</span><span style="color: #008000;">&#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: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	PaymentAccountAssertion<span style="color: #008000;">&#40;</span>expected, paymentAccount<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">void</span> PaymentAccountAssertion<span style="color: #008000;">&#40;</span>PaymentAccount expectedObject, PaymentAccount paymentAccount<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">IsTrue</span><span style="color: #008000;">&#40;</span>paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">AccountID</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span>DateTime<span style="color: #008000;">.</span><span style="color: #0000FF;">Now</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">CreateTime</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span>DateTime<span style="color: #008000;">.</span><span style="color: #0000FF;">Now</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">UpdateTime</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span>expectedObject<span style="color: #008000;">.</span><span style="color: #0000FF;">Balance</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">Balance</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span>expectedObject<span style="color: #008000;">.</span><span style="color: #0000FF;">AvailableBalance</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">AvailableBalance</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span>expectedObject<span style="color: #008000;">.</span><span style="color: #0000FF;">FreezeAccount</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">FreezeAccount</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#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; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">void</span> ObjectAreEqual<span style="color: #008000;">&lt;</span>t<span style="color: #008000;">&gt;</span><span style="color: #008000;">&#40;</span>T expected, T actual, List<span style="color: #008000;">&lt;</span><span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">&gt;</span> excludedProperties<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #000000;">System</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Type</span> myType <span style="color: #008000;">=</span> <span style="color: #008000;">typeof</span><span style="color: #008000;">&#40;</span>T<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	PropertyInfo<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> props <span style="color: #008000;">=</span> myType<span style="color: #008000;">.</span><span style="color: #0000FF;">GetProperties</span><span style="color: #008000;">&#40;</span>BindingFlags<span style="color: #008000;">.</span><span style="color: #0600FF; font-weight: bold;">Public</span> <span style="color: #008000;">|</span> BindingFlags<span style="color: #008000;">.</span><span style="color: #0000FF;">Instance</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #0600FF; font-weight: bold;">foreach</span> <span style="color: #008000;">&#40;</span>var item <span style="color: #0600FF; font-weight: bold;">in</span> props<span style="color: #008000;">&#41;</span>
	<span style="color: #008000;">&#123;</span>
		<span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span><span style="color: #0600FF; font-weight: bold;">null</span> <span style="color: #008000;">==</span> excludedProperties <span style="color: #008000;">||</span> <span style="color: #008000;">!</span>excludedProperties<span style="color: #008000;">.</span><span style="color: #0000FF;">Contains</span><span style="color: #008000;">&#40;</span>item<span style="color: #008000;">.</span><span style="color: #0000FF;">Name</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
		<span style="color: #008000;">&#123;</span>
			<span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>item<span style="color: #008000;">.</span><span style="color: #0000FF;">PropertyType</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Equals</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">double</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
			<span style="color: #008000;">&#123;</span>
				Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">double</span><span style="color: #008000;">&#41;</span>item<span style="color: #008000;">.</span><span style="color: #0000FF;">GetValue</span><span style="color: #008000;">&#40;</span>expected, <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">&#41;</span>, <span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">double</span><span style="color: #008000;">&#41;</span>item<span style="color: #008000;">.</span><span style="color: #0000FF;">GetValue</span><span style="color: #008000;">&#40;</span>actual, <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">&#41;</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
			<span style="color: #008000;">&#125;</span>
			<span style="color: #0600FF; font-weight: bold;">else</span> <span style="color: #0600FF; font-weight: bold;">if</span> <span style="color: #008000;">&#40;</span>item<span style="color: #008000;">.</span><span style="color: #0000FF;">PropertyType</span><span style="color: #008000;">.</span><span style="color: #0000FF;">Equals</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">float</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span>
			<span style="color: #008000;">&#123;</span>
				Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">float</span><span style="color: #008000;">&#41;</span>item<span style="color: #008000;">.</span><span style="color: #0000FF;">GetValue</span><span style="color: #008000;">&#40;</span>expected, <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">&#41;</span>, <span style="color: #008000;">&#40;</span><span style="color: #6666cc; font-weight: bold;">float</span><span style="color: #008000;">&#41;</span>item<span style="color: #008000;">.</span><span style="color: #0000FF;">GetValue</span><span style="color: #008000;">&#40;</span>actual, <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">&#41;</span>, <span style="color: #FF0000;">0.0001</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
			<span style="color: #008000;">&#125;</span>
			<span style="color: #0600FF; font-weight: bold;">else</span>
			<span style="color: #008000;">&#123;</span>
				Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span>item<span style="color: #008000;">.</span><span style="color: #0000FF;">GetValue</span><span style="color: #008000;">&#40;</span>expected, <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">&#41;</span>, item<span style="color: #008000;">.</span><span style="color: #0000FF;">GetValue</span><span style="color: #008000;">&#40;</span>actual, <span style="color: #0600FF; font-weight: bold;">null</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
			<span style="color: #008000;">&#125;</span>
		<span style="color: #008000;">&#125;</span>
	<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008000;">&lt;/</span><span style="color: #6666cc; font-weight: bold;">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: #008000;">&#91;</span>TestMethod<span style="color: #008000;">&#93;</span>
<span style="color: #0600FF; font-weight: bold;">public</span> <span style="color: #6666cc; font-weight: bold;">void</span> GetPaymentAccountByOwnerID<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	<span style="color: #6666cc; font-weight: bold;">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: #008000;">.</span><span style="color: #0000FF;">DeletePaymentAccountByOwnerId</span><span style="color: #008000;">&#40;</span>ownerId<span style="color: #008000;">&#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: #008000;">.</span><span style="color: #0000FF;">PaymentProvider</span><span style="color: #008000;">.</span><span style="color: #0000FF;">GetPaymentAccountByOwnerID</span><span style="color: #008000;">&#40;</span>ownerId, AccountOwnerType<span style="color: #008000;">.</span><span style="color: #0000FF;">NormalUser</span><span style="color: #008000;">&#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: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	PaymentAccountAssertion<span style="color: #008000;">&#40;</span>expected, paymentAccount<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0600FF; font-weight: bold;">private</span> <span style="color: #6666cc; font-weight: bold;">void</span> PaymentAccountAssertion<span style="color: #008000;">&#40;</span>PaymentAccount expectedObject, PaymentAccount paymentAccount<span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#123;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">IsTrue</span><span style="color: #008000;">&#40;</span>paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">AccountID</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span>DateTime<span style="color: #008000;">.</span><span style="color: #0000FF;">Now</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">CreateTime</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
	Assert<span style="color: #008000;">.</span><span style="color: #0000FF;">AreEqual</span><span style="color: #008000;">&#40;</span>DateTime<span style="color: #008000;">.</span><span style="color: #0000FF;">Now</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span>, paymentAccount<span style="color: #008000;">.</span><span style="color: #0000FF;">UpdateTime</span><span style="color: #008000;">.</span><span style="color: #0000FF;">DayOfYear</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
	List<span style="color: #008000;">&lt;</span><span style="color: #6666cc; font-weight: bold;">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: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">&gt;&lt;</span><span style="color: #6666cc; font-weight: bold;">string</span><span style="color: #008000;">&gt;</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#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: #008000;">&#125;</span><span style="color: #008000;">;</span>
&nbsp;
	TestUtilityGateway<span style="color: #008000;">.</span><span style="color: #0000FF;">CustomizedAssert</span><span style="color: #008000;">.</span><span style="color: #0000FF;">ObjectAreEqual</span><span style="color: #008000;">&lt;</span>paymentaccount<span style="color: #008000;">&gt;</span><span style="color: #008000;">&#40;</span>expectedObject, paymentAccount, ExcludedProperties<span style="color: #008000;">&#41;</span><span style="color: #008000;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008000;">&lt;/</span>paymentaccount<span style="color: #008000;">&gt;&lt;/</span><span style="color: #6666cc; font-weight: bold;">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>
<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://magustest.com/blog/whiteboxtesting/refactoring-unit-test/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

