<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Bill Liu&amp;#39;s Blog</title><subtitle type="html">.Net, .Net Profiling, Windows Azure, Managed Fault Injection, cloud computing, software testing</subtitle><id>http://blogs.msdn.com/b/billliu/atom.aspx</id><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/" /><link rel="self" type="application/atom+xml" href="http://blogs.msdn.com/b/billliu/atom.aspx" /><generator uri="http://telligent.com" version="5.6.50428.7875">Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><updated>2010-03-27T19:41:00Z</updated><entry><title>优秀员工的十大要素</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/12/19/10379344.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/12/19/10379344.aspx</id><published>2012-12-19T07:52:00Z</published><updated>2012-12-19T07:52:00Z</updated><content type="html">&lt;p&gt;前两天整理自己在微软的工作邮箱时候，偶然看到多年以前比尔&amp;middot;盖茨写给员工的一份邮件，我一直保存偶尔翻出来看看。他在该邮件中列出了成为公司优秀员工的10大要素。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;经常有人问我如何成为一个好的经理，我在许多专栏中也多次谈到。但是很少有人反问：如何成为一个好的员工？&lt;/p&gt;
&lt;p&gt;下面是我在最优秀的员工身上发现的他们共有的10大特征，公司应该竭尽所能吸引具有这些特征的员工。 如果你具有这些特征，你可能就是这些最好员工中的一个了。&lt;/p&gt;
&lt;p&gt;第一：你必须对你的产品有强烈的好奇心。你必须亲自使用你做的产品。这一点非常重要，不仅在计算机世界里，在其他高速发展的科技行业也是一样。如果你对自己的产品不热情，你很快就会被淘汰了。&lt;/p&gt;
&lt;p&gt;第二：你必须擅长和客户讨论他们是如何使用你的产品的，他们喜欢什么，不喜欢什么。你需要不停宣传你的产品同时很现实地清楚知道你的产品中的不足和需要提高的方面。&lt;/p&gt;
&lt;p&gt;第三：一旦理解了客户需求，你必须很乐意地去思考该产品中如何帮助客户。比如，如果你是开发软件的，你可以问自己我的产品如何让用户更享受工作，如何让用户更乐于学习，如何让用户在家里更乐于使用？&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;前面三点彼此关联。成功来自于你理解和对产品，使用的技术和用户的需求的深深关注。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;第四：做为员工中的一员，你应该保持和公司一样的长远策略。员工需要专注于自己一生的目标，比如发展自己的能力。这种动力需要很强的自律但是会有好的回报。当然管理层也应该鼓励这种自我激励。比如如果你是销售，每月的销售量是很好的考核标准。当销售量超过预期是很好，但是如果超过预期销售量是你唯一的动力，你可能会错过类如团队合作和发展等有助于长期成功的方面。&lt;/p&gt;
&lt;p&gt;第五：你必须在某个方面有特别的专长同时又有广博的知识。特别是大公司需要可以快速学习的员工。没人可以保证今天的特长明天还管用。所以必须好学。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;第六：你必须灵活利用给你的机会。微软为每个员工提供多种不同类型的工作。我们鼓励对管理感兴趣的员工在不同领域理工作，即使需要不停换工作。&lt;/p&gt;
&lt;p&gt;第七：好的员工想学习一些经济商业知识。你的公司为什么要做这个产品？业务模式是什么？如何赚钱的？很奇怪有些公司不告诉员工这些东西。员工需要明白业界的成功与失败，这样她才会明白他们的价值所在。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;第八：你必须关注你的竞争对手。我很喜欢哪些留意市场动态的员工。我们的竞争对手聪明在哪里？从他们哪里学什么？如何避免他们犯的错误？&lt;/p&gt;
&lt;p&gt;第九：你必须思考。分析问题但是不可以一直在分析。了解各种可能的折衷以及他们的影响。比如是有一点信息后就快速行动呢？还是等待更多信息后在行动呢？学会在两者间的折衷。现实考虑问题，有效利用时间，考虑如何给别人清晰的意见。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;最后：不要忽略那些明显的特征比如诚实，守信，努力。这些特征不用说至关重要。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10379344" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author></entry><entry><title>提高软件质量实践―― Facebook 篇</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/11/04/facebook.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/11/04/facebook.aspx</id><published>2012-11-04T23:12:29Z</published><updated>2012-11-04T23:12:29Z</updated><content type="html">&lt;p&gt;Facebook从04年的哈佛校园的学生项目在短短的7－8年的时间中快速增长为拥有10亿用户的世界上最大的社交网络，又一次见证了互联网创业成功的奇迹。同时它的产品研发流程也成为了众多互联网产品公司的追逐对象。今天我们来看一下facebook在产品质量控制方面的实践。有人说，现在的google象早期的微软，现在的facebook象早期的Google. 我觉得无不道理。 虽然facebook已经早已不是创业公司，但是不难看出它在产品研发和质量控制仍然保持着创业公司的风格。在产品研发上，他们以小的研发团队为核心，遵循几个非常重要的原则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Be there from start to ship: 每个工程师自始至终负责产品。从最开始的一个想法，到开发原型，到内部审核，反馈，到产品开发，上线和维护，全部有工程师自己搞定。&lt;/li&gt;
&lt;li&gt;Show work early and often: &amp;nbsp;facebook非常看重反馈，尤其早期内部反馈。他们鼓励工程师有了想法后，尽快开发出原型，尽快得到反馈。&lt;/li&gt;
&lt;li&gt;Gets your hands dirty: 动手去做，去实现。&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t fall in love: 互联网产品是不断变化的，不需要等到把一个产品设计的很完美了才发布。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;为了遵循以上原则，facebook工程师采用以下质量控制手段来保证产品质量：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;开发对质量负责： 开发从设计，实现，测试，到部署都要自己做。其它做工具，流程的工程师通过开发工具和流程来帮助开发人员更为简单方便地做测试，做部署和做监控。每个开发人员有自己单独的测试环境，测试环境就是运行在开发本地机器上，部署非常简单快速。测试环境用的是真实的用户数据。&lt;/li&gt;
&lt;li&gt;持续集成和测试自动化：每周发布一次。星期天晚上，要发布的构建从主线上分支出来到发布分支，到星期二的中午如果没有大的问题，就可以上线了。所有的测试运行控制在10分钟以内，所以不需要考虑不运行哪些测试用例。运行所有测试用例。 （只是听说，没有经过考证。）&lt;/li&gt;
&lt;li&gt;内测 （dog food）：发布之前，公司员工使用要发布的功能。2－3天之内可以有几百个或上千个人在使用新功能。负责要发布功能的开发人员在星期天晚上到星期二中午之间会做大量的测试 （一边上班，一边刷微博，岂不是很爽 :) ）。&lt;/li&gt;
&lt;li&gt;发布风险控制：新功能本身质量可能有问题，新功能也可能影响其它现有功能。为了减少或控制这些风险。Facebook开发了一整套完善的发布，控制，监控流程和工具。做到：1.测试通过后，产品质量基本有保证。2.即使有漏测的bug，只会影响很少量的用户。3.及时监控到问题。4.及时修复。&lt;/li&gt;
&lt;li&gt;产品监控：监控产品的系统的运行状态。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Facebook之所以采取这种质量控制策略和它的产品特点密切相关：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用户对社交产品质量的容忍度相对较高。比如发微博，现在连不上，等一会在连接也可以，现在发布不出去可以等一会再发，粉丝数量统计有误，没有人太关心。其实facebook并不认为自己的质量差。他们认为产品的质量高低不是有多少个failed测试用例,有多少个bug来确定的，而是有用户对质量的期望值来决定的。如果用户对产品质量的期望值很高很高，一个bug漏掉了都会照成质量差的印象，用户很有可能放弃使用。相反，如果用户的期望值一般，100个bug漏掉了都不会影响用户继续使用。所以facebook产品发布的条件是满足用户对质量的期望值即可。&lt;/li&gt;
&lt;li&gt;相对宽松的产品发布周期。不想微软或google很多产品已经在市场上，用户对下一版本的发布时间和新增加功能的期望很高，这往往给产品开发组的压力很大。Facebook基本没有这个问题，它有适合自己的发布期限，不用受到外界干扰。&lt;/li&gt;
&lt;li&gt;产品发布和监控流程比较完善，即使有漏测的bug，对用户的影响可以控制在最小而且可以及时发现及时修复。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Facebook质量控制中引以为豪而且倍受瞩目的就是&amp;ldquo;没有专职测试工程师&amp;rdquo;。我这里需要专门讨论一下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;什么是&amp;ldquo;专职测试工程师&amp;rdquo;？ 头衔里面有&amp;ldquo;测试&amp;rdquo;的工程师？专门找bug的工程师？专门做质量控制的工程师？等等。&lt;/li&gt;
&lt;li&gt;Facebook的确没有带&amp;ldquo;测试&amp;rdquo;头衔的工程师，也没有专门运行产品找bug的工程师。每个人都是开发工程师。但是他们的实际工作有区别，有的专门做面对用户的产品，有的专门做测试，开发工具，有的专门做产品的构建和持续集成工具和流程，有的专门做发布和监控的工具和流程。如果按照传统意义上的开发和测试的划分的话，除了第一类外，其他都可以看做专职测试工程师。&lt;/li&gt;
&lt;li&gt;Facebook不是惟一一个没有带&amp;ldquo;测试&amp;rdquo;头衔工程师的公司，很多软件公司都没有，比如twitter.&lt;/li&gt;
&lt;li&gt;很多人把专职测试工程师指专门运行产品找bug的工程师。微软在2005年去掉STE (software test engineer )岗位，就已经没有这一类型的专职测试工程师了。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;所以个人认为，专职测试工程师是个非常模糊的结论。尤其现在我们对产品质量控制方法的不断演变和提高，&amp;ldquo;测试&amp;rdquo;的概念不仅仅是指找bug了，所有围绕提高产品质量的工作都是测试。头衔上有没有&amp;ldquo;测试&amp;rdquo;不重要，有没有&amp;ldquo;测试&amp;rdquo;岗位不重要，重要的是如何有效保证和提高产品质量。&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10365657" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="software testing" scheme="http://blogs.msdn.com/b/billliu/archive/tags/software+testing/" /></entry><entry><title>Dev owns testing, Dev owns quality, really?</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/09/03/dev-owns-testing-dev-owns-quality-really.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/09/03/dev-owns-testing-dev-owns-quality-really.aspx</id><published>2012-09-03T07:41:00Z</published><updated>2012-09-03T07:41:00Z</updated><content type="html">&lt;p&gt;You might hear a lot about dev owns quality recently. James whittaker, the former engineering director of Google, spends quite a lot pages in his new book &amp;lt;&amp;lt;how Google Test software&amp;gt;&amp;gt; &amp;nbsp;to articulate why dev should own testing, and why should dev owns quality, like this:&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&amp;ldquo;Who better to do all that testing than the people doing the actual coding? Who better to find the bug than the person who wrote it? Who is more incentivized to avoid writing the bug in the first place? The reason Google can get by with so few dedicated testers is because developers own&amp;nbsp; quality.&amp;rdquo;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;However, not surprisingly, there are arguments on this. Some, particularly fulltime tester/QA believe dev doesn&amp;rsquo;t have mindset or required skill set to do good testing. On other hand, you can&amp;rsquo;t ask one to test their own codes. Human is very bad on verifying her own work. Asking dev to test her own codes is like asking a wolf to guard sheep. It just won&amp;rsquo;t work.&lt;/p&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;Really?&lt;/p&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;Before we jump into any conclusion, let&amp;rsquo;s look at how things got evolved with a coding example. Assume dev was asked to provide an API to calculate tax based on the income, factor and a value stored in database. (disclaimer: the code example is to make a point with obvious bugs, no offense to dev :))&lt;/p&gt;
&lt;p&gt;In old days, dev doesn&amp;rsquo;t test her code but simply hands over to tester for quality assurance. The code very likely looks like this:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;class Tax {&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ......&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public double CalcTax(int income, int factor)&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DBConnection c = ConnectToDB();&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;Int t = c.GetValue(); &lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return income/(factor*t);&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;}&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Why? Because dev&amp;rsquo;s role is to writing products codes to build the features, not assure its quality. Quality is tester&amp;rsquo;s responsibility, so I don&amp;rsquo;t need to care and I don&amp;rsquo;t want to care. My performance is measured against how many lines of codes I write (or how many new features I build).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now,&amp;nbsp;dev&amp;nbsp;needs to do the testing&amp;hellip; the code probably looks like this:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;class Tax {&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ......&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public double CalcTax(int income, int factor)&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if factor == 0 then return 0;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DBConnection c = ConnectToDB();&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Int t = c.GetValue(); &lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (t==0) t=0; // this is bug.&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return income/(factor*t);&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt; }&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;assume dev made a mistake, it actually want to write if (t==0) t=0.1; the bug will stay undetected, due to its dependency on values in database. if there is no zero in the test db, the bug probably slip to customers that has zero in their db.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Then,&amp;nbsp;dev owns quality... the codes probably looks like this:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;span style="font-size: x-small;"&gt;create fake database mock.&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;span style="font-size: x-small;"&gt;TestCase1.CalcTax(100, 1);&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;span style="font-size: x-small;"&gt;TestCase2.CalcTax(100,0);&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;span style="font-size: x-small;"&gt;TestCase3.CalcTax(100,1) with mock db to let GetValue() return 0;&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;.....&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;class Tax {&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.....&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Database db;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Tax(Database d) { db = d;}&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public double CalcTax(int income, int factor)&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if factor == 0 then return 0;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DBConnection c = db.ConnectToDB();&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Int t = c.GetValue();&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (t== 0 ) t=0.1;&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return income/(factor*t);&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: x-small;"&gt;&lt;em&gt; }&lt;/em&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;so, what we learned?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Dev owns quality means better codes.&lt;/li&gt;
&lt;li&gt;Dev owns quality means find bug easily.&lt;/li&gt;
&lt;li&gt;Dev owns quality means find bug early, much earlier. We know the later you find a bug, the more expensive to fix.&lt;/li&gt;
&lt;li&gt;Dev owns quality means reduce the hand off, more efficient and more fast.&lt;/li&gt;
&lt;li&gt;Dev owns quality means test ability. When dev owns quality, dev has to think about how to test it when write code. They can&amp;rsquo;t be tested manually. Test automation is the only way to go, otherwise, he is not going to have time to write new codes any more but doing manual testing all the&lt;br /&gt;time :)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Here,you might think this is TDD. Dev owns quality means use TDD. Well, not exactly.&amp;nbsp; My experience with TDD is more in the ideally world. I don&amp;rsquo;t see any team yet use pure TDD. Most teams use what we called delay TDD. You still write code first, and then write test, then do the refactoring, in the end submit both code and test at the same time. This is more nature way to develop software and achieve the same goal of TDD, meanwhile it&amp;rsquo;s much easy to adopt vs pure TDD which is completely opposite of what you came along. furthermore, dev owns quality can be extended to owning functional testing, i.e not only making sure unit works by unit testing, but also make sure component works by functional testing.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s the cost of dev owning quality? &amp;ldquo;Slowing down?&amp;rdquo; Yes or no. the problem is that we only see the cost of doing unit tests, but not see the cost of not doing it. since dev need to writing a lot of testing which takes time. Of course, she will spend less time writing product codes, which eventually slow down building new features. However, if you see the whole application life cycle, developing feature is just one phase of it. There are maintenance, livesite, and application getting more and more complex. Some industry researches show that it actually shorten application life cycle, because without early testing, a lot of bugs are found at the late stage and even in the customer&amp;rsquo;s environment, this start to eat dev&amp;rsquo;s time and eventually slow down dev. in contrast, dev owns quality makes software component robust at the first place. It&amp;rsquo;s like building a highway v.s. bumpy road, initially car goes faster on bumpy road since it takes time to build highway. But once highway is ready, the car goes much faster than running on bumpy road. &amp;nbsp;This actually leads to another question that is there any situation that unit testing doesnot doing any good? yes, there is. again, take the high way as an example, if you go that road only once or twice, you probably don't want to build a highway. however, if you have to go on the road again and again for the next 5, 10 years, i think you better start to build highway.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;By far, I hope you are with me that dev owns quality is a good thing. But what if dev agree but still don&amp;rsquo;t do it? Many students told me that &amp;ldquo;we all know /agree this in theory, but dev just don&amp;rsquo;t do it for whatever reasons, how can I change it?&amp;rdquo; Here I&amp;rsquo;m going to share with you a few tips you can try.&lt;/p&gt;
&lt;p&gt;First off, there is no silver bullet for it. Dev born to be writing product code, they don&amp;rsquo;t like testing &amp;nbsp;in nature. It is a hard and long effort to make the change. So&amp;nbsp;you got&amp;nbsp;be prepared (hopefully you are not discouraged). On other hand, challenge goes with opportunity. Based on my&amp;nbsp; experience, the change from the state that dev refuse to testing &amp;nbsp;to the state that dev love testing, are not one step task, it usually take a few phases.&lt;/p&gt;
&lt;p&gt;1. awareness. Your first task to convince dev that&amp;nbsp;dev owning quality is good thing or industry trend. If they agree, you are half way to success. if they don't agree, any effort you try to push is useless. so, you got to get them on board first. no exception.&lt;/p&gt;
&lt;p&gt;2. make unit test as part of code complete criteria. Once dev agree it&amp;rsquo;s good thing to unit testing their own codes, you can start to make rules on it. For example, we must have unit tests for every API before we declare code complete. Here is tricky part, at the end of the first iteration, very likely you still don&amp;rsquo;t see any unit test. &amp;nbsp;That&amp;rsquo;s ok, make an exception, but the key thing is let the team knows we are make an EXCEPTION this time. I bet at the beginning of second iteration, dev will start to consider unit test into their overall work. Hopefully at the end of 2&lt;sup&gt;nd&lt;/sup&gt; interation, you will see a little unit test. Again, it's not good progress but it&amp;rsquo;s good sign. Just be patient. Make another EXCEPTION and let the team knows. So on and so forth, after a few iterations, you will suprisely see there are a lot unit test in place.&lt;/p&gt;
&lt;p&gt;You also can try peer pressure or indirect push tips to make the unit test coverage transparent, so the team knows who write unit test, who doesn&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;Reward those devs or teams having better unit tests. measure dev's performance based&amp;nbsp;quality of codes, not number of lines of codes.&amp;nbsp;build a culture that team take pride of their unit testing results.&lt;/p&gt;
&lt;p&gt;Working with dev to improve unit test framework and make unit test as easy as possible. Image you are devs, you take 1 minute to write one line of product code, and takes 2minutes to write its unit tests, now takes 30 minutes to run unit tests. You won&amp;rsquo;t do it either, right? So the most efficient way to push dev to do unit test is to make it as easy as possible.&lt;/p&gt;
&lt;p&gt;3. make it default. After the team is armed with tools/framework for unit testing, you can make it default. For example, block the checkin if no unit test. Showing unit test cc before checkin, etc&amp;hellip;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If dev owns quality, what a tester will do? &amp;nbsp;Will fulltime tester be phased out?&amp;nbsp; i will try to answer these questions in my next blog, also talk about tester's core competency, so, stay tuned....&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10345836" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="software testing" scheme="http://blogs.msdn.com/b/billliu/archive/tags/software+testing/" /></entry><entry><title>提高软件质量实践―― Amazon 篇</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/08/20/amazon.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/08/20/amazon.aspx</id><published>2012-08-20T04:35:18Z</published><updated>2012-08-20T04:35:18Z</updated><content type="html">&lt;p&gt;前几天回国转了一圈，做了两家企业质量管理培训，一次上海测试沙龙，和chinatest两次演讲。收获颇多，以后慢慢分享。回来后发现我的软件质量实践系列文章距离上一次发表已经有很长一段时间了。我想还是先把它写完，再写别的文章吧。那么今天我们看看互联网公司的另外一个大哥大是如何做质量控制的――Amazon.&lt;/p&gt;
&lt;p&gt;Amazon是一个很传奇的公司，它1995年的时候以一个网上书店起家，在短短的十几年里成为全球最大的在线购物公司。更为甚者，他在2005推出的AWS云计算服务更是被业界公认为云计算的鼻祖，也是现在全球最大最成功的云计算服务提供商。我一直坚信成功的产品一定是由成功的质量控制做保障的，采取什么样的测试策略只有两个决定因素。一是企业文化，二是产品特点。在分析Amazon的测试策略之前，我们先看看它的企业文化。&lt;/p&gt;
&lt;p&gt;业界关于amazon企业文化和成功要素有很多，我觉得实际上最为核心的只有一个，就是他们的&amp;ldquo;low margin, large volume&amp;rdquo;理念。就是通过单个商品的低利润和巨大的销售量来最终提高公司利润和公司业务向前发展。工程团队的理念就是要保障企业文化得以顺利实施，所以Amazon的工程团队的理念就是如何保障公司&amp;ldquo;low margin, large volume&amp;rdquo;的企业文化。Amazon工程团队有以下特点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;独立的团队：在Amazon，负责产品功能模块的每个团队相对独立。他们对该模块的所有功能，性能，开发，质量，上线，维护等从头到尾的绝对负责。我们在Google中也可以明显看的这一特征.&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;li&gt;敏捷的团队：为了保障团队的敏捷，Amazon采用&amp;ldquo;2个比萨饼&amp;rdquo;的原则来看控制一个团队的大小。也就是2个比萨饼就可以吃饱（5－7个人）的大小。团队内部和团队之间尽量减少工作的交接，一方面减少因为交接照成的不必要延迟，另一方面避免互相推卸责任。Amazon是最早采用敏捷开发（scrum）的公司之一，他们现在绝大多说产品组都是用scrum，据说有超过400多个CSM.&lt;/li&gt;
&lt;li&gt;&lt;/li&gt;
&lt;li&gt;面向服务的产品体系架构。在01年的时候，Amazon随着它的产品线迅速扩大，业务逻辑越来越复杂，现有的产品体系架构极大地限制了整个公司的高速发展。他们重新设计了基于面向服务的，松耦合体系架构，使得各个模块独立开发，修改和维护。所以Amazon可以在不牺牲质量的同时，快速推出新产品新服务。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;很遗憾的是Amazon很少公开谈论他们的质量管理流程和策略，不过通过有限的资料，还是不难看出他们的质量管理的策略：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;&lt;br /&gt;开发对质量负责：因为每个团队对模块完全负责，并且要做到敏捷。Amazon要求开发对质量负责：从设计，写代码开始一直到代码上线。开发做测试不仅可以尽快地发现bug，而且可以���免过分依赖测试人来提高质量，更为重要的优点是开发在设计是会考虑代码的可测试性 （因为他们自己要测试，肯定想方设法使得测试更为容易些），从而使得模块容易测试，容易维护，松耦合，最终极大提高模块质量。因为开发做了大量的测试，Amazon专职测试工程师也比较稀少（据说对开发的比例是1:7左右）。测试的主要职责是负责复杂用户环境下的测试，以及开发测试工具，流程和基础设施。而且很多产品组把一部分功能测试外包，所以即使Amazon的测试工程师不多，但是整个产品的测试工作却没有一点减少。&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;br /&gt;自动化测试：这里我就不在多说了，和microsoft, google一样，他们开发了大量的测试工具和流程基础设施来提高测试效率。开发专注于写代码和测试，不用在搭建环境，部署，运行测试用例，和反馈上浪费时间。除了测试自动化外，他们也开发了一整套用以产品上线，维护和监控的工具和流程。只有这样，开发才有可能既要写代码，又要对代码质量从头到尾负责。&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;br /&gt;数据驱动的决策流程：和google一样，Amazon全方位监控它的应用服务的运行状态，从每个API调用时间，到用户使用产品的每一步骤。根据对这些数据的分析和挖掘，开发团队决定如何提高产品质量。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;如果大家熟悉Google的软件质量实践应该可以发现，Amazon和google在软件质量控制的理念和实践有非常的相似之处。有所不同的是，google的很多项目以实验性为目的，最初没有任何专职测试。只有等到项目真的被重视后，测试才开始介入。做为互联网产品的两个大哥大，他们的测试方式或许可以代表着互联网产品的测试发展方向吧。下一次我们介绍最后一个公司的测试策略－facebook。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10341515" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="software testing" scheme="http://blogs.msdn.com/b/billliu/archive/tags/software+testing/" /></entry><entry><title>再看云计算是否安全</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/07/06/10327336.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/07/06/10327336.aspx</id><published>2012-07-06T00:51:00Z</published><updated>2012-07-06T00:51:00Z</updated><content type="html">&lt;p&gt;Amazon的AWS云计算服务又宕机了，这是6月份的第二次。和其它的宕机事件一样，又引发了大家对云计算安全性的质疑。其它的云计算服务比如windows azure 或google的gmail服务的宕机也时有发生。 老是出问题好像不太符合云计算的吹捧的高安全性呀。那么云计算的安全性到底如何，做为那些正在准备引入云计算的公司，是否需要需要再考虑考虑呢？下面谈谈我的看法。&lt;/p&gt;
&lt;p&gt;首先要订正的是该事件实际上不属于安全性的范畴而是高可用性的问题。安全性通常是指是否可以访问未授权的资源或数据（当然DoS攻击也是安全性问题），这里所指的是用户部署在云里的服务是否可以一直可用。 所以真正的问题是云计算是否高可用?&lt;/p&gt;
&lt;p&gt;在回答该问题前我们需要分清楚云计算里的两个基本概念：计算服务和存储服务。&lt;/p&gt;
&lt;p&gt;计算服务是指云计算提供商提供给用户的用以进行运算的服务。它通常是以实例单元来衡量的，比如一个虚拟机可以是一个实例单元。用户在购买或使用计算服务时可以是一个或多个实例单元。比如用户的在线购物应用程序，一个实例单元可以扛得住1000用户的访问量的话，如果你通常会有10000个用户同时访问的话，你至少需要10个运算实例。如果在高峰值时有50000个用户同时访问，你需要购买50个运算实例。而在低峰期是如果只有2000个用户访问的话，你可以只购买2个运算实例就可以了。所以你可以方便灵活地更具用户访问量来调整购买实例的数据量，这样既不会浪费，也不会不足。这就是我们所说的云计算的最大优点之一：弹性伸缩，按需使用和按使用付费。但是，要做到这一点，每个运算实例必须是"无状态"的，也就是每个运算实例完全相同，不可以在运算实例的本地机器上保存任何状态数据。原因很简单：如果你在本地保存数据的话，只有你自己实例能够使用。在前面10000个用户访问量的例子中，在增加再多的运算实例也没有帮助，因为只有你有数据，别的再多机器也帮不上忙。&lt;/p&gt;
&lt;p&gt;但是在实际的应用程序中我们又必须处理和保存数据。所以为了运算实例"无状态"而又可用保存数据，云计算提供商必须提供第二个服务：存储服务。&lt;/p&gt;
&lt;p&gt;存储服务很简单就是给用户保存数据用的。但是数据是用户业务的核心中的核心，绝不可以出现任何差错。所以存储服务必须使用足够的措施来保证数据的万无一失。绝大多数的公司都采用两中方式：一是：把用户数据划分成块，每一块是一个存储单元。每个存储单元分多次保存在多个服务器上。这有两个好处：一是如果一个服务器宕机了，其它服务器上的数据还可用；另一个是负载均衡以提高读数据的效率。这些服务器都在同一个数据中心，所以使用同步复制，即使把同一个数据块写多次也不会影响写数据的效率。但是把同一个数据的多个拷贝存放在同一个数据中心无法应付大的灾难，比如数据中心失火，地震或城市断电等。所以大部分公司把数据再一次复制保存到另外一个城市的数据中心里（两个数据中心最少相距150公里）。如果一个数据中心瘫痪，可以把用户请求切换到另外一个数据中心。因为两个数据中心的数据复制较慢，所以通常采用异步复制的方式，每隔10分钟复制一次。另外一点是第一种同步复制是默认的，用户不用做任何配置，也是免费的；但是第二个异步复制需要用户提出，而且可能有额外的费用。&lt;/p&gt;
&lt;p&gt;所以有了存储服务后，用户就可以把数据或状态保存到存储服务理，而实现运算实例的无状态了。可以随时增加或减少实例数量，一个实例宕机也没有问题，还有其它实例在处理。实际上在数据中心里机器宕机，网络断掉，硬盘坏掉每天都在发生，但是用户感觉不到。如果用户把自己的应用服务同时部署到多个数据中心的话，即使一个整个数据中心宕掉的话，用户的访问请求可以快速切换到另外一个数据中心，用户也不会感觉到任何问题。这就是运算服务的高可用性：服务器宕掉了没有问题，整个数据中心宕掉了，同样没有问题。但是我们可以看的要做到这一点，用户必须做两件事情：1.你必须有最少两个运算实例，道理很简单：如果只有一个，它宕掉的话没有其它实例，当然做不到高可用性。2.你的应用程序必须在多个数据中心部署，一样的道理。最少两个才可以做到双保险。&lt;/p&gt;
&lt;p&gt;我们再来看看亚马逊的本次宕机事件。因为当地暴风雨导致数据中心断电，在切换到备用电源后，备用电源出现故障。所以导致整个数据中心宕掉了。在切换到其它数据中心的时候有发现切换程序出现故障，导致无法切换，所以最终导致用户应用服务不可用。另外它都只是计算服务宕掉了，并没有影响数据服务，或则数据没有丢失。等到计算服务回复后，系统恢复正常。所以计算服务宕机很正常，如果数据丢失麻烦就大了。其实这一次恶劣天气照成数据中心断电本来可以体现亚马逊云计算高可用性的一个经典案例，但是很可惜的是它的切换程序出了问题，反而成了失败案例。&lt;/p&gt;
&lt;p&gt;所以我们可以看出在保证应用程序的高可用性和数据的安全性上，没有一家单个公司可以做到像亚马逊，微软或其它云计算提供商那样的完备，根本不是一个级别上的比较。我们对亚马逊宕机反应强烈只不过是我们对云计算有着不切实际的期望（100％高可用性）。殊不知我们对自己公司办公室的服务器经常宕机习以为常了。&amp;nbsp;当然云计算提供商在保证高可用上还要继续努力，但是它也不应该是质疑或反对云计算的理由。另外一点就是要高可用性不是与生俱来的，而是要求用户必须做很好的设计，充分利用云计算提供的机制，而不是把应用程序扔到云里面就万事大吉了。一个最简单的道理：不要把所有鸡蛋放在一个篮子里。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10327336" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="云计算" scheme="http://blogs.msdn.com/b/billliu/archive/tags/_914EA18B977B_/" /></entry><entry><title>敏捷，是灵丹妙药还是又一个忽悠？</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/06/21/10322470.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/06/21/10322470.aspx</id><published>2012-06-21T05:42:00Z</published><updated>2012-06-21T05:42:00Z</updated><content type="html">&lt;p&gt;敏捷开发和敏捷测试这两年自从从国外引进后，在国内很火，很多人都在谈论。无论是项目延期，失败，质量低下等等，你总能听到分析的原因是：&amp;ldquo;看看，你没有敏捷了吧&amp;rdquo;。所以一下子敏捷成了包治百病的灵丹妙药。很多项目组公司开始学习敏捷，采用敏捷，转向敏捷。但是遗憾的是很多人尝试过后发现以前的问题并没有被敏捷所解决掉，反而带来了很多新的问题，于是也有人就得出结论：敏捷又是一个大忽悠。读了很多网上关于敏捷的辩论，我想起一个故事：&lt;/p&gt;
&lt;p&gt;话说清朝的时候慈禧太后听说西方国家有个新的交通工具，汽车，它坐在舒服跑的很快。于是就叫人买了一辆回来。但是用的时候没有人会开，于是不得不把汽车用几根柱子绑起来做成了轿子，让几个人抬着。因为汽车太沉，几个轿夫步履蹒跚，走不了几步就得歇歇。结果以前半个时辰的路走了好几个时辰。而且到了后因为门很窄，汽车做的轿子过不去，她也不得不老远就下来自己走一段。慈禧太后很不高兴就得出结论：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;汽车前期投入大，维护成本高。&lt;/li&gt;
&lt;li&gt;没有轿子走的快。&lt;/li&gt;
&lt;li&gt;很多地方汽车都不适用。&lt;/li&gt;
&lt;li&gt;汽车是个大忽悠的东西，根本不管用。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;那么我们现在对敏捷的认识是不是和慈禧对汽车的认识类似呢？是因为我们不会用敏捷呢，还是因为敏捷就是个忽悠？&lt;/p&gt;
&lt;p&gt;在国外通常一个概念出来之前已经有很多年的实践积累，然后为了大家交流方便或者提高普及度给其一个名字。所以是先有实践，再有概念。但是在国内正好相反，我们先把国外&amp;ldquo;先进&amp;ldquo;的概念引进来了而把产生概念的多年实践忽略掉了。但是概念又太虚不能当饭吃，最终还是需要具体东西和具体做法。所以不得不根据概念来设计出各种各样的做法来。这些做法听起来不错，非常符合概念，但是在项目中一使用就不灵了，旧的问题没有解决，新的问题一大堆。最终得出汽车是个大忽悠的结论。&lt;/p&gt;
&lt;p&gt;敏捷和云计算是两个非常典型的例子。很多人为了敏捷，文档不要了，计划不要了，测试用例也不要了，认为几个人站在走廊里沟通沟通就把一切都搞定了，因为敏捷了嘛。但是问题并没有因为&amp;ldquo;敏捷&amp;ldquo;了而被解决掉，于是乎得出敏捷是个忽悠的结论。云计算也一样，很多人认为云计算就是数据中心，所以大家大兴土木建立数据中心。但是建完数据中心以后呢？没啥用处呀。那大家都在吹捧云计算，不就是个大忽悠吗。 殊不知，人家是因为业务需要很多年了已有数据中心，为了提高数据中心的使用率，开始对公众开放资源，所以才有了云计算。&lt;/p&gt;
&lt;p&gt;先有概念再造实践的做法违背了事物发展规律，不仅解决不了现有问题，而且带来新的问题。敏捷是个好东西，在特定情况下。我们需要搞明白的是它要解决什么问题的？它是如何解决的。而不要在乎它叫什么名字或则防止生搬硬套。还有越是先进的东西对人和基础设施的要求越高。比如飞机再好，没有飞行员或则没有机场也没有用。高铁跑的越快对铁道的要求越高。&lt;/p&gt;
&lt;p&gt;软件测试也是一样，做质量控制不是为了赶时髦。如果你的项目只做3个月就彻底结束了，而且就3－5个人，不会有人离开也不会有人进来，也不需要和其它任何项目打交道，或则你的产品在早期实验阶段，你可以不要文档，不要计划，不要记录bug，完全靠口头交流。否则的话：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;不能没有文档:&amp;nbsp; 但是要减少不必要的文档，避免过于详细的文档，使用易于更新和维护的动态文档。&lt;/li&gt;
&lt;/ol&gt;&lt;ol&gt;
&lt;li&gt;不能没有计划: 距离现在越远计划越模糊，但是距离现在越近计划越详细。&lt;/li&gt;
&lt;/ol&gt;&lt;ol&gt;
&lt;li&gt;不能没有纪律:&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;与其在琢磨如何敏捷测试，不如一步一步把自动化做好，把持续集成做起来，创建更多的测试工具以提高测试效率，把质量反馈系统做起来，把dev提交代码前的质量检查做起来，把在产品中测试做起来， 把测试工程师的素质提高上去，。。。。&lt;/p&gt;
&lt;p&gt;等到这些都建立起来了后，你发现自己其实已经很敏捷了。&lt;/p&gt;
&lt;p&gt;---------------&lt;/p&gt;
&lt;p&gt;关注我：新浪微博：@billliu_seattle &lt;a href="http://www.weibo.com/windowsazure"&gt;http://www.weibo.com/windowsazure&lt;/a&gt; 或twitter: @billliu_seattle&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10322470" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="software testing" scheme="http://blogs.msdn.com/b/billliu/archive/tags/software+testing/" /></entry><entry><title>google testing 的光环正在褪去？</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/06/17/google-testing.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/06/17/google-testing.aspx</id><published>2012-06-17T04:49:00Z</published><updated>2012-06-17T04:49:00Z</updated><content type="html">&lt;p&gt;最近因为在写一个各个公司质量控制实践对比的系列文章，包括微软，google，amzon和facebook，所以对google的测试越加了解。google是互联网公司的领导者，它的产品质量控制也成为其它公司的学习的楷模。James，前google测试总监，在他的新书《how google test software》中号称google的测试实践将会是其它互联网公司实施质量控制的教科书。但是随着对google测试的了解加深，与更多的熟悉或者工作在google的测试工程师的深入交谈，发现google真正的测试实践好像不太完全象外面宣传的那样耀眼。&lt;/p&gt;
&lt;p&gt;昨天请了一个在facebook的做网站性能测试的大牛来给我们分享facebook做性能测试的经验。她在google做了5年的测试在2年前跳到facebook。在提到其它公司在推崇google的测试实践时，她把google的测试狠狠抨击了一番。她说google的广告做的很好，很多google演讲的数据，比如每天有多少个build；一个build有多么快速，测试运行有多快速，等等数据有过分夸张。可能某一个组的某些测试做的还可以，但绝不是代表整个公司，甚至不能代表大部分组，至少她在google工作的5年里没有看见过。而且很多内部工具真正的做法，实际效果都不像外面传说的那样神奇。&lt;/p&gt;
&lt;p&gt;James 在3月份离开google回到微软。虽然他在博客中强调他离开的原因是不同意google的产品策略以及公司文化的变化，但是我觉得他的根本原因还是他对测试的的看法和公司高层有不小的分歧。而且从他最近写的有关软件后期测试的文章可以很明显地感觉到。James 和其它两个工程师合写新书。书还没有出版，两个作者就先后离开了google，另外一个早就转成了开发。即使在他的新书中，James在最后展望google的测试的章节中，他就承认因为google的测试工程师是用租借的方式分配到产品组中，这使得测试工程师对产品没有归属感。这很令人担忧。很典型的例子：if you ask a dev what she is doing in google, she will say i'm working for chrome, search, g+, etc.. whatever component/product she is working on. however, if you ask a tester what she is doing in google, she will say i'm a tester.&lt;/p&gt;
&lt;p&gt;前两天和两个在google测试的工程师聊天，他们也是一直在摇头。而且承认搞测试还是在微软（这两个工程师都在微软工作过）。&lt;/p&gt;
&lt;p&gt;google测试实践真的值得推崇吗？&lt;/p&gt;
&lt;p&gt;是不是因为google成功了我们就默认为他的所有做法都值得追随？&lt;/p&gt;
&lt;p&gt;那么我们到底该从google学习什么样的成功经验呢？&lt;/p&gt;
&lt;p&gt;我想把这些问题留给读者自己去琢磨和思考。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;----------------------------------------&lt;/p&gt;
&lt;p&gt;关注我：新浪微博：@billliu_seattle &lt;a href="http://www.weibo.com/windowsazure"&gt;http://www.weibo.com/windowsazure&lt;/a&gt; 或twitter: @billliu_seattle&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10321068" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="software testing" scheme="http://blogs.msdn.com/b/billliu/archive/tags/software+testing/" /></entry><entry><title>提高软件质量实践――google 篇</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/06/07/google.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/06/07/google.aspx</id><published>2012-06-07T06:46:24Z</published><updated>2012-06-07T06:46:24Z</updated><content type="html">&lt;p&gt;很多人应该都看过James whittaker的博客或新书 《how google test software》，在这里我不想重复他的内容，而是从另外一个角度来分析对比google是如何保障它的产品质量的。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;首先申明的是本人并没有在google工作过所以没有第一手的经验，仅以一个旁观者的身份来分析google的质量控制实践。主要信息来源于google测试博客，在西雅图google工作的朋友聊天和项目上合作，以及James的新书&amp;lt;&amp;lt;how google tests software&amp;gt;&amp;gt;。不过旁观者有旁观的优势，可以看见整个森林；相比较许多在大公司工作的工程师往往专注于一个产品或者一个团队，只看见了一颗树木J。不管如何，个人观点仅供参考。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;我们前面在微软的质量控制实践中谈到，因为微软大部分的产品还是以桌面型产品为主，比如windows, office,sql server等等。桌面型产品的最大特定就是产品召回或发布热修复的成本太大，而且运行很多关键业务，这就迫使微软必须在产品发布之前投入大量人力物力来充分测试产品用以保障产品的高质量。与微软不同的是，google采用不同的策略来保证软件质量。在理解分析google的质量策略之前，我们必须了解google的采取该策略的根源：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Google质量文化：google起源于校园。在有限的资金下，那时候创始人只能使用廉价的机器，把多个廉价的机器放在一起来提高处理能力。这些廉价的机器最大的问题是经常死机或报废，所以google在起始阶段就必须有很强的容错能力。也就是说在系统在部分机器死机或报废的情况下仍然可以提供服务。或者说，系统部分可以出错但是整个系统不可以宕机 （Graceful Degradation）。Google这个从一开始因为被迫置入的高容错能力反而成就了现在他们运行在数据中心上的服务的巨大优势。我们知道通常硬件的出错概率大概在万分之一，如果有一万台机器，其中一台出错概率就达到百分之百。在现在的数据中心里少则几万台，多者几十万台的机器。所以产品的容错能力已经不是可有可无，而是必须有的功能。所以google信奉的原则是单个模块可以出错可以有bug，它通过系统强大的容错能力来保障系统的整体高质量。&lt;/li&gt;
&lt;li&gt;互联网产品：google是互联网公司成功的代表。互联网产品的最大特点就是&amp;ldquo;快&amp;rdquo;：产品定义快，开发快，反馈快，死掉的也快。所以为了有效利用有限的测试资源，google信奉的另外一个原则是：build the right it before you build it right.也就就是说只有确认了产品的确是用户需要的产品(build the right it)之后才开始提高它的质量(build it right)。道理很简单如果未知产品是否正确的情况下，没有必要浪费资源来提高它的质量。所以google的大部分产品测试人员介入较晚，开发人员不得不自己先测试以保障基本质量。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;在理解了goolge对产品质量认识这两个根本出发点后，就不难理解google采用什么样的测试策略了：&lt;/p&gt;
&lt;p&gt;1. Dev owns quality&lt;/p&gt;
&lt;p&gt;Google认为：谁写的的代码谁负责，谁开发的模块谁负责质量。所以开发在写代码的同时也要花很多时间测试，主要是单元测试和模块测试。Google坚信软件质量是先天就创建出来的，而不是通过后天测试测出来的。让开发做测试对产品质量负责不是件容易的事情，google通过主要三个途径：一是减少测试人员数量，所以开发不得不做测试；而是通过一些活动比如test certificate program来正面影响开发做测试；最重要的第三点是通过建立强大的完善的基础设施，使得开发很容易地写测试自动化很容易地运行测试。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2. Tester is to enable developer to test effectively&lt;/p&gt;
&lt;p&gt;这个是对传统意义上的测试人员的职责非常大的改变。传统意义上的测试人员的主要职责是寻找产品中的bug。既然google要求开发对质量负责，当然就不太需要传统意义上的测试人员了。所以google中的测试更多时间是在开发测试自动化，开发测试工具，开发基础设施。相对花很少的时间做真正意义上的测试了。所以后来干脆把测试部门从原来的&amp;ldquo;Test Service&amp;rdquo;改名子为&amp;ldquo;engineering productivity&amp;rdquo;。测试的主要职责是让开发更为容易地做测试。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;但是最近两年，随着它的产品的日趋成熟和越来越复杂，google开始加强产品的后期测试。主要原因是虽然开发可以做很多单元和模块测试来保障模块的质量，但是很多bug是在和其它模块集成的时候才被发现。所以google把测试工程师分成两种：一种是和开发一起负责开发的，最要做单元测试，测试工具等。另外一种是面向用户的测试工程师，主要做面向用户的集成场景测试。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;3.Continuous Integration&lt;/p&gt;
&lt;p&gt;这个就不用多介绍了，搞互联网或基于服务的产品的项目组，如果不使用持续集成的话有点太out了。Google的持续集成是行业的领先者，一方面有强大的测试自动化和完善的基础设施做为保障，使得开发测试工程师不用在如何部署，如何运行，如何分析结果等等上浪费时间，而是专注于开发和测试自动化。代码提交后会有成千上万个测试用例自动运行，并且很快返回结果以供进一步分析之用。另一方面，google继续优化现有的工具和基础设施来进一步提过持续集成的效率。比如在做持续集成中最为头疼的一个问题是运行那些测试用例？运行多了当然会延长运行时间从而降低了效率，运行少了又有漏测的风险。Google开发了一套测试用例分析工具用以分析代码和测试用例的依赖关系。如果修改了某行代码后，该工具决定哪些测试用例必须运行，也就是说不多不少。微软也有类似的工具在帮助测试人员决定运行测试用例的优先权，但是个人感觉效果不太好。所以我也对google的工具到底效果如何应用情况很感兴趣。&lt;/p&gt;
&lt;p&gt;另外一点就是持续集成是以自动化做为基本保障的。测试自动化不是万能的，但是没有测试自动化是万万不能的。注意的是测试自动化不仅仅解放了人，也不仅仅是为了回归，更为重要的一点是逼迫开发在设计的时候就考虑到如何自动测试该模块从而大大提高模块的可测试性（我们知道这是提高软件质量的一个重要指标）。当然除了测试自动化外，google开发了许许多多的工具和平台来大大提高测试效率。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;4. Measure everything&lt;/p&gt;
&lt;p&gt;客观上说以上几点我都觉得没什么特殊之处，但是下面这个绝对让我受益匪浅：measure everything。从最底层的硬件驱动器，到操作系统的CPU, memory,&amp;nbsp; disk IO, 再到每个API的调用， 最后到最高层的用户体验，Google监控和衡量所有的这些活动。然后对监控和衡量的数据进行数据挖掘和分析，从而对整个系统的运行情况了如指掌。一方面，如果有bug的话，它可以在最短的时间内发现并根据监控的数据很快找到bug的根源加以修复；另一方面根据详细的监控数据清楚地表明哪些地方需要改进，尤其是在系统性能方面；再一方面就是了解用户的使用情况和规律从而为产品功能的改进提供精确的数据和预测。Google认为： If you can&amp;rsquo;t measure your product/component, don&amp;rsquo;t build it。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;小结，google是互联网公司成功的代表，他在互联网产品上的质量控制实践和经验对于广大的互联网公司有值得借鉴意义。在产品发布速度和产品发布质量的权衡和取舍中，google选择发布速度。在保障基本产品质量的前提下，用最快的速度把产品推到市场中，然后通过丰富的反馈渠道和工具再不断演变。这样即控制了用户又保障了质量，而且也做到了对没有用户的产品：fail fast, fail cheap。除了google之外，在西雅图的另外一家公司也是互联网产品的大哥大，特别是在在线销售和云计算应用服务类型的产品。所以下一次和大家探讨：提高软件质量实践――Amazon 篇。&lt;/p&gt;
&lt;p&gt;----------------------------------------&lt;/p&gt;
&lt;p&gt;关注我：新浪微博：@billliu_seattle &lt;a href="http://www.weibo.com/windowsazure"&gt;http://www.weibo.com/windowsazure&lt;/a&gt; 或twitter: @billliu_seattle&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10316524" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="software testing" scheme="http://blogs.msdn.com/b/billliu/archive/tags/software+testing/" /></entry><entry><title>探索性测试揭秘</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/05/26/10310656.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/05/26/10310656.aspx</id><published>2012-05-26T06:24:00Z</published><updated>2012-05-26T06:24:00Z</updated><content type="html">&lt;p&gt;最近看了不少有关探索性测试的讨论和观点，老实说越看越糊涂。所以忍不住吐槽一下，在这里和大家讨论一下探索性测试。希望对于想学习和尝试探索性测试的朋友有所帮助澄清，或者是更加糊涂，^_^。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;探索性测试有很多很多的定义：&lt;/p&gt;
&lt;p&gt;百度百科的定义：&amp;ldquo;同时设计测试和执行测试&amp;rdquo;。 嗯。。什么意思？&lt;/p&gt;
&lt;p&gt;Cem 老人家的正式定义：&amp;ldquo;a style of software testing that emphasizes the personal freedom and responsibility of the individual tester to continually optimize the quality of his/her work by treating test-related learning, test design, test execution, and test result interpretation as mutually supportive activities that run in parallel throughout the project&amp;rdquo;。啊。。 糊涂了。。。&lt;/p&gt;
&lt;p&gt;有人说：&amp;ldquo;手工测试就是探索性测试&amp;rdquo;。&amp;nbsp; 更糊涂了。。。&lt;/p&gt;
&lt;p&gt;又有人说：&amp;ldquo;探索性测试就是一遍探索一遍测试&amp;rdquo;。 彻底糊涂了。。。。&lt;/p&gt;
&lt;p&gt;。。。。。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;那么探索性测试到底是啥玩意啊？&lt;/p&gt;
&lt;p&gt;我们先来看一个例子吧。很多人都玩过猜数字的游戏吧。我心里想一个数字，你来猜。你可以问任何问题，我回答&amp;ldquo;是&amp;rdquo;还是&amp;ldquo;不是&amp;rdquo;。然后你通过不断问问题和我的回答来最终猜到我心想的数字。在猜对的情况下问的问题越少得分越高。比如，我心里想了一个数字。你可以问&amp;ldquo;大于零？&amp;rdquo;，我说&amp;ldquo;是&amp;rdquo;。你现在知道是正数了，你然后问&amp;ldquo;小于100？&amp;rdquo;，我说&amp;ldquo;是&amp;rdquo;。你现在知道是小于100的正数，你然后问&amp;ldquo;小于50？&amp;rdquo;，我说&amp;ldquo;不是&amp;rdquo;。你现在知道是介于50和100间的数。你继续再问几次后因该就能猜对了。&lt;/p&gt;
&lt;p&gt;在这个简单的游戏中有两个策略至关重要：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;你要根据前面问题的答案来分析和设计下一个问题。第一个问题可能不着边，但是第二个问题会让你跟接近你想要的答案。第三个会更加靠近，以此类推。&lt;/li&gt;
&lt;li&gt;仅仅根据前面问题的答案来设计下一个问题可以最终帮你猜对数字，但是要想用最少的问题来猜对数字不仅要根据前面问题的答案，而且需要对问题本身其它知识加以综合运用使用其它策略和技术。比如在知道是小于100的正数后，你可以使用binary search，最多猜6次就可以猜对；如果你不知道binary search，你可以猜是否小于90？小于80？小于70？&amp;hellip; 猜上十几次也可以猜对；或者猜是否小于99？小于98？小于97？&amp;hellip; 猜上几十次也可以猜对。所以采用不同策略直接决定你猜对的速度。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所以两个关键因素：前面问题的答案＋有效的策略。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;探索性测试和猜数字游戏完全一样。在这里要猜的数字就是你要找的bug。你问的问题就是你做的测试，每个问题的答案就是你测试过程中产品的输出。第一轮你只有一个非常模糊的范围比如测试某个模块的某个功能。在你测试的时候通过观察产品的反应和输出来判断分析下一步做什么会发现bug。当然实际测试中不会像猜数字那样直接和简单。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;下面我们来看一下一个真实的测试例子。有一次我在测试一个用户界面的录入页面。用户可以输入比如姓名，年龄，等等很多信息，最后系统根据输入的内容处理保存到数据库中。当然我对每一个输入框都会尝试不同的数据比如空值，很长的字符串，空格等等，系统都没有问题。但是我注意到每次保存的时候系统都会生成一个本地文件，该文件的名字是其中一个输入框的我的输入。该输入框的唯一限制就是不可以为空不可以超过255个字符。我想到文件名字中不可以有斜杠&amp;ldquo;\&amp;rdquo;，于是我就在该输入框中如入&amp;ldquo;ab\cd&amp;rdquo;，它通过了输入校验，但是保存的时候系统就崩溃了。这就是探索性测试一个非常典型的例子，通过观察分析上一次测试的产品反应和输出来判断系统会有问题的地方，然后设计调整步骤和测试数据反复尝试直到完全验证模块没有问题或找到bug.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;探索性测试和手工测试的区别：手工测试通常是指完全按照预先设计好的步骤一步一步人工测试直到验证了所要验证的功能。如果结果和预期结果一致，则验证通过；如果不一致，则是bug.可以看出手工测试过程单调没有思考没有变通。在上面的猜数字的游戏中你明明已经知道是正数，你还在按照游戏开始前设计的步骤问大于－100？ 大于－90？。。。。当然现实生活中没有这样的傻子，在你&amp;ldquo;手工&amp;rdquo;测试的时候你或多或少已经使用&amp;ldquo;探索性&amp;rdquo;了，只不过你没有意识到罢了。所以很多人误认为探索性测试是个时髦新测试技术，研究了半天又不知道到底新在那里和自己一致做的有什么不同。或者恍然大悟原来自己已经探索了很多年了。但是探索性测试有效率高和效率低之分，所以有人干脆就把效率高ET的才叫ET, 效率低的ET叫手工测试。这也是让人糊涂的原因之一吧。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;测试自动化就是把手工测试的每个步骤有测试自动化工具来完成。好处是不用人做了，缺点是测试过程中仍然没有思考没有变通。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;Ad-hoc测试（随机测试）：没有预先设计好的步骤，也没有明确目标，也没有策略。在上面猜数字的游戏中你明明知道是正数，你还在东一榔头，西一棒槌的乱猜等于100？等于－100？等于0？。。。当然也有可能被你一不小心蒙对了。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;探索性测试和测试自动化各有各的优缺点。至于什么时候开始测试自动化，什么时候开始ET，先测试自动化后ET,还是先ET后测试自动化需要看项目产品具体情况了。没有绝对对错，以尽早发现bug,发现更多的的bug为宗旨。另外既然ET和测试自动化的各自优缺点，微软有些组最近两年在尝试&amp;ldquo;探索性测试自动化&amp;rdquo;的方式来把探索性测试和测试自动化相结合，充分发挥各自的优点。看到这里你可能要恨我了，我刚学会测试自动化，你又提倡ET了；我刚搞清楚ET，你又开始提倡探索性测试自动化了。。。 呵呵，人类发展过程就是通过社会分工，扬长避短。专注于做自己擅长的事情，把自己不擅长做的事情交给擅长的人去做。社会发展是如此，云计算是如此，测试也是如此。有人说过：&amp;ldquo;The computer is incredibly fast, accurate, and stupid （test automation）. Man is unbelievably slow, inaccurate, and brilliant (exploratory test). The marriage of the two is a force&amp;nbsp; beyond calculation。&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;其实我们可以看到探索性测试入门容易或者你已经在做了多年了，难得是有效地探索性测试，或者做效率高的ET（否则被别人不屑为手工测试了J）。那么如何根据前面的测试结果来分析和思考，如何才能敏锐地嗅觉到通向bug的种种线索？当然有多种方式来训练自己这方面的能力。还有如何衡量考核ET的效率，投入和产出比率？欲知详情，请听下回分解。。。。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;或者把这篇文章在微博上转发5次，我会发私信告诉你，哈哈。。。。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;----------------------------------------&lt;/p&gt;
&lt;p&gt;关注我：新浪微博：@billliu_seattle &lt;a href="http://www.weibo.com/windowsazure"&gt;http://www.weibo.com/windowsazure&lt;/a&gt; 或twitter: @billliu_seattle&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10310656" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="software testing" scheme="http://blogs.msdn.com/b/billliu/archive/tags/software+testing/" /></entry><entry><title>对测试的要求太高？</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/05/17/10306143.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/05/17/10306143.aspx</id><published>2012-05-17T06:23:00Z</published><updated>2012-05-17T06:23:00Z</updated><content type="html">&lt;p&gt;微软的软件质量控制实践三篇写完了，收到很多评论。不可能一一回答，所以在这里我挑几个评论最多的和有代表性的，和大家再多讨论一下。希望有所帮助。&lt;/p&gt;
&lt;p style="margin-right: 0px;"&gt;1. 对测试的要求太高了&lt;/p&gt;
&lt;p&gt;在国内培训的时候经常遇到的一个说法：&amp;ldquo;（比如测试自动化，工具，流程）的确好处很多，但是它对测试的要求太高了&amp;rdquo;。刚开始的时候我很惊讶，第一次听到对测试要求太高的说法，后来听多了才慢慢意识到这才是问题所在。如果你认为国内的测试比国外落后N年的话，我觉得&amp;ldquo;对测试的要求太高了&amp;ldquo;的观念就是导致这个落后的根本原因。我一直在观察和对比国内外测试的区别，当然有技术上的，工具上的，流程上的区别等等，但是这些差别都只是表象，根本的差别是观念上的差别，也就是测试在研发中的真正角色。这个不是找到多少个bug的问题，也不是采用什么测试方法的问题，而是是否把测试做为支撑研发两条腿中的一条腿的问题。测试是一个专门的职业，和开发一样有不同级别。初级人员解决简单的事情，高级人员必须负责解决复杂，高难度的事情。这样才能形成一个完善的测试人员职业发展体系。很多测试经理一直很困惑说我们也在加大在测试上的投资，参加很多技术、流程、管理培训，但是效果都不好。原因就是我们不能总是希望通过学习一个技术，或一个工具来解决观念上的问题，当然没有效果。也容易跟风，刚学会手工测试，又要测试自动化了；刚学会测试自动化；又要ET了。刚学会ET，又要敏捷了。没有观念就没有主见。所以改变观念才是提高软件质量的根本途径。&lt;/p&gt;
&lt;p&gt;那么如何改变观念呢？我也不知道。公司老板不愿改变呢？我也没有办法。但是重要的是你知道问题所在了，这就是解决了最大的难题。如果自己都觉得测试没有难度，没有前途或者对测试要求太高了的话，如何指望得了别人？所以我们搞测试的人的一个重要职责就是：把这个观念灌输给其他人，把测试的门槛提高，对测试的要求没用很高只有更高，其它问题也都解决了。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;2. Dev不愿意修改bug.&lt;/p&gt;
&lt;p&gt;这是一个很多测试抱怨的问题：自己辛辛苦苦找到一个bug，开发却认为不是bug。或者更为令人气愤的是开发在没有沟通之前直接resolved as &amp;ldquo;by design&amp;rdquo; or &amp;ldquo;not repro&amp;rdquo;。这个情况通常在质量控制成熟度级别（1级或2级）较低的组出现较多。根本上解决的办法是提高整个组的成熟度级别，当然需要在很多方面加以提高，这个问题就随之而去了。可以使用以下几个策略：&lt;/p&gt;
&lt;p&gt;首先这里牵涉到两个问题：一个是resolve as &amp;ldquo;not repro&amp;rdquo;的问题。很多时候dev resolve as &amp;lsquo;not repro&amp;rsquo;是因为bug本身不清楚没有足够的信息来判断或进一步investigate（当然他应该和你确认一下先）。所以测试在报bug是一定要记录足够信息。基本原则是当别人在看该bug是否有足够的信息来判断该bug是怎么回事或进一步investigate。我总结过一个好的bug描述应该是Concise,Accurate, Searchable, Entirety, 也就是 CASE 原则。可能你会觉得这需要太多的时间才能报一个bug了。的确是，但是总比你花了两天找到一个bug，花了10秒钟就把bug写完了，结果过两天dev resolve 成not repro强吧。另外就是自动报bug的工具，还有就是创建bug模板等都可以减少报bug的时间。&lt;/p&gt;
&lt;p&gt;其次是&amp;rsquo;by design&amp;rsquo;的问题。很多时候测试不服气认为就是bug，但是开发不同意修改。我想借用一句话来说明我的观点：a good idea is not really &amp;nbsp;good &amp;nbsp;until it is accepted. 也就是说如果你不可以说服别人接受你的主意，再好的主意也没有用。同样的道理你认为的bug，如果不能说服别人，它也不是一个bug。或者bug只有在被修复时才是真正的bug。如果dev/test有分歧的话，通常PM负责一个功能，应该有PM做最后决定；如果没有PM的话，通常有整个team来决定。当然如果你非常肯定，可以继续找更多的理由来支持你的观点。但是最终如果还是不能说服别人的话，还是要服从team的决定，虽然我们常说真理往往掌握在少数人的手里，但是绝大多数时候都是少数人考虑不周。另外一点就是我们通常很少在是不是bug上有分歧，而是在什么时候修复上有分歧。这是另外一个话题了，需要考虑很多其它非技术因素了。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;3. 如何做到自动报bug,并把相关的信息放到bug 里面.&lt;/p&gt;
&lt;p&gt;我在comments里已经回答过了，就把它拷贝一下吧以是完整：我前面提到微软有很多工具来提高测试人员的工作效率，也就是说把时间花在需要专注的地方而不是在其他繁琐的地方浪费时间。其中一个好的实践就是自动报bug。其实整个过程比较直接：首先用来管理bug的工具应该会有API接口，所以可以使用工具来自动报bug。其次是添加分析处理工具，测试的出错信息比较容易获取，比如测试用例出错了，或者抛异常或者返回错误结果，可以容易地把异常信息或错误信息放到bug里面；分析产品的日志找到错误点有写难度，需要和dev共同努力把测试日志和产品日志通过某些属性（时间戳或操作id）关联起来。或者简单地把相关日志、windows event log,等拷贝到network share，在bug中指向该路径即可。还有对于UI测试，如果测试错误，一定要把当时的屏幕截图抓下来放到bug中去。还是那句话，专注于应该要专注的地方而不是把时间浪费在其它步骤上了，测试用例出错，不应该花太多时间去报bug （最多2分钟）。同样道理有了bug后dev可以直接去investigate，而不是花时间去找日志在那里？那里出错了？等等。有条件的产品组还可以进一步提高，比如工具自动报bug的时候可以到到数据库里根据异常或错误信息查找一遍看一看以前有没有类似的bug，或者做BI，这些信息对于将来的分析和决策非常有帮助，而且也可以帮助预防bug。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;----------------------------------------&lt;/p&gt;
&lt;p&gt;关注我：新浪微博：@billliu_seattle &lt;a href="http://www.weibo.com/windowsazure"&gt;http://www.weibo.com/windowsazure&lt;/a&gt; 或twitter: @billliu_seattle&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10306143" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="software testing" scheme="http://blogs.msdn.com/b/billliu/archive/tags/software+testing/" /></entry><entry><title>软件质量控制实践――Microsoft 篇 (3)</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/05/11/microsoft-3.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/05/11/microsoft-3.aspx</id><published>2012-05-11T04:58:00Z</published><updated>2012-05-11T04:58:00Z</updated><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol&gt;7. invest on test engineer&amp;rsquo;s career&lt;/ol&gt;
&lt;p&gt;无论产品使用何种方式保障质量，人总是最核心最关键的因素。提高软件质量有无数种方式和无数个因素，如果非要说一个最最重要的方式，那就是激发测试工程师的工作热情。You can only achieve average by working hard, but passion is the one driving to excellence. 为了最大化激发测试工程师的潜能，微软为测试工程师设计一整套完善的职业发展计划。测试工程师主要有两个职业发展路线。一个是Individual Contributor (IC): 不管人，管技术。另外一个是Manager: 偏重于管人和项目。这两个路线没有好坏之分，因人而异。两个路线都是以技术能力为核心，也是加薪升职的最主要考虑因素。经理未必比个人挣钱更多，&amp;ldquo;Become a manager is not a promotion&amp;rdquo;。You are paid for what you cover。&amp;rdquo;what you cover&amp;rdquo;就像长方形的面积，面积大小有长和宽同时决定。VP管的很多（长），但是深度有限（宽）。而技术大牛管的很少（长），但是很深（宽），所以两个长方形的面积大小差不多。这也就是为什么 有些技术大牛一个人不管但是挣钱和VP一样多。下面是几个测试工程师常见的职位：&lt;/p&gt;
&lt;p&gt;SDET － 初级测试工程师 ，要求是：executor，如果有个问题需要解决，而且告诉你如何解决，你能够很好地把问题解决了。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;SDET 2 － 中级测试工程师 ，要求是：designer，如果有个问题需要解决，你自己找出办法去解决。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;Senior SDET － 资深测试工程师，要求是：planner，你自己去发现问题，然后找出解决办法。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;Principal SDET － 首席 测试工程师， 要求是：thinker，能发现问题并且发现问题的共性，不仅解决问题而且避免问题出现。&lt;/p&gt;
&lt;p&gt;对经理的要求也大致如此，除了技术上也要过硬外，还要求经理为手下的人尽可能创造机会以帮助他们成功。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;另外微软鼓励测试工程师创造性思维，鼓励员工创建好的测试工具用来提高测试效率，好的想法也可以可以申请测试专利或发表论文，并且被邀请到国际性测试会议上做演讲。微软内部有一个测试工具库，有将近1万个测试工具。本人就有一个测试工具在微软内部50多个产品组广泛使用，我也多次做演讲，现在正open source。&lt;/p&gt;
&lt;p&gt;最后，我总结的测试工程师必须具备的硬技术能力：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;至少一门编程语言，比如 C++/C#/Java，最好也了解设计模式的基本概念，比如：open-close principle, design to interfaces, favor aggregation over inheritance, encapsulate&lt;br /&gt;by policy and reveal by need, etc&amp;hellip;&lt;/li&gt;
&lt;li&gt;至少一个脚本语言， 比如DOS batch, powershell, perl&lt;/li&gt;
&lt;li&gt;熟悉测试基础，比如功能测试，性能压力测试，安全测试，本地化测试。&lt;/li&gt;
&lt;li&gt;基本测试技能，比如等价类划分，边界值分析，黑白盒测试，组合测试，基于模型测试，探索性测试等&lt;/li&gt;
&lt;li&gt;Xml&lt;/li&gt;
&lt;li&gt;P/invoke&lt;/li&gt;
&lt;li&gt;Reflection&lt;/li&gt;
&lt;li&gt;Threading&lt;/li&gt;
&lt;li&gt;Code coverage analysis&lt;/li&gt;
&lt;li&gt;Network knowledge, such as TCP/IP, HTTP, HTTPS,WCF&lt;/li&gt;
&lt;li&gt;Fault injection/dependency injection and mocking&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;还有微软鼓励测试工程师take responsibility, make a difference。鼓励员工在做好本职工作同时在某一项技术领域专的更深。比如前面提到的一些测试基础 (test fundamentals) 包含功能测试，性能压力测试，安全性测试，本地化测试，容错测试, TiP等等。可以鼓励测试团队的每一个人选一个领域去专研，把他培养成不仅是产品组里的go-to person, 而且成为公司内乃至更大范围的领域专家。这不仅对产品的质量有帮助，更是对员工本身职业发展的极大激励。工程师是一群特殊的人类，如果一直重复做一件事（比如本职工作），很容易厌倦失去兴趣；相反越是有难度，有挑战，有影响力的工作，越是激发工程师一定要搞定，做好的斗志和恒心，哪怕是没有任何报酬，不为别人，为的是自我价值的实现。英语里有句话：it&amp;rsquo;s not what you have to do make you success, it&amp;rsquo;s what else you do . that will make a difference. 所以不仅仅把本职工作做好（这是最低要求了），更进一步将会使你脱颖而出。&amp;ldquo;更进一步&amp;rdquo;不是指你的本职工作，也不是让你加班加点，而是指那些自己喜欢的可以实现自我价值，同时对产品质量有深刻影响的东西。没有人逼你做这些东西，你完全可以选择按部就班或平平庸庸。最后引用功夫熊猫里的一句话立志：It&amp;rsquo;s not about where you came from or what you were, it&amp;rsquo;s about what you choose to be。所以，what you choose to be?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;好了，关于微软的话题就此打住。感觉好像在写长篇小说，没完没了，越聊话题越多。:)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;小结，英语里面有句话&amp;ldquo;little steps lead to big change&amp;rdquo;。我觉得这句话用来描述微软走过的测试路最恰当不过了。微软有几百个产品组，发布过几千个产品。很难有一个或几个因素决定产品的质量。但是上面几个是我个人认为是诸多因素中的几个至关重要的。微软是世界上最伟大的软件公司&amp;hellip;..（没有之一）。尤其是在测试方面，微软的投资比其它任何公司都多，在软件测试理论和实践上绝对是首屈一指的领先者。微软就像一个健壮的中年人，而google像一个20岁的青年，facebook可能只是teenager。 但是google,facebook这些公司起源于互联网应用服务，在互联网应用服务质量管理方面的确有很多出色的实践。所以下一次和大家探讨：提高软件质量实践――Google 篇。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Stay tuned&amp;hellip;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;----------------------------------------&lt;/p&gt;
&lt;p&gt;关注我：新浪微博：@billliu_seattle &lt;a href="http://www.weibo.com/windowsazure"&gt;http://www.weibo.com/windowsazure&lt;/a&gt; 或twitter: @billliu_seattle&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10304096" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="software testing" scheme="http://blogs.msdn.com/b/billliu/archive/tags/software+testing/" /></entry><entry><title>code coverage, what is for after all?</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/05/06/code-coverage-what-is-for-after-all.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/05/06/code-coverage-what-is-for-after-all.aspx</id><published>2012-05-06T18:24:00Z</published><updated>2012-05-06T18:24:00Z</updated><content type="html">&lt;p&gt;I was reading discussions&amp;nbsp;on software testing code coverage. The discussion was dominated by what the code coverage number for unit test or overall test&amp;nbsp;&amp;nbsp;are correct or desired. 40%, 60%, 80%, even 100%? some claims that google only requires 60%. some asked me what are code coverage number requirement in microsoft. as far as i know, there isn't code coverage requirement per se in microsoft, but only guidance. although i can't speak for google, but&amp;nbsp;very likely&amp;nbsp;they are the same here. for code coverage, there is only guidance, no requirement. so instead telling him 'no requirement', thought better to write a few thoughts&amp;nbsp;i have regarding code coverage. (disclaimer: when I speak on microsoft or google, i have to use "in general", "in most case", or "in many product teams", because microsoft and google are so big and diverse, have so many product teams, there are no universal ways for every engeering practice.&amp;nbsp; some teams do it in this way, some teams do it in other way. however there are common practices that are adopted by many or most teams. code coverage is one of them.)&lt;/p&gt;
&lt;p&gt;what's the code coverage anyway? code coverage is a to measure how much the product code was covered by a set of test.&amp;nbsp;it can&amp;nbsp;be&amp;nbsp;measured by&amp;nbsp;by&amp;nbsp;lines, by blocks, by arcs, by classes, or by files, etc.. in most case, we use blocks&amp;nbsp;as code coverage unit. note: we only collect code coverage based on automated tests, not consider manual tests.&lt;/p&gt;
&lt;p&gt;in most microsoft product teams, we do require to collect code coverage number. there are different&amp;nbsp;code coverage numbers we collect based on different type of tests, for instance, code coverage for unit tests, code coverage for component tests, and code coverage for scenario tests (e2e).&amp;nbsp; unit test code coverage are automatically collected whenever unit test got run. so dev finishing up writing code/unit tests before checkin, they run a set of tests (checkin quality gate) which includes unit tests. so you got unit test code coverage automatically. code coverage on component tests and scenario tests are collected on code coverage build peroidically, for example once a week&amp;nbsp;or on demand.&lt;/p&gt;
&lt;p&gt;there is always argument about the real benefit of code coverage. some says code coverage number represents product quality, the higher the number is, the higher the product quality is. some says higher code coverage doesn't mean higher quality, because 100% coverred code still have bugs, which is true.&lt;/p&gt;
&lt;p&gt;here is my takes on code coverage:&lt;/p&gt;
&lt;p&gt;1. code coverage is important. it's easy and simple to collect and fast way to let you get&amp;nbsp; a&amp;nbsp;sense on how the codes are tested. it let you visualize and examine how the codes are tested. kind of like a flash light in the dark which let you see many objects more clearly. does it gurantee you will see the objects in the dark, of course not. but without flash light, it will be quite difficult to see the object.&lt;/p&gt;
&lt;p&gt;2. although 100% code coverage doesn't not mean bug free, but 0% code coverage DOES mean a huge risk&amp;nbsp;to product quality.&lt;/p&gt;
&lt;p&gt;3. code coverage only measure how the codes are tested, not how the product are tested.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;so, do we need a requirement on code coverage number? if yes, what the number is the best?&lt;/p&gt;
&lt;p&gt;first off, any number is meaningless without a context. number itself is not the goal. it's&amp;nbsp;the indictor for any action need to follow. it's like you got 100 points school test, is it good? bad? the answer is: it depends. it depends on what's the total points, the easy/difficult of the test, what points do your peers get, etc... it's the same to the code coverage number. 60%, 80% or 100% don't mean anything without context.&lt;/p&gt;
&lt;p&gt;then what should i do with it after collect the code coverage? this is exactly the meaning of collecting code coverage number, find out what you should do with your code coverage number, or how to use/interpret the number:&lt;/p&gt;
&lt;p&gt;1. test gap analysis. i would say this is most important benefit of code coverage. there are many ways to do test gap analysis, however, throuh analyzing code coverage is one of most effective way.&amp;nbsp; exam the code coverage number, see which areas are low or zero coverage, decide any test could missed or potenail risk areas.&lt;/p&gt;
&lt;p&gt;2. test effectiveness analysis. i have 1000 test cases which takes 1 day to run. can it reduced to 500 test cases, 200 test cases without compromise overall test coverage?&lt;/p&gt;
&lt;p&gt;3. test and code change association analysis. one of hard problem to sovle in software testing is: i just change one line of code, you need to run 1000 test cases taking one day to verify no regression? there got be a better way. where, the better way is to run only affect tests. the question is how&amp;nbsp;do you know what tests got affected. there are tools/researchs available to help, by&amp;nbsp;using code coverage.&lt;/p&gt;
&lt;p&gt;4. see your code coverage trend over time, is it getting higher and higher or lower and lower.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;last, if you must need a&amp;nbsp;number from me, here is my guidence. again, any number is meaningless without context.&lt;/p&gt;
&lt;p&gt;1. if you unit test cc is &amp;gt; 80%, you should take action only when you have time&lt;/p&gt;
&lt;p&gt;2. if your unit test cc is between 50% and 80%, you should allocate some time within your current milestone to take action on it.&lt;/p&gt;
&lt;p&gt;3. if your unit test cc is &amp;lt;50%, you should allocate some time&amp;nbsp;asap to&amp;nbsp;take action on it.&lt;/p&gt;
&lt;p&gt;4. if your unit test cc is &amp;lt;30%, you call yourself a developer???? :)&lt;/p&gt;
&lt;p&gt;hope this help....&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;----------------------------------------&lt;/p&gt;
&lt;p&gt;关注我：新浪微博：@billliu_seattle &lt;a href="http://www.weibo.com/windowsazure"&gt;http://www.weibo.com/windowsazure&lt;/a&gt; 或twitter: @billliu_seattle&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10301572" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="software testing" scheme="http://blogs.msdn.com/b/billliu/archive/tags/software+testing/" /></entry><entry><title>软件质量控制实践――Microsoft 篇 (2)</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/05/03/microsoft-2.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/05/03/microsoft-2.aspx</id><published>2012-05-03T07:20:00Z</published><updated>2012-05-03T07:20:00Z</updated><content type="html">&lt;ol&gt;&lt;/ol&gt;&lt;ol&gt;4. Drive quality upstream&lt;/ol&gt;
&lt;p&gt;我们都知道bug越是滞后发现，修复的成本越高。据微软统计，如果产品发布以后需要发布一个热修复，它的直接成本是150万美元（间接成本在200万美元），而在发布之前的一个月发现的话，修复成本是5万，设计阶段修复成本是1千，需求阶段修复成本是1百。在需求分析阶段，测试人员主要职责就是验证需求分析的可行性和可靠性。PM和DEV的共性是易于乐观，倾向于把实际情况简单化，所以会作出很多假设。比如用户肯定不会这么使用，用户肯定知道如何用，所有用户的环境肯定都有该配置。但是实际情况下总会有用户不知道如何用，总会有用户会不按&amp;ldquo;预先设计&amp;rdquo;的方式使用，总会有用户环境没有该项配置。所以测试人员的主要职责就是找出这些假设并提出疑问并加以验证。&lt;/p&gt;
&lt;p&gt;在dev设计阶段，测试人员需要验证设计，同样找出dev的假设然后疑问这些假设是否合理，看看该设计是否处理很多没有预料的但是有可能会发生的情况，比如用户输入特殊字符，非常规操作，非常规流程，机器重启，死机，数据库连接中断，网络中断，内存耗尽等等。除了验证设计是否处理非正常情况外，测试人员的另外一个更为重要的职责是验证设计的可测试性。可测试性是指测试软件容易的程度。软件的可测性对于提高软件的质量至关重要。道理很简单，如果你的软件很难测试，无从下手，测试一个用例需要几个小时甚至几天的话，你的软件质量也就无从保证。提高软件可测试性通常的做法是把软件模块化，松耦合，模块内部运行状态可见，模块内部运行分支可控制。在评审一个设计时通常问的问题是该如何测试该模块，是否容易测试它，能不能单独测试它。如果不可以的话，需要重新考虑设计。因为一个设计的很容易测试的模块和产品可以使得后期的测试代价大大降低。微软大部分复杂系统都会有一个&amp;ldquo;one-box&amp;rdquo;版本，该版本是个假的模拟系统但是拥有真正系统的几乎所有功能，它可以运行在任何机器上。系统的绝大部分功能都可以在该模拟系统上快速方便验证。我在培训的时候很多学生问，他们在后期测试的时候遇到许多无法测试或者很难测试的困境，问我该如何解决。在具体了解困难和困境之后，我发现他们的测试策略非常单调，只能把产品部署到有限的测试环境下从用户界面上做端到端的测试。如果想测试某个特定模块或功能需要好几个其它模块配合起来才可以。我就坦率的说如果你的软件是这么架构设计的话而且已经到了这一步，世界上没有人可以解决你现在面临的困难。因为看起来好像你是卡在现在这一步了，但实际上根本问题是在前期，在需求或设计。就像解决河流的水质污染问题，你在下游无论多大的代价也只能稍微改善，解决问题的根本方法是在解决上游的污染源。或者像隔靴挠痒，隔着厚厚的靴子无法挠到关键地方，必须能够把靴子脱掉直接挠。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5. Getting better every day&lt;/p&gt;
&lt;p&gt;软件测试的目的一个是找出bug,另外一个是衡量软件的质量。通过测试来了解产品哪些地方薄弱，哪些地方不稳定. 通过监控测试的结果，包括功能测试，性能压力测试，安全测试，本地化测试，容错测试等等来反映当前软件的质量。这也是持续集成的一个重要原因，它一方面短期迭代，另一方面可以在最短的时间内知道软件的质量，同时跟踪软件质量重开始到发布，软件质量的变化曲线。衡量软件质量的通常指标有：测试用例通过率/趋势，bug数量，种类/趋势，代码覆盖率等等。另外测试在开发周期中通常做的其它工作还有：bug root cause analysis, Bug analysis, Test case failure analysis, test gap analysis, Bug talk, bug share, CCS data analysis等等。这一方面促使产品质量逐渐变好，而且是看得见的好。另外也促使自己放下繁忙的工作静心思考一下，如何更有效率更进一步提高质量。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6. Engineering agility&lt;/p&gt;
&lt;p&gt;随着软件即服务和云计算的兴起，它们给开发管理，质量管理，运营管理等提出了很多新的挑战。以前那种保密开发测试2－3年再突然发布的策略无法适应互联网应用服务的要求，而是逐渐演变成快速开发出产品基本原型，然后就发布，根据用户反馈不断加以改进的方式。质量管理方面，基于服务的产品除了关注功能性能，还有其它特别重要的方面，比如scalability, high availability, fault tolerance, disaster recovery, etc.. 这些都是桌面型产品所没有的或不重视的。微软从2010年开始在很多组开始实践如何提高服务型产品的质量，比如Azure, Bing, etc&amp;hellip;。其中最为根本的一点就是提高整个团队的敏捷度，团队能够跟的上快速迭代交付的节奏。这需要从产品设计上到测试自动化，工具，基础设施上得以保障。另外一个非常重要的实践就是TiP (test in production) 或 crowd-sourced testing. 我们在前面谈到&amp;ldquo;drive quality upstream&amp;rdquo;，也即是提前测试。test in production正好相反是&amp;ldquo;drive quality downstream&amp;rdquo;，也即是在产品环境中测试。传统的桌面产品发布之后就不再测试了。服务型产品，产品发布后继续测试。它的基本出发点是：无论投资多少建立测试环境用以模拟产品运行环境，测试环境和真正产品环境总会有不同。无论花费多大的代价做前期测试，都不可能找出所有的bug。所以无论在发布之前花费多大的代价做测试，在产品上线后总会发现新的bug。现在既然发布产品更新非常快和容易，为什么不干脆在真正产品环境中来测试，或者利用真正的用户使用真正的产品来测试（当然用户意识不到）。一旦发现bug,马上修复，马上更新。这不仅减轻了前期测试的投入，而且提高的测试效率。看看我们在测试环境中发现的bug有多少没有被认为是&amp;ldquo;真正&amp;rdquo;的bug就明白了。当然要做到test in production, 需要很多具体的流程、技术，工具作为保障。不能影响用户的关键业务，不能让用户发现过于简单的bug。 除了基本的测试自动化基础设施和测试用例外，常用的一些TiP技术有：A/B testing, expose control/slicing model, on/off features, chaos-monkey, measuring/monitoring.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;最后一篇将和大家讨论一下测试工程师的技能提高和职业发展， to be continued .....&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;----------------------------------------&lt;/p&gt;
&lt;p&gt;关注我：新浪微博：@billliu_seattle &lt;a href="http://www.weibo.com/windowsazure"&gt;http://www.weibo.com/windowsazure&lt;/a&gt; 或twitter: @billliu_seattle&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10300306" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="software testing" scheme="http://blogs.msdn.com/b/billliu/archive/tags/software+testing/" /></entry><entry><title>软件质量控制实践――Microsoft 篇 (1)</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/04/29/microsoft-1.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/04/29/microsoft-1.aspx</id><published>2012-04-29T05:18:00Z</published><updated>2012-04-29T05:18:00Z</updated><content type="html">&lt;p&gt;因为工作在微软的缘故，无论我在给国内企业做软件测试内训的时候，还是在质量技术大会上做演讲的时候，问的最多的一个问题就是：微软如何做测试的？前几天看见有人在新浪微博上讨论是否需要专职QA，再有我刚刚决定带领两个google在西雅图的测试工程师一起翻译google的新书《how google tests software》。微软以前也有一本书《how we test software at microsoft》。所以几件事情碰到一起，有感而发，决定写一个&amp;ldquo;xx公司如何测试的&amp;rdquo;系列文章。目的不是为了回答以上问题，旨在通过分析对比如Microsoft,Google, Amazon, Facebook等在保证产品质量的诸多具体实践， 和大家分享一下我个人认为这些公司在保证软件质量中的最为关键的几个实践和经验。希望大家有所收获和思考。我们今天先谈谈微软在提高软件质量上有哪些值得学习和借鉴的经验：&lt;/p&gt;
&lt;p&gt;&amp;nbsp;1. Evolving test role&lt;/p&gt;
&lt;p&gt;微软的正式测试工程师可以追溯到1990年左右，以后以每年大概500人递增。现在大概有1万左右的测试工程师。回顾走过的20多年，其中最为明显的特征就是微软对软件测试和质量控制的认识不是一成不变的，而是随着经验的积累，产品的演变不断演变，同时测试工程师的职责也不断在演变。最开始叫software test engineer (STE)，主要职责是设计测试用例，手工黑盒测试。2000年左右演变成Software Design Engineer in Test (SDET)，主要职责是设计测试用例，开发测试自动化代码，测试基础设施和测试工具。同时把繁琐的简单的手工测试外包给印度和中国的外包公司。2005年以前公司的测试文化基本上是：产品质量是测试人员的责任，测试人员保证产品质量，测试人员很多时候像给开发打下手为开发服务。2005年后随着敏捷和软件及服务的出现，测试的角色逐渐从依赖测试来提高产品质量转变成用测试来建立保证产品质量的具体要素。测试不再像给开发打下手，而是转变成一个独立的岗位为产品质量服务。2010后，随着软件即服务和云计算的日趋成熟，微软很多产品组转向开发服务型的产品，同时测试人员的角色为了适应新的挑战而继续演变，比如现在很多组开发也做测试，测试也做开发，两者间的界限越来越模糊。正是测试的这种灵活性和对不同时期不同产品的适应性使得每个发布产品的质量得以有效保证。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2. Set full-time test role&lt;/p&gt;
&lt;p&gt;微软的产品一直以桌面产品为主，比如Windows, Office, SQL server, etc&amp;hellip;。这些类型的产品的共同特点就是对发布版本的质量要求非常非常高，它要求产品在发布之前必须修复几乎所有的bug，至少不可以有关键性bug。因为万一漏掉一个关键性的bug，召回产品或发布热修复的代价太大。所以每个产品组在产品开发过程中投入大量的测试人员来全方位，反反复复测试， 包括功能测试，性能压力测试，本地化国际化测试，安全性测试，使用性和兼容性测试，等等。这些大量繁重的工作不可能都有dev来做。有了专职的测试人员不仅大大减轻了开发人员的工作量，而且通过测试人员特有的、经过专门训练的技能可以在产品发布之前找出更多、更为关键的bug。所以在这种情况下，专职测试人员不仅是有用的而且是必须的，他们对提高软件质量起到至关重要的作用。在像windows和office这两个最大的产品组，专职测试人员的数量和开发一样多，再加上大量外包公司的测试人员，可以说测试人员的数量实际上是开发的将近两倍。但是，如前所述，随着从桌面产品逐渐转向服务型的产品（软件即服务），专职测试人员的作用在逐渐下降。主要原因是：首先产品质量不再是光光通过&amp;ldquo;测试&amp;rdquo;来提高了；其次对发布版本质量要求有所降低，因为服务型产品不是安装在用户机器上而是部署在微软自己的数据中心里，如果有bug，开发人员可以很快修复然后及时更新产品（而不是像桌面产品需要召回），所以热修复的成本大大降低了；还有就是利用用户来做测试（我们在下面会具体再谈）。所以在服务型产品中，专职测试人员的作用不再像以前那样显得至关重要。微软现在许多组在削减测试，或者转成dev，即使保留测试的头衔，做的工作也不是严格意义上的测试了。另外一点值得说明的是，虽然专职测试人员数量有所减少，但是并不意味着测试的覆盖率就一定减少了。很多时候实际上是测试的覆盖率更多了，这主要是因为开发做越来越多的测试，同时测试的效率提高。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;br /&gt;3. Heavily invest in test automation&lt;/p&gt;
&lt;p&gt;测试自动化不是万能的，但是没有测试自动化是万万不能的。测试自动化可以把测试人员从枯燥重复的手工测试中解脱出来做更多更有有技术含量的工作。当然测试自动化需要前期投入，而且不稳定的测试自动化还会把测试人员拽到疲于维护的泥潭中。但是这不是否定测试自动化的理由。没有用好测试自动化并不代表它没有用。而且，敏捷测试，持续集成，快速交付，等等都是以测试自动化为基础的。公司可以根据具体情况采用逐步提高的策略，比如先自动化每日构建，再自动化部署，然后自动化最关键的测试用例，次关键的测试用例，等等。微软测试工程师有超过80％的时间是在写测试代码。它们包括测试自动化代码，开发基础设施代码以及开发测试工具。默认情况下自动化所有测试用例，除非你有合理的理由不自动化。我个人的准则是：如果手工重复运行一个过程超过3次，就是时候自动化了。通常在一个发布周期的计划阶段，PM,dev，test,根据本次发布的时间长短和内容各自做计划，然后汇总讨论，制定一个最终的符合各个角色的发布计划。Pm和dev决定本次发布中的产品新功能，测试决定本次发布中的测试有关的工作量，比如为新功能而添加的测试自动化，为修改现有功能而修改测试，需要开发或改进的测试工具或基础设施。经过讨论后大家一致同意最终计划。计划好后，大家就根据各自的计划并行工作，当然中间大家及时沟通进度，如果需要，调整计划。这个过程的好处是把与测试自动相关的所有工作都放到开始项目计划中来，包括新功能测试自动化，现有代码的维护，工具的创建和改进等等，这不仅逐步提高测试自动化覆盖率，而且使得基础设施和测试工具逐渐成熟和完善。成熟和完善的设施和工具同时极大提供了开发效率和速度，比如大部分产品组都有daily execution 和checkin quality gate：&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;times; Daily execution: 每天晚上，自动生成每日构建，自动部署到测试环境，自动运行测试用例。对于失败的测试用例，系统自动报bug,并且对测试日志和产品日志进行自动分析，把相关信息放到bug中。最后自动发送测试结果到整个组。第二天早上到办公室，每个人都会看到已经运行完的测试报告。这使得测试可以有更多的时间自动化更多的用例，更多的时间分析测试缺口或做探索性测试。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;times; Checkin quality gate: 开发在提交代码之前通过运行一个简单命令可以把相关测试自动运行一遍。这使得开发从一开始就提交高质量的代码。&lt;/p&gt;
&lt;p&gt;即使在做手工或探索性测试，测试工程师也尽可能使用测试工具来自动化其中步骤，从而使得测试人员完全专注于应该专注的地方，比如思考探索尝试，而不是在别的地方浪费时间，比如准备测试数据，搭建测试环境，分析日志，报bug等等。 打个简单的比喻，比如你要从北京到上海开会，手工测试就好像你骑自行车过去，你的目的是开会但是你结果把大量时间浪费在路上了。测试自动化就好像你乘飞机过去。还有看起来来好像飞机票很贵，成本比骑自行车要大，但实际上最后骑自行车的成本要高的很多。只不过很多成本你当时看不到罢了。&lt;/p&gt;
&lt;p&gt;所以很多我给做培训的公司的经理抱怨说我们也想做单元测试，做测试自动化，但是就是成本负担不起。我就说你只看到&amp;ldquo;做&amp;rdquo;的成本，因为它很直接；而看不到&amp;ldquo;不做&amp;rdquo;的成本，因为你不能马上看到。业界无数公司，项目已经证明在单元测试和测试自动化在提高软件质量方面&amp;ldquo;不做&amp;rdquo;的成本要比&amp;ldquo;做&amp;rdquo;的成本大的多得多。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;to be continue...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;----------------------------------------&lt;/p&gt;
&lt;p&gt;关注我：新浪微博：@billliu_seattle &lt;a href="http://www.weibo.com/windowsazure"&gt;http://www.weibo.com/windowsazure&lt;/a&gt; 或twitter: @billliu_seattle&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10298814" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="software testing" scheme="http://blogs.msdn.com/b/billliu/archive/tags/software+testing/" /></entry><entry><title>any update on managed fault injection in testapi?</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2012/03/13/any-update-on-managed-fault-injection-in-testapi.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2012/03/13/any-update-on-managed-fault-injection-in-testapi.aspx</id><published>2012-03-13T21:48:46Z</published><updated>2012-03-13T21:48:46Z</updated><content type="html">&lt;p&gt;there is an issue with&amp;nbsp;fault injection api in the latest&amp;nbsp;testapi version (0.6). unfortunately the testapi project on codeplex doesn't seem to be actively maintained any more. so i'm working on creating an new project on codeplex for managed fault injeciton only. the new project will have full functionality instead of the current limited version.&lt;/p&gt;
&lt;p&gt;before the new&amp;nbsp;project goes live, please use testapi 0.5 version for fault injeciton.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10282297" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="Fault Injection" scheme="http://blogs.msdn.com/b/billliu/archive/tags/Fault+Injection/" /></entry><entry><title>TechED 2011 北京</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2011/10/19/teched-2011.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2011/10/19/teched-2011.aspx</id><published>2011-10-19T07:13:00Z</published><updated>2011-10-19T07:13:00Z</updated><content type="html">&lt;p&gt;TechED 2011圆满结束了。很荣幸再次接受主办方的邀请，能够亲临大会现场感受，可以说是行程匆匆、收获多多。因为redmond这里工作很忙，加上刚刚回过国，所以这次在国内只呆了一个礼拜。本次行程的几个亮点：&lt;/p&gt;
&lt;p&gt;1. 见了几个大学同学，回忆过去，展望未来。带来一瓶白酒，喝的吃的很过瘾。&lt;/p&gt;
&lt;p&gt;2.做了两次有关Windows Azure的演讲。&lt;/p&gt;
&lt;p&gt;3. 我的新书终于如期出版了《详解Windows Azure云计算平台》。woooh!大半年的奋笔疾书，呕心沥血，总算是小有收获吧。感兴趣的朋友可以在网上预购了：&lt;a href="http://product.china-pub.com/194361#xgzy"&gt;http://product.china-pub.com/194361#xgzy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;4.做了一个小时的与读者面对面交流签名售书活动&lt;/p&gt;
&lt;p&gt;5.做了一小时媒体采访&lt;/p&gt;
&lt;p&gt;6.晚上做了两个小时的infoQ举办的与专家面对面技术社区活动。&lt;/p&gt;
&lt;p&gt;几点感受：&lt;/p&gt;
&lt;p&gt;1.国内云计算环境开始转向务实。这点很好，去年我回去时候明显感受到整个业界对云计算很浮躁，都在谈云计算，但是又不太清楚什么是云计算。问的问题都有的不着边。然而今年回去，明显感觉到业界多云计算有了更深刻的了解。不再是泛泛而谈，而是讨论云计算的收益和具体实施。问的问题也侧重于使用。比如我被多次问道具体案例，实际经验等等。&lt;/p&gt;
&lt;p&gt;2.同时对讲课内容要求也有所提高，不再是单单满足理论知识，而是倾向于了解更多的实际案例，解决方案，设计架构。&lt;/p&gt;
&lt;p&gt;3.对云计算的理解还有待继续提高。绝大部分对云计算的理解停留在基础设施及服务或仅仅虚拟化的层面上，对平台及服务和软件及服务了解不多。也许是国内可选择公有云几乎没有的原因吧，绝大部分企业都在或打算搞自己的私有云。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;最后，上传我的两次演讲的PPT：&lt;a href="https://skydrive.live.com/redir.aspx?cid=014259c1c51ccac5&amp;amp;resid=14259C1C51CCAC5!127"&gt;https://skydrive.live.com/redir.aspx?cid=014259c1c51ccac5&amp;amp;resid=14259C1C51CCAC5!127&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10227378" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="Windows Azure" scheme="http://blogs.msdn.com/b/billliu/archive/tags/Windows+Azure/" /></entry><entry><title>windows azure management portal 中文版</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2011/07/18/windows-azure-management-portal.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2011/07/18/windows-azure-management-portal.aspx</id><published>2011-07-18T18:50:55Z</published><updated>2011-07-18T18:50:55Z</updated><content type="html">&lt;p&gt;今天微软发布了最新版本的windows azure管理门户网站（management portal）。令人欣喜的是在该新版本开始支持中文了。虽然Windows Azure在中国大陆暂时还不可以使用，但是我们可以看出微软在继续为在中国推广Windows Azure而打基础的决心还是很大的。另外，中国大陆的用户完全可以学习和研究windows azure. 只是在注册时候选择中国香港。 而且微软经常会推出很多免费使用windows azure的机会，比如现在就有3个月免费（需要信用卡）和1个月免费（不需要信用卡）。大家可以试一试。&lt;/p&gt;
&lt;p&gt;不过好像翻译的有些问题，很多地方我都看不懂了，还是切换回英文了 ：）&lt;/p&gt;
&lt;p&gt;先睹为快。&lt;a href="http://windows.azure.com"&gt;http://windows.azure.com&lt;/a&gt;，登录后选择中文。&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-36-48/5543.azureportal.PNG"&gt;&lt;img border="0" alt="" src="http://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-36-48/5543.azureportal.PNG" /&gt;&lt;/a&gt;&lt;a href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-36-48/6866.azureportal.PNG"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10187595" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="Windows Azure" scheme="http://blogs.msdn.com/b/billliu/archive/tags/Windows+Azure/" /></entry><entry><title>Microsoft Windows Azure Platform whitepaper (白皮书)</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2011/01/05/microsoft-windows-azure-platform-whitepaper.aspx" /><link rel="enclosure" type="application/pdf" length="827731" href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-11-18-91/Microsoft-Windows-Azure-Platform-_7D76AE76664E_.pdf" /><id>http://blogs.msdn.com/b/billliu/archive/2011/01/05/microsoft-windows-azure-platform-whitepaper.aspx</id><published>2011-01-05T06:56:00Z</published><updated>2011-01-05T06:56:00Z</updated><content type="html">&lt;p&gt;三个星期的圣诞节假期过的真快！今天是上班的第一天，感觉还在度假一样。好在假期时间没有白费，把David的关于windows azure platform whitepaper 好好读了一边。读的过程中顺便翻译了一下。正好还没有发现关于Windows Azure 平台的中文书籍，这也许算是关于Windows azure 平台的中文第一书吧？ ^_^。。。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;点击附件下载，欢迎宝贵意见。&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10111891" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="Windows Azure" scheme="http://blogs.msdn.com/b/billliu/archive/tags/Windows+Azure/" /></entry><entry><title>My Demo in TechED 2010 China</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2010/12/31/teched-2010-demo.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="3689991" href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-11-06-78/TechED2010_5F00_China_5F00_Demo.zip" /><id>http://blogs.msdn.com/b/billliu/archive/2010/12/31/teched-2010-demo.aspx</id><published>2010-12-31T20:42:00Z</published><updated>2010-12-31T20:42:00Z</updated><content type="html">&lt;p&gt;上传我在TechED 2010 中国上做的Demo。&lt;/p&gt;
&lt;p&gt;以下是一些关于我课程的媒体报道（从百度上搜的):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cloud.51cto.com/art/201012/236296.htm"&gt;http://cloud.51cto.com/art/201012/236296.htm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cloud.51cto.com/art/201012/236344.htm"&gt;http://cloud.51cto.com/art/201012/236344.htm&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://bbs.tech.163.com/bbs/itchaguan/191646556.html"&gt;http://bbs.tech.163.com/bbs/itchaguan/191646556.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://soft.cfan.com.cn/win7/201012/26/1293325638d13865.shtml"&gt;http://soft.cfan.com.cn/win7/201012/26/1293325638d13865.shtml&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cio.zol.com.cn/topic/2055712.html"&gt;http://cio.zol.com.cn/topic/2055712.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.chinacloud.cn/list.aspx?cid=12"&gt;http://www.chinacloud.cn/list.aspx?cid=12&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10110678" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="Windows Azure" scheme="http://blogs.msdn.com/b/billliu/archive/tags/Windows+Azure/" /></entry><entry><title>My Session PPT in TechED 2010 China</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2010/12/31/teched-2010-ppt.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="4223302" href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-11-06-76/TechED2010_5F00_China_5F00_PPT-.zip" /><id>http://blogs.msdn.com/b/billliu/archive/2010/12/31/teched-2010-ppt.aspx</id><published>2010-12-31T20:31:00Z</published><updated>2010-12-31T20:31:00Z</updated><content type="html">&lt;p&gt;上传我的演讲PPT.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10110676" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="Windows Azure" scheme="http://blogs.msdn.com/b/billliu/archive/tags/Windows+Azure/" /></entry><entry><title>Windows Azure</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2010/12/31/windows-azure.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2010/12/31/windows-azure.aspx</id><published>2010-12-31T05:17:00Z</published><updated>2010-12-31T05:17:00Z</updated><content type="html">&lt;p&gt;从北京TechED 2010回来已经快一个月了，一直想开始写一些针对云计算和Windows Azure的东西。主要是这次TechED之行感触很多，特别是国内对云计算技术的热衷。同时我又发现关于云计算的资料少之又少，关于Windows Azure学习资料就更是寥寥无几了。所以我想在我的博客中开始写关于云计算的东西。该博客 1. 面向国内用户 （所以我用中文了 :) ） 2. 专注于Windows Azure 技术，因为我在这个组工作 ：）。&lt;/p&gt;
&lt;p&gt;这次中国之旅非常匆忙。共做了5次演讲： 外包公司两次，北京TechED 2010 两次，上海第二届.NET 技术大会一次. 最后嗓子很痛。在老家和爸妈就呆了一天。看来做讲师也不是容易。&lt;/p&gt;
&lt;p&gt;在北京TechED 2010演讲的连接：&lt;/p&gt;
&lt;p&gt;&lt;a href="http://technet.microsoft.com/zh-cn/ff934861.aspx"&gt;http://technet.microsoft.com/zh-cn/ff934861.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在上海第二届.NET 技术大会演讲的连接：&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.net-china.org/"&gt;http://www.net-china.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.net-china.org/con2010/speaker.aspx"&gt;http://www.net-china.org/con2010/speaker.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10110543" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="Windows Azure" scheme="http://blogs.msdn.com/b/billliu/archive/tags/Windows+Azure/" /></entry><entry><title>Fault Injection to Web application or Windows service</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2010/10/23/using-fault-injection-api-for-web-application-or-windows-service.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2010/10/23/using-fault-injection-api-for-web-application-or-windows-service.aspx</id><published>2010-10-23T07:24:00Z</published><updated>2010-10-23T07:24:00Z</updated><content type="html">&lt;p&gt;I have been busy since this march when i moved to Azure team.&amp;nbsp;since then, a newer version of&amp;nbsp;TestAPI (v0.5) was released. we take a few bugs fix in this release. one of them is .net 4.0 compatible. in my previous post, i mentioned that you need to set the enviornment varible for .net 4.0 application. in v0.5, we fix this, so if you use v0.5 onward version, you can ignore that manual workaround. we also add another important feature called "global mode"&amp;nbsp; which enable you to inject fault into web applications or window service.&lt;/p&gt;
&lt;p&gt;as I pointed out in prior post that to use fault injection API, you have to use the provided API to launch your application that you want to inject fault. The problem comes when you don't have the executable or you can't launch the executable, one of obvious example is web application or windows service application which&amp;nbsp;are launched by windows system or IIS automatically. this is exactly the reason why we provided 'global mode'. in global mode, the fault injection will take effect on all processes running on this machine, so you don't have to launch your test application.&amp;nbsp;however, you still need to enable the fault injection&amp;nbsp;BEFORE web application or windows service&amp;nbsp;starts. in this post, I will show you how to use global mode to inject fault into a web application step by step.&lt;/p&gt;
&lt;p&gt;step 1: download the TestAPI v0.5&amp;nbsp; from&amp;nbsp;&lt;a href="http://www.codeplex.com/testapi"&gt;http://www.codeplex.com/testapi&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Step2: create you&amp;nbsp;web application for test ( i will create a simple calculator )&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a. in visual studio, create a new web application project&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; b. in the web page design view, add two testbox and&amp;nbsp;one button and one label &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c. double click the button to open the code view. in the code, add the following codes:&lt;/p&gt;
&lt;p&gt;
&lt;p&gt;&lt;code class="csharp"&gt;
&lt;pre class="scroll"&gt;&lt;code class="csharp"&gt;&lt;span style="color: #3366ff;"&gt;protected void Button1_Click(object sender, EventArgs e)
&lt;br /&gt;{
&lt;br /&gt;   Label1.Text = Add(Int32.Parse(TextBox1.Text),Int32.Parse(TextBox2.Text)).ToString ();
&lt;br /&gt;}
&lt;br /&gt;private int Add(int x, int y)
&lt;br /&gt;{
&lt;br /&gt;     return x + y;
&lt;br /&gt;}
&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style="font-family: Arial;"&gt;&lt;/span&gt;&lt;/p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; d. Ctr+F5 to run the application, in the web page, input two integers and click button, the correct result displayed.&lt;/code&gt;&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Step3: inject fault using testapi&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a. in visual studio, create a console project and add the testapicore.dll to the reference&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; b. define the fault injection rules/sessions and start global mode. since i don't have test automation for my web application, i just let it pause before press any key, and then manully test my web application&lt;/p&gt;
&lt;pre class="scroll"&gt;&lt;code class="csharp"&gt;&lt;span style="color: #3366ff;"&gt;        static void Main(string[] args)
&lt;br /&gt;        {
&lt;br /&gt;            // Define rules
&lt;br /&gt;            string method = "WebApplication1.MyTest.Add(int,int)";
&lt;br /&gt;            ICondition condition = BuiltInConditions.TriggerOnEveryCall;
&lt;br /&gt;            IFault fault = BuiltInFaults.ReturnValueFault(0);
&lt;br /&gt;            FaultRule rule = new FaultRule(method, condition, fault);
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;            // Establish a session, injecting the faults defined by the fault rule(s)
&lt;br /&gt;            FaultSession session = new FaultSession(rule);
&lt;br /&gt;
&lt;br /&gt;            // Enable Global mode
&lt;br /&gt;            FaultSession.SetGlobalFault(session);
&lt;br /&gt;
&lt;br /&gt;            // Run your test automation here
&lt;br /&gt;            Console.WriteLine("press any key to exit....");
&lt;br /&gt;            Console.ReadLine();
&lt;br /&gt;
&lt;br /&gt;            // After test automation complete, disble global mode
&lt;br /&gt;            FaultSession.ClearGlobalFault();
&lt;br /&gt;
&lt;br /&gt;        }
&lt;br /&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c. shift+F5 to&amp;nbsp;build, saying the executable is named: mytestapitest.exe&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; d. &amp;nbsp;copy mytestapitest.exe to the webapplication&amp;nbsp;binary folder (in my case it's d:\webapplication1\bin).&amp;nbsp;AND copy "FaultInjectionEngine" folder from&amp;nbsp;your&amp;nbsp;testapi download/unzipped folder to&amp;nbsp;the webapplication binary folder too.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;e. run your test at administrator privilege: mytestapitest.exe&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; f. start a new visual studio and open your web application project and run it. in the web page, input two integers, you can see it always return 0 regardless what two integers you input. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Step4: press a key to exit your test. and start a new visual studio and run your web application again, the global mode shold be disabled and the application should run as normal.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;a few things you need to be aware to make sure you can get this working in your own machine:&lt;/p&gt;
&lt;p&gt;1. make sure your test running on elevated privilege&lt;/p&gt;
&lt;p&gt;2. copy test executable and "FaultInjectionEngine" folder to your web application binary folder due to the 'one-place' issue (ya, still not fixed in v0.5, hopefully i can fix this in next release)&lt;/p&gt;
&lt;p&gt;3. make sure to restart you web application or windows servcie AFTER enable global mode. in my case, i restart the visual stuido. if you&amp;nbsp;run&amp;nbsp;IIS&amp;nbsp;on your test machine, you can run "iisreset" to restart the IIS. this is true to all other application under global mode. you have to restart the application/service or command window to let global mode take effect.&lt;/p&gt;
&lt;p&gt;4. after test complete,&amp;nbsp;do not forget to disable global mode. again, after disabling global mode, you have to restart the application/servie or command window to let global mode truely disabled.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;with&amp;nbsp;all of these, you should be able to&amp;nbsp;use&amp;nbsp;global mode&amp;nbsp;to inject fault into web application/window service or in any situation that you can't launch test application.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-family: Courier New; font-size: large;"&gt;&lt;span style="font-family: Courier New; font-size: large;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10079838" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="Fault Injection" scheme="http://blogs.msdn.com/b/billliu/archive/tags/Fault+Injection/" /></entry><entry><title>if it still not working</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2010/05/27/if-it-still-not-working.aspx" /><link rel="enclosure" type="application/x-zip-compressed" length="1723966" href="http://blogs.msdn.com/cfs-file.ashx/__key/communityserver-components-postattachments/00-10-01-61-11/SupportDlls.zip" /><id>http://blogs.msdn.com/b/billliu/archive/2010/05/27/if-it-still-not-working.aspx</id><published>2010-05-27T06:13:00Z</published><updated>2010-05-27T06:13:00Z</updated><content type="html">&lt;p&gt;if you're sure that you followed exact steps in my previous blogs, but it seems the tool still not working. there are a few known issues that you can check to see if it's your case:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'Tahoma','sans-serif'; color: black; font-size: 10pt;"&gt;1. .NET 4.0&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'Tahoma','sans-serif'; color: black; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;the current version (TestAPI 0.4) does NOT work on .net 4.0 platform. so if you install .net 4.0 or your application compiled with .net 4.0, the fault injection will NOT work. I'm&amp;nbsp;working on the fix, but meanwhile, you can use the following steps to workaround:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'Tahoma','sans-serif'; color: black; font-size: 10pt;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set enviornment variable by running this command:&amp;nbsp; &lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;&lt;span style="font-family: 'Calibri','sans-serif'; color: black;"&gt;set COMPLUS_ProfAPI_ProfilerCompatibilitySetting=EnableV2Profiler&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: 'Tahoma','sans-serif'; color: black; font-size: 10pt;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;strong&gt;&lt;span style="font-family: 'Calibri','sans-serif'; color: black;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/strong&gt;&lt;span style="font-family: 'Calibri','sans-serif'; color: black;"&gt;then you should be good to go.&lt;/span&gt;&lt;span style="font-family: 'Tahoma','sans-serif'; color: black; font-size: 10pt;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 'Calibri','sans-serif'; color: black;"&gt;2. can't find fault injection engine file but it is there.&lt;/span&gt;&lt;span style="font-family: 'Tahoma','sans-serif'; color: black; font-size: 10pt;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-family: 'Calibri','sans-serif'; color: black;"&gt;&amp;nbsp;&amp;nbsp; if your machine does NOT have Visual Studio 2005/2008 installed, you are very likely meet this issue. the error message is kind of misleading. it actually means the registration engine failed for many possible reasons, one of them is .net 4.0 issue as I explained above. another reason is that it can't find the following dependent binaries: msvcr90d.dll, msvcp90d.dll, msvcm90d.dll,atl90.dll,Microsoft.VC90.ATL.manifest, Microsoft.VC90.DebugCRT.manifest.&lt;/span&gt;&lt;span style="font-family: 'Tahoma','sans-serif'; color: black; font-size: 10pt;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'Calibri','sans-serif'; color: black;"&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; you could either install Visual Studio 2005/2008&amp;nbsp;or .net framework SDK to install those dependent binaries, or you could download the attached zip file and unpack it, &amp;nbsp;and put&amp;nbsp;the binaries&amp;nbsp;into the both x86 and x64 accordingly under&amp;nbsp;faultinjectionengine folder.&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: 'Tahoma','sans-serif'; color: black; font-size: 10pt;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;"&gt;3.&amp;nbsp;&amp;nbsp;One-place issue.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; you need to put your application (aut.exe)&amp;nbsp; into the test binary (auttest.exe) directory. i.e the applicaiton and the test need to be in the same directory.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;"&gt;4. x64 bit issue&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; make sure your application and your test binary has the SAME bitness, i.e. both are 32 or both are 64.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10016111" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="Fault Injection" scheme="http://blogs.msdn.com/b/billliu/archive/tags/Fault+Injection/" /></entry><entry><title>Fault Injection For Managed Code</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2010/03/30/fault-injection-for-managed-code.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2010/03/30/fault-injection-for-managed-code.aspx</id><published>2010-03-30T22:21:00Z</published><updated>2010-03-30T22:21:00Z</updated><content type="html">&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;b&gt;&lt;span style="font-size: 12pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;"&gt;Introduction&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 12pt; mso-fareast-font-family: 'Times New Roman';"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-justify: inter-ideograph; text-align: justify; line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;span style="font-size: 12pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;"&gt;As&amp;nbsp;part of software testing, we often want to know&amp;nbsp;how the software behaves under failure conditions and&amp;nbsp;to know whether&amp;nbsp;the software system correctly handles error conditions, such as low memory, loss of network connectivity or dependent components unavailable, etc... This actually particularly important for managed code of which big parts are to handle exception. However, this is extremely to test in the normal test environment, it's even harder to&amp;nbsp;do through test automation. This is how fault injection comes into picture. Basically fault injection is to purposely inject fault into software code to simulate failure that occurs in a deterministic and repeatable way.&amp;nbsp; There are many existing tools for fault injection purpose; however, most of them have some significant drawbacks such as statically instrument binaries, not flexible to inject fault or different fault, no API for test automation, etc...&lt;/span&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 12pt; mso-fareast-font-family: 'Times New Roman';"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-justify: inter-ideograph; text-align: justify; line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;&lt;span style="font-size: 12pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;"&gt;To make fault injection easier, we developed&amp;nbsp;a new Tool/API for fault injection into managed code. It allows you to manually or through test automation to test exception&amp;nbsp;handling, manipulate different&amp;nbsp;code path at run time, and also mocking&amp;nbsp;API calls as well. If this sounds interesting to you, read on....&lt;/span&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 12pt; mso-fareast-font-family: 'Times New Roman';"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="font-size: 12pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Under the hood.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style="text-justify: inter-ideograph; text-align: justify; line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-size: 12pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Normally, this is how managed code got&amp;nbsp;executed. Developers first writes managed codes and compiles into binaries which is MSIL (Microsoft Intermediate Language).&amp;nbsp;At runtime, the method is invoked and CLR loads binary into&amp;nbsp;memory to do second compilation, i.e Just-In-Time compilation.&amp;nbsp;.Net framework provides a mechanism to monitor this process. Controlled by a set of environment variables,&amp;nbsp;CLR&amp;nbsp;at run time can trigger a set of events such as assembly loaded/unloaded, class loaded/unloaded,&amp;nbsp;etc... One of the most useful events is JITCompilationStarted event which occurs right before the method got JITed. You can subscribe a callback function to this event, so it will call your callback function when the event occurs. One of the parameters to the callback function is FunctionID through which you can call GetILFunctionBody to get function's original IL code, then you can modify it in the memory (inject fault, in this case), as a result the modified IL code passed to the JIT compiler through SetILFunctionBody method. This is in high level how the managed fault injection API works. For .net profiling, please check MSDN (&lt;/span&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms404386(v=VS.80).aspx" mce_href="http://msdn.microsoft.com/en-us/library/ms404386(v=VS.80).aspx"&gt;&lt;span style="color: windowtext; text-decoration: none; text-underline: none;"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;http://msdn.microsoft.com/en-us/library/ms404386(v=VS.80).aspx&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;) for more details.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-justify: inter-ideograph; text-align: justify; margin: 0in 0in 10pt;" class="MsoNormal"&gt;&lt;span style="line-height: 115%; font-size: 12pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;To use managed fault injection API, you need to simply provide the WHERE, WHEN, and HOW information:&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-justify: inter-ideograph; text-align: justify; text-indent: -0.25in; margin: auto auto auto 0.5in; mso-add-space: auto; mso-list: l1 level1 lfo1;" class="MsoListParagraphCxSpFirst"&gt;&lt;span style="font-family: Times New Roman;" face="Times New Roman"&gt;&lt;span style="mso-fareast-language: EN-US;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-size: small;" size="3"&gt;1.&lt;/span&gt;&lt;span style="font: 7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin;"&gt;&lt;span style="font-size: small;" size="3"&gt;WHERE: defines which method to be injected fault, i.e. target method&amp;rsquo;s signature.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-justify: inter-ideograph; text-align: justify; text-indent: -0.25in; margin: auto auto auto 0.5in; mso-add-space: auto; mso-list: l1 level1 lfo1;" class="MsoListParagraphCxSpMiddle"&gt;&lt;span style="font-family: Times New Roman;" face="Times New Roman"&gt;&lt;span style="mso-fareast-language: EN-US;"&gt;&lt;span style="mso-list: Ignore;"&gt;&lt;span style="font-size: small;" size="3"&gt;2.&lt;/span&gt;&lt;span style="font: 7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin;"&gt;&lt;span style="font-size: small;" size="3"&gt;WHEN: defines when the method should be faulted, i.e. trigger conditions.&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp; &lt;/span&gt;A set of build-in conditions like TriggerOnEveryCall, TriggerNthCalls, TriggerCalledBy, etc. are supported. In addition, users can define their own conditions by implementing provided interface Icondition.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-justify: inter-ideograph; text-align: justify; text-indent: -0.25in; margin: auto auto auto 0.5in; mso-add-space: auto; mso-list: l1 level1 lfo1;" class="MsoListParagraphCxSpLast"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: Arial;"&gt;&lt;span style="mso-list: Ignore;"&gt;3.&lt;span style="font: 7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: small;" size="3"&gt;&lt;span style="font-family: Times New Roman;" face="Times New Roman"&gt;&lt;span style="mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin;"&gt;HOW: defines the behavior of faulted method, which can be either to throw a specified exception or to return a specified value. Users can define their own fault by implementing provided interface Ifault.&lt;/span&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt;"&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: 'Times New Roman','serif'; font-size: 12pt; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin;"&gt;I will show you how to use the API step by step in next section.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;b&gt;&lt;span style="font-size: 12pt; mso-fareast-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-fareast-language: EN-US; mso-ascii-font-family: Calibri; mso-hansi-font-family: Calibri;"&gt;&lt;span style="font-family: Calibri;" face="Calibri"&gt;Let&amp;rsquo;s get started&amp;hellip;.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: 'Times New Roman';"&gt;Step1: Prepare Application for testing (AUT)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: 'Times New Roman';"&gt;Assume the following is your application code that you want to test. The logic is simple and self-explanatory.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;using System;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;using System.IO;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;class SimpleExample&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;static int GetNumberOfProc()&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return Environment.ProcessorCount;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;static void CreateObjects()&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;if (GetNumberOfProc() == 1)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;//todo: business logic if the machine is single processor.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Console.WriteLine("Single Processor.");&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;else&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;//todo: business logic if the machine is multiple processors.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Console.WriteLine("Mulitple Processors.");&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;//todo: allocate a large memory to create objects&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;static void Main(string[] args)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;try&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;CreateObjects();&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Console.WriteLine("Sucessfully creates objects.");&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;catch (OutOfMemoryException ex)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;//todo: business logic if memory is low.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Console.WriteLine("the memory is low: " + ex.Message);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Console.WriteLine("Press any key to exit&amp;hellip;");&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Console.ReadLine();&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: 'Times New Roman';"&gt;Compile the code to aut.exe and run it. The output should be what your expecting.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: 'Times New Roman';"&gt;Step 2: Download TestAPI package.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: 'Times New Roman';"&gt;Go to codeplex website: &lt;a href="http://testapi.codeplex.com/Wikipage" mce_href="http://testapi.codeplex.com/Wikipage"&gt;http://testapi.codeplex.com/Wikipage&lt;/a&gt; to download and unpack to your local machine, for example: D:\tmp\TestApi_v0.4. As of now (3/30/2010), the latest version is v0.4.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: 'Times New Roman';"&gt;Step3: Write Test Code&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: 'Times New Roman';"&gt;Basically I want to test the business logics when the memory is low.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-indent: -0.25in; margin: auto 0in auto 0.5in; mso-list: l0 level1 lfo2;" class="MsoListParagraph"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: Arial;"&gt;&lt;span style="mso-list: Ignore;"&gt;1.&lt;span style="font: 7pt 'Times New Roman';"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt;"&gt;In Visual Studio, create a new console application. Add reference to TestApiCore.dll. I define the rule that every time the method &lt;/span&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;SimpleExample.CreateObjects &lt;/span&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt;"&gt;is called, it will throw outofmemory exception. The following is the test source code.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;using System;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;using Microsoft.Test.FaultInjection;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;namespace auttest&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;class Program&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;static void Main(string[] args)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;{&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;// &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;// Set up a fault rule to throw outofmemory exception&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;//&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;string method = "SimpleExample.CreateObjects()";&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ICondition condition = BuiltInConditions.TriggerOnEveryCall;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;IFault fault = BuiltInFaults.ThrowExceptionFault (new OutOfMemoryException ("fault inject test"));&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;FaultRule rule = new FaultRule(method, condition, fault);&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;//&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;// Establish a session, injecting the faults defined by the fault rule(s)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;//&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;FaultSession session = new FaultSession(rule);&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;ProcessStartInfo psi = session.GetProcessStartInfo(@".\aut.exe"); &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;//&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;// Launch the target application for testing&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;//&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;Process p = Process.Start(psi);&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;p.WaitForExit();&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;&lt;span style="mso-spacerun: yes;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: 9pt; margin: 0in 0in 0pt; mso-line-height-rule: exactly; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; color: blue; font-size: 9pt;"&gt;}&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 0pt; mso-layout-grid-align: none;" class="MsoNormal"&gt;&lt;span style="font-family: Consolas; font-size: 9.5pt;"&gt;&lt;o:p&gt;&amp;nbsp;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-indent: -0.25in; margin: auto 0in auto 0.5in; mso-list: l0 level1 lfo2; mso-layout-grid-align: none;" class="MsoListParagraph"&gt;&lt;span style="font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Consolas;"&gt;&lt;span style="mso-list: Ignore;"&gt;2.&lt;span style="font: 7pt 'Times New Roman';"&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: 9.5pt;"&gt;Compile it into auttest.exe.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-indent: -0.25in; margin: auto 0in auto 0.5in; mso-list: l0 level1 lfo2; mso-layout-grid-align: none;" class="MsoListParagraph"&gt;&lt;span style="font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Consolas;"&gt;&lt;span style="mso-list: Ignore;"&gt;3.&lt;span style="font: 7pt 'Times New Roman';"&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: 9.5pt;"&gt;Copy FaultInjectionEngine folder from your unpacked folder to auttest.exe folder.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-indent: -0.25in; margin: auto 0in auto 0.5in; mso-list: l0 level1 lfo2; mso-layout-grid-align: none;" class="MsoListParagraph"&gt;&lt;span style="font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Consolas;"&gt;&lt;span style="mso-list: Ignore;"&gt;4.&lt;span style="font: 7pt 'Times New Roman';"&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: 9.5pt;"&gt;Run command line window under administrator privilege&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-indent: -0.25in; margin: auto 0in auto 0.5in; mso-list: l0 level1 lfo2; mso-layout-grid-align: none;" class="MsoListParagraph"&gt;&lt;span style="font-family: Consolas; font-size: 9.5pt; mso-fareast-font-family: Consolas;"&gt;&lt;span style="mso-list: Ignore;"&gt;5.&lt;span style="font: 7pt 'Times New Roman';"&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: 9.5pt;"&gt;Run auttest.exe, you can see aut.exe throw outofmemory exception.&lt;/span&gt;&lt;/p&gt;
&lt;p style="text-indent: -0.25in; margin: auto 0in auto 0.5in; mso-list: l0 level1 lfo2; mso-layout-grid-align: none;" class="MsoListParagraph"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: 'Times New Roman';"&gt;&lt;o:p&gt;6. &lt;/o:p&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: 9.5pt;"&gt;If you run aut.exe again, it will output the original output, which means the binary is not changed.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: 'Times New Roman';"&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: 'Times New Roman';"&gt;Congratulations! You got your first example works using managed fault injection API. Next time, I will show you a few more scenarios.... &lt;/span&gt;&lt;/p&gt;
&lt;p style="line-height: normal; margin: 0in 0in 10pt; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto;" class="MsoNormal"&gt;&lt;span style="font-family: 'Arial','sans-serif'; font-size: 10pt; mso-fareast-font-family: 'Times New Roman';"&gt;In this blog, I only touch base managed fault injection API, there are other very useful APIs for testing in the TestAPI package, check Ivo's blog (&lt;a href="http://blogs.msdn.com/ivo_manolov/archive/2009/10/14/9907447.aspx"&gt;http://blogs.msdn.com/ivo_manolov/archive/2009/10/14/9907447.aspx&lt;/a&gt;) for more details.&lt;/span&gt;&lt;/p&gt;
&lt;p style="margin: 0in 0in 10pt;" class="MsoNormal"&gt;&lt;o:p&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;&amp;nbsp;&lt;/span&gt;&lt;/o:p&gt;&lt;/p&gt;
&lt;p style="margin: 0in 0in 10pt;" class="MsoNormal"&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;----------------------------------------&lt;/p&gt;
&lt;p style="margin: 0in 0in 10pt;" class="MsoNormal"&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;关注我：新浪微博：@billliu_seattle &lt;a href="http://www.weibo.com/windowsazure"&gt;http://www.weibo.com/windowsazure&lt;/a&gt; 或twitter: @billliu_seattle&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style="margin: 0in 0in 10pt;" class="MsoNormal"&gt;&lt;span style="font-family: Calibri; font-size: small;" face="Calibri" size="3"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p mce_keep="true"&gt;&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9987749" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author><category term="Fault Injection" scheme="http://blogs.msdn.com/b/billliu/archive/tags/Fault+Injection/" /></entry><entry><title>Introduction</title><link rel="alternate" type="text/html" href="http://blogs.msdn.com/b/billliu/archive/2010/03/27/introduction.aspx" /><id>http://blogs.msdn.com/b/billliu/archive/2010/03/27/introduction.aspx</id><published>2010-03-27T18:41:00Z</published><updated>2010-03-27T18:41:00Z</updated><content type="html">Hi, Welcome to my blog! My name is Biao (Bill) Liu. I'm a Software Design Engineer in Test in Microsoft. I own the Managed Fault Injection Tool released as part of TestAPI&amp;nbsp;in codeplex (&lt;A href="http://testapi.codeplex.com/Wikipage" mce_href="http://testapi.codeplex.com/Wikipage"&gt;http://testapi.codeplex.com/Wikipage&lt;/A&gt;). So, I will mainly blog on this tool. I just transferred to a new team&amp;nbsp;working on Windows Azure Technology, so I will start to blog it too as I learn. stay tune...&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9986211" width="1" height="1"&gt;</content><author><name>billliu</name><uri>http://blogs.msdn.com/billliu/ProfileUrlRedirect.ashx</uri></author></entry></feed>