﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-秋阳的软件测试专栏</title><link>http://www.cnitblog.com/qiuyangzh/</link><description /><language>zh-cn</language><lastBuildDate>Wed, 29 Apr 2026 23:37:40 GMT</lastBuildDate><pubDate>Wed, 29 Apr 2026 23:37:40 GMT</pubDate><ttl>60</ttl><item><title>傲慢与偏见——‘任何人都可以做软件测试的工作’</title><link>http://www.cnitblog.com/qiuyangzh/archive/2010/12/15/72288.html</link><dc:creator>qiuyangzh</dc:creator><author>qiuyangzh</author><pubDate>Wed, 15 Dec 2010 05:02:00 GMT</pubDate><guid>http://www.cnitblog.com/qiuyangzh/archive/2010/12/15/72288.html</guid><wfw:comment>http://www.cnitblog.com/qiuyangzh/comments/72288.html</wfw:comment><comments>http://www.cnitblog.com/qiuyangzh/archive/2010/12/15/72288.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/qiuyangzh/comments/commentRss/72288.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/qiuyangzh/services/trackbacks/72288.html</trackback:ping><description><![CDATA[<p>&nbsp; &#8216;任何人都可以做软件测试的工作，就是点点鼠标，提提bug嘛&#8217;。哦，也熟悉，是吧？确实有不少人是这样认为的，甚至是带领一个技术团队的经理，他可能表面没这样说，但是行为却体现出这样的想法，这些人觉得软件测试没有什么技术含量，如果换做让开发工程师来测试，或者随便找几个员工，或者学校的学生，甚至拉过一个路人甲，都可以做测试工作。对，可以做，但是你想得到什么质量的工作成果呢？专业的测试人员得到的效果，和随机测试的效果之间差别非常大。那么测试的专业性体现在哪里？我认为主要有以下几点：<br>&nbsp; 1.不同的角度。在一个团队里，开发经理、需求人员、设计人员、编码人员，大家的思路，都是在考虑如何构建一个系统，但是，测试人员，对，只有测试人员，他们是在思考如何能够&#8216;破坏&#8217;系统。这是一个非常有价值的角度，只有在开发过程中这些可能遭受破坏的地方被发现，被修复，软件投入实际使用后，才会避免在客户的环境中发生这些失败的情况。所以，不同的角度是测试人员的一个重要的，也是团队中一个独特的价值所在，可能很多人没有意识到这一点。 <br>&nbsp; 2.广泛的覆盖。覆盖率是软件测试中的一个重要概念，我觉得可能仅次于前面提到的角度的重要性。测试人员会根据软件系统将来承诺运行的环境，硬件的、软件的、第三方的，以及功能方面的，性能方面的，安全性方面的等等需求，设计测试用例，验证软件是否能够如预期的正常应对。如果不是经过专门训练的工程师，测试覆盖的设计，肯定会有问题。<br>&nbsp; 3.系统集成的问题。有责任心的编码人员，会尽力确保自己负责的模块功能正确（当然这也只是主观的期望，实际上不出错是不可能的），但是如果涉及到自己模块与其他人模块之间的交互，往往就会出问题，这是由系统集成的特殊性决定的，主观认真会起作用，但问题还是要发生，而测试人员会比较容易的发现这类问题。<br>&nbsp; 4.质量文化的建立。测试工程师在团队中，有助于建立一种质量文化，使大家能够从反面思考一些问题。另外，包括全程测试、尽早测试的提倡，单元测试的指导，等等，对于提高软件质量都会发挥极大作用。</p>
<p>&nbsp; 软件测试人员，能看到整个系统的全貌，可能是对系统要做什么最了解的人，甚至比产品的负责人还要了解（我指的是广度上，具体特性的深度上往往会欠缺一些）。从测试团队那里，你能及时的得到一个系统当前状况的切片，对于防止项目失控，看清当前情况与目标的差距，是非常重要的的信息。</p>
<img src ="http://www.cnitblog.com/qiuyangzh/aggbug/72288.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/qiuyangzh/" target="_blank">qiuyangzh</a> 2010-12-15 13:02 <a href="http://www.cnitblog.com/qiuyangzh/archive/2010/12/15/72288.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>傲慢与偏见——‘软件是开发出来的，不是测试出来的’</title><link>http://www.cnitblog.com/qiuyangzh/archive/2010/12/12/72229.html</link><dc:creator>qiuyangzh</dc:creator><author>qiuyangzh</author><pubDate>Sun, 12 Dec 2010 14:49:00 GMT</pubDate><guid>http://www.cnitblog.com/qiuyangzh/archive/2010/12/12/72229.html</guid><wfw:comment>http://www.cnitblog.com/qiuyangzh/comments/72229.html</wfw:comment><comments>http://www.cnitblog.com/qiuyangzh/archive/2010/12/12/72229.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/qiuyangzh/comments/commentRss/72229.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/qiuyangzh/services/trackbacks/72229.html</trackback:ping><description><![CDATA[&nbsp; &#8216;软件是开发出来的，不是测试出来的&#8217;。我经常听到这个说法，这句话一般都包含着这样一个意思——测试工作本身不能提高软件质量。我对这个说法嗤之以鼻。如果测试工作不能提高软件质量，那么就没有必要进行这项工作。我想问：你认为什么能提高软件的质量呢——是贴合用户实际需要的需求？是清晰、简介的设计？是可靠、优美、简单的编码实现？还是覆盖全面、快速适应变化的测试？开发过程是一个整体，任何一个环节的给力，都会有助于提高软件的质量，使其向优秀软件的目标靠近。如果再听到诸如&#8216;测试并不能提高软件质量&#8217;这样的谬论，你作为一个关心对方的好人，应该给予彻底批驳。<br>&nbsp;&nbsp;&nbsp; 当然，测试人员对此也要有一个清醒的认识，就是测试人员发现的bug，以及提交的各类测试报告，提供了一种促进软件提高质量、改进软件开发过程的信息，但是具体的改进工作，是需要依赖整个团队来完成的，所以说，测试是一个发现者，是一盏探照灯，为产品成功照亮前进的路途，看清达到目标路上的各类障碍和险阻。
<img src ="http://www.cnitblog.com/qiuyangzh/aggbug/72229.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/qiuyangzh/" target="_blank">qiuyangzh</a> 2010-12-12 22:49 <a href="http://www.cnitblog.com/qiuyangzh/archive/2010/12/12/72229.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>楔子</title><link>http://www.cnitblog.com/qiuyangzh/archive/2010/12/12/72228.html</link><dc:creator>qiuyangzh</dc:creator><author>qiuyangzh</author><pubDate>Sun, 12 Dec 2010 14:37:00 GMT</pubDate><guid>http://www.cnitblog.com/qiuyangzh/archive/2010/12/12/72228.html</guid><wfw:comment>http://www.cnitblog.com/qiuyangzh/comments/72228.html</wfw:comment><comments>http://www.cnitblog.com/qiuyangzh/archive/2010/12/12/72228.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/qiuyangzh/comments/commentRss/72228.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/qiuyangzh/services/trackbacks/72228.html</trackback:ping><description><![CDATA[&nbsp; 最近又开始了一个招聘季，看到一些刚毕业的同学，或者第一次申请软件测试工作的朋友，递交了软件测试工作的申请，但是对这个职业还一无所知，或者存在一些误解，因此觉得有必要写一些关于软件测试这个职业的文章，供想从事软件测试这个职业的朋友们参考。
<img src ="http://www.cnitblog.com/qiuyangzh/aggbug/72228.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/qiuyangzh/" target="_blank">qiuyangzh</a> 2010-12-12 22:37 <a href="http://www.cnitblog.com/qiuyangzh/archive/2010/12/12/72228.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>爷爷，晚安！ </title><link>http://www.cnitblog.com/qiuyangzh/archive/2009/12/13/63137.html</link><dc:creator>qiuyangzh</dc:creator><author>qiuyangzh</author><pubDate>Sun, 13 Dec 2009 13:36:00 GMT</pubDate><guid>http://www.cnitblog.com/qiuyangzh/archive/2009/12/13/63137.html</guid><wfw:comment>http://www.cnitblog.com/qiuyangzh/comments/63137.html</wfw:comment><comments>http://www.cnitblog.com/qiuyangzh/archive/2009/12/13/63137.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cnitblog.com/qiuyangzh/comments/commentRss/63137.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/qiuyangzh/services/trackbacks/63137.html</trackback:ping><description><![CDATA[&nbsp; 今天晚上，很想爷爷。<br>&nbsp; 那天夜里，爸爸打来电话，告诉我爷爷走了。<br>&nbsp; 爷爷去年春节的时候病危过一次，经过治疗出院回家过了年。没想到不到一年，还是走了。<br>&nbsp; 几个月前爷爷住进医院。治疗的过程很痛苦。我清楚的记得医生治疗时，我按住爷爷身体的情景。爷爷疼的大喊，最后对我说：让爷爷走吧。现在想起来心里还是会痛。爷爷如果不是疼的无法忍受，不会在他的孙子面前这样的表现。有一次,治疗结束已经是深夜，我一人开车到城外，在路边待了半天。痛苦，无奈，复杂的感觉。回家后很久不能入睡，感觉能做得太有限了。<br>&nbsp; 医生最后建议出院回家调养，这只是婉转的说法。出院后爸爸陪在爷爷身边，直到那天打电话告诉我爷爷走了。从小到大，爸爸在我的印象中是个有主见的人，遇到问题总有办法，但从去年爷爷病危以来，常能看到他的无奈和痛苦，明显感觉到爸爸老了。<br>&nbsp; 接到电话后，开车往老家赶。进屋，看到爷爷躺在堂屋里，身上盖着白布单子，手已经冰凉。身上穿的是几年前做好的装老衣服，脚上穿的是千层底的布鞋，奶奶说，穿上这种鞋，走多远的路也不累。回家的路上我一直想哭，到家看到爷爷，却反而哭不出来。<br>&nbsp; 天快亮的时候，殡仪馆的车来了。为爷爷戴上帽子，放进棺椁，抬到车上，整个过程什么想法也没有，只是一步一步的做。<br>&nbsp; 殡仪馆火化，墓地下葬，从墓地往回走的时候，眼泪控制不住，不断地往出涌，爷爷是真的离开了。<br>&nbsp; 小的时候在乡下生活，爷爷很少多我发火。有一年，菜园里的玉米还没熟，隔壁菜园的熟了，我掰了几根拿回家煮着吃。爷爷看到拿回的玉米，问哪来的，告诉爷爷后，爷爷让我拿上玉米还给隔壁菜园的邻居，我觉得非常羞愧，不敢去，最后还是被爷爷逼着去了。<br>&nbsp; 爷爷走已经过去一段时间，现在有时在外面看到什么吃的东西，经常冒出的想法还是，这个东西我爷爷应该会喜欢吃，然后反应过来，爷爷已经不在了。<br>&nbsp; 人生是一段旅程，爷爷和我走了三十年。现在，我继续我的旅程，爷爷则开始了他新的一段旅程。再过2个月，我的孩子就要出生了。相聚，离开，不断上演的主题。正因为有离开的时刻，所以我们才会思考相聚的时候应该怎样度过。珍惜旅途中遇到的人，好好地生活，好好地存在。<br>&nbsp; 爷爷，谢谢您曾经给我的爱！<br>&nbsp; 爷爷，晚安！&nbsp;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 永远爱您的孙儿 
<img src ="http://www.cnitblog.com/qiuyangzh/aggbug/63137.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/qiuyangzh/" target="_blank">qiuyangzh</a> 2009-12-13 21:36 <a href="http://www.cnitblog.com/qiuyangzh/archive/2009/12/13/63137.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于‘软件开发者面试百问’</title><link>http://www.cnitblog.com/qiuyangzh/archive/2009/02/05/54277.html</link><dc:creator>qiuyangzh</dc:creator><author>qiuyangzh</author><pubDate>Thu, 05 Feb 2009 05:17:00 GMT</pubDate><guid>http://www.cnitblog.com/qiuyangzh/archive/2009/02/05/54277.html</guid><wfw:comment>http://www.cnitblog.com/qiuyangzh/comments/54277.html</wfw:comment><comments>http://www.cnitblog.com/qiuyangzh/archive/2009/02/05/54277.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cnitblog.com/qiuyangzh/comments/commentRss/54277.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/qiuyangzh/services/trackbacks/54277.html</trackback:ping><description><![CDATA[今天看到同事转发的&#8216;软件开发者面试百问&#8217;，里面的一些问题放在非面试的场合，思考一下也很有意思。<br>下面是ZT的中文版，关于测试的几个问题，按照我的理解写了一些，放在了后面。<br>-----------------------------------------------------------------------------------------------<br><br>1月13日，著名博客作者<a title="Jurgen Appelo" href="http://www.noop.nl/"><u><font color=#0000ff>Jurgen Appelo</font></u></a>写了一篇博文：&#8220;<a title=软件开发者面试百问 href="http://www.noop.nl/2009/01/100-interview-questions-for-software-developers.html"><u><font color=#800080>软件开发者面试百问</font></u></a>&#8221;。该文甚受读者欢迎，15日便登上了delicious，Popurls.com，Reddit的首页，这也是我见过考察范围最广的一个面试题集合。
<p>原文见：<a title=软件开发者面试百问 href="http://www.noop.nl/2009/01/100-interview-questions-for-software-developers.html"><u><font color=#800080>100 Interview Questions for Software Developers</font></u></a>。<br><br></p>
<p><strong>想雇到搞软件开发的聪明人可不容易</strong>。万一一不小心，就会搞到一堆低能大狒狒。我去年就碰到这种事了。你肯定不想这样吧。听我的，没错。在树上开站立会议门都没有。</p>
<p><strong>问点有难度的问题</strong>能帮你把聪明人跟狒狒们分开。我决定把我自己整理出来的<strong>软件开发者面试百问</strong>发出来，希望能帮到你们的忙。</p>
<p>这个列表涵盖了<a href="http://en.wikipedia.org/wiki/SWEBOK" target=_blank>软件工程知识体系</a>中定义的大多数知识域。当然，如果你只想找出类拔萃的程序员，便只需涉及结构、算法、数据结构、测试这几个话题。如果想雇架构师，也可以只考虑需求、功能设计、技术设计这些地方。</p>
<p>不过不管你怎么做，都要牢记一点：</p>
<p><strong>这里大多数问题的答案都没有对错之分！</strong></p>
<p><strong>你可以把我的这些问题作为引子，展开讨论。</strong>例如下面有个问题是使用静态方法或是单例的缘由。如果那个面试的就此展开长篇大论，那他很有可能是个聪明能干的家伙！如果他一脸茫然的看着你，发出<a href="http://simplythebest.net/sounds/WAV/sound_effects_WAV/sound_effect_WAV_files/mandrill.wav">这种声音</a>，很明显这就是只狒狒了。同样，想知道一个数是不是2的乘方也有很多方法，不过要是面试的人想用mod运算符，嗯&#8230;&#8230;你知道我的意思吧。（你不知道也没关系，来根香蕉？）<strong>需求</strong></p>
<ol>
    <li><strong>你能给出一些非功能性（或者质量）需求的例子么？ </strong>
    <li><strong>如果客户需要高性能、使用极其方便而又高度安全，你会给他什么建议？ </strong>
    <li><strong>你能给出一些用来描述需求的不同技术么？它们各自适用于什么场景？ </strong>
    <li><strong>需求跟踪是什么意思？什么是向前追溯，什么是向后追溯？ </strong>
    <li><strong>你喜欢用什么工具跟踪需求？ </strong>
    <li><strong>你怎么看待需求变化？它是好是坏？给出你的理由。 </strong>
    <li><strong>你怎样研究需求，发现需求？有哪些资源可以用到？ </strong>
    <li><strong>你怎么给需求制定优先级？有哪些技术？ </strong>
    <li><strong>在需求过程中，用户、客户、开发人员各自的职责是什么？ </strong>
    <li><strong>你怎么对待不完整或是令人费解的需求？ </strong></li>
</ol>
<p><strong>功能设计</strong></p>
<ol>
    <li><strong>在功能设计中有哪些隐喻？给出几个成功的例子。 </strong>
    <li><strong>如果有些功能的执行时间很长，怎么能让用户感觉不到太长的等待？ </strong>
    <li><strong>如果用户必须要在一个很小的区域内，从一个常常的列表中选择多个条目，你会用什么控件？ </strong>
    <li><strong>有哪些方法可以保证数据项的完整？ </strong>
    <li><strong>建立系统原型有哪些技术？ </strong>
    <li><strong>应用程序怎样建立对用户行为的预期？给出一些例子。 </strong>
    <li><strong>如何入手设计一组数量庞大而又复杂的特性，你能举出一些设计思路吗？ </strong>
    <li><strong>有一个列表，其中有10个元素，每个元素都有20个字段可以编辑，你怎样设计这种情况？如果是1000个元素，每个元素有3个字段呢？ </strong>
    <li><strong>用不同的颜色对一段文本中的文字标记高亮，这种做法有什么问题？ </strong>
    <li><strong>Web环境和Windows环境各有些什么限制？ </strong></li>
</ol>
<p><strong>技术设计</strong></p>
<ol>
    <li><strong>什么是低耦合和高聚合？封装原则又是什么意思？ </strong>
    <li><strong>在Web应用中，你怎样避免几个人编辑同一段数据所造成的冲突？ </strong>
    <li><strong>你知道设计模式吗？你用过哪些设计模式？在什么场合下用的？ </strong>
    <li><strong>是否了解什么是无状态的业务层？长事务如何与之相适应？ </strong>
    <li><strong>在搭建一个架构，或是技术设计时，你用过几种图？ </strong>
    <li><strong>在N层架构中都有哪些层？它们各自的职责是什么？ </strong>
    <li><strong>有哪些方法可以确保架构中数据的正确和健壮？ </strong>
    <li><strong>面向对象设计和面向组件设计有哪些不同之处？ </strong>
    <li><strong>怎样在数据库中对用户授权、用户配置、权限管理这几项功能建模？ </strong>
    <li><strong>怎样按照等级制度给动物王国（包括各种物种和各自的行为）建模？ </strong></li>
</ol>
<p><strong>程序设计</strong></p>
<ol>
    <li><strong>你怎样保证你的代码可以处理各种错误事件？ </strong>
    <li><strong>解释一下什么是测试驱动开发，举出极限编程中的一些原则。 </strong>
    <li><strong>看别人代码的时候，你最关心什么地方？ </strong>
    <li><strong>什么时候使用抽象类，什么时候使用接口？ </strong>
    <li><strong>除了IDE以外，你还喜欢哪些必不可少的工具？ </strong>
    <li><strong>你怎么保证代码执行速度快，而又不出问题？ </strong>
    <li><strong>什么时候用多态，什么时候用委派？ </strong>
    <li><strong>什么时候使用带有静态成员的类，什么时候使用单例？ </strong>
    <li><strong>你在代码里面怎么提前处理需求的变化？给一些例子。 </strong>
    <li><strong>描述一下实现一段代码的过程，从需求到最终交付。 </strong></li>
</ol>
<p><strong>算法</strong></p>
<ol>
    <li><strong>怎样知道一个数字是不是2的乘方？怎样判断一个数是不是奇数？ </strong>
    <li><strong>怎样找出链表中间的元素？ </strong>
    <li><strong>怎样改变10,000个静态HTML页面中所有电话号码的格式？ </strong>
    <li><strong>举出一个你所用过的递归的例子。 </strong>
    <li><strong>在散列表和排序后的列表中找一个元素，哪个查找速度最快？ </strong>
    <li><strong>不管是书、杂志还是网络，你从中所学到的最后一点算法知识是什么？ </strong>
    <li><strong>怎样把字符串反转？你能不用临时的字符串么？ </strong>
    <li><strong>你愿意用什么类型的语言来编写复杂的算法？ </strong>
    <li><strong>有一个数组，里面是从1到1,000,000的整数，其中有一个数字出现了两次，你怎么找出那个重复的数字？ </strong>
    <li><strong>你知道&#8220;旅行商问题（Traveling Salesman Problem）&#8221;么？ </strong></li>
</ol>
<p><strong>数据结构</strong></p>
<ol>
    <li><strong>怎样在内存中实现伦敦地铁的结构？ </strong>
    <li><strong>怎样以最有效的方式在数据库中存储颜色值？ </strong>
    <li><strong>队列和堆栈区别是什么？ </strong>
    <li><strong>用堆或者栈存储数据的区别是什么？ </strong>
    <li><strong>怎样在数据库中存储N维向量？ </strong>
    <li><strong>你倾向于用哪种类型的语言编写复杂的数据结构？ </strong>
    <li><strong>21的二进制值是什么？十六制值呢？ </strong>
    <li><strong>不管是书、杂志还是网络，你从中所学到的最后一点数据结构的知识是什么？ </strong>
    <li><strong>怎样在XML文档中存储足球比赛结果（包括队伍和比分）？ </strong>
    <li><strong>有哪些文本格式可以保存Unicode字符？ </strong></li>
</ol>
<p><strong>测试</strong></p>
<ol>
    <li><strong>什么是回归测试？怎样知道新引入的变化没有给现有的功能造成破坏？ </strong>
    <li><strong>如果业务层和数据层之间有依赖关系，你该怎么写单元测试？ </strong>
    <li><strong>你用哪些工具测试代码质量？ </strong>
    <li><strong>在产品部署之后，你最常碰到的是什么类型的问题？ </strong>
    <li><strong>什么是代码覆盖率？有多少种代码覆盖率？ </strong>
    <li><strong>功能测试和探索性测试的区别是什么？你怎么对网站进行测试？ </strong>
    <li><strong>测试套件、测试用例、测试计划，这三者之间的区别是什么？你怎么组织测试？ </strong>
    <li><strong>要对电子商务网站做冒烟测试，你会做哪些类型的测试？ </strong>
    <li><strong>客户在验收测试中会发现不满意的东西，怎样减少这种情况的发生？ </strong>
    <li><strong>你去年在测试和质量保证方面学到了哪些东西？ </strong></li>
</ol>
<p><strong>维护</strong></p>
<ol>
    <li><strong>你用哪些工具在维护阶段对产品进行监控？ </strong>
    <li><strong>要想对一个正在产品环境中被使用的产品进行升级，该注意哪些重要事项？ </strong>
    <li><strong>如果在一个庞大的文件中有错误，而代码又无法逐步跟踪，你怎么找出错误？ </strong>
    <li><strong>你怎样保证代码中的变化不会影响产品的其他部分？ </strong>
    <li><strong>你怎样为产品编写技术文档？ </strong>
    <li><strong>你用过哪些方式保证软件产品容易维护？ </strong>
    <li><strong>怎样在产品运行的环境中进行系统调试？ </strong>
    <li><strong>什么是负载均衡？负载均衡的方式有哪些种？ </strong>
    <li><strong>为什么在应用程序的生命周期中，软件维护费用所占的份额最高？ </strong>
    <li><strong>再造工程（re-engineering）和逆向工程（reverse engineering）的区别是什么？ </strong></li>
</ol>
<p><strong>配置管理</strong></p>
<ol>
    <li><strong>你知道配置管理中基线的含义么？怎样把项目中某个重要的时刻冻结？ </strong>
    <li><strong>你一般会把哪些东西纳入版本控制？ </strong>
    <li><strong>怎样可以保证团队中每个人都知道谁改变了哪些东西？ </strong>
    <li><strong>Tag和Branch的区别是什么？在什么情况下该使用tag，什么时候用branch？ </strong>
    <li><strong>怎样管理技术文档——如产品架构文档——的变化？ </strong>
    <li><strong>你用什么工具管理项目中所有数字信息的状态？你最喜欢哪种工具？ </strong>
    <li><strong>如果客户想要对一款已经发布的产品做出变动，你怎么处理？ </strong>
    <li><strong>版本管理和发布管理有什么差异？ </strong>
    <li><strong>对文本文件的变化和二进制文件的变化进行管理，这二者有什么不同？ </strong>
    <li><strong>同时处理多个变更请求，或是同时进行增量开发和维护，这种事情你怎么看待？ </strong></li>
</ol>
<p><strong>项目管理</strong></p>
<ol>
    <li><strong>范围、时间、成本，这三项中哪些是可以由客户控制的？ </strong>
    <li><strong>谁该对项目中所要付出的一切做出估算？谁有权设置最后期限？ </strong>
    <li><strong>减少交付的次数，或是减少每个每个交付中的工作量，你喜欢哪种做法？ </strong>
    <li><strong>你喜欢用哪种图来跟踪项目进度？ </strong>
    <li><strong>迭代和增量的区别在哪里？ </strong>
    <li><strong>试着解释一下风险管理中用到的实践。风险该如何管理？ </strong>
    <li><strong>你喜欢任务分解还是滚动式计划？ </strong>
    <li><strong>你需要哪些东西帮助你判断项目是否符合时间要求，在预算范围内运作？ </strong>
    <li><strong>DSDM、Prince2、Scrum，这三者之间有哪些区别？ </strong>
    <li><strong>如果客户想要的东西太多，你在范围和时间上怎样跟他达成一致呢？ </strong></li>
</ol>
<p><br><span style="FONT-SIZE: 18pt">对于上面的有些问题，我只想说：给我一只香蕉吧<br>因为对软件测试部分有一些了解，谈一谈自己的看法</span><br><br><span style="COLOR: #003366"><strong>测试<br></strong></span></p>
<strong><font face=宋体>
<p style="COLOR: #003366"><br>什么是回归测试？怎样知道新引入的变化没有给现有的功能造成破坏？<br>&gt;<br>产品修正了bug或增加了功能，生成新的版本，对这个版本进行测试，就叫做回归测试。<br>保证变化没有对产品原有功能造成破坏，最可靠的方式是对产品进行全面的测试。还有一个方法是只对修改部分的相关部分进行测试，这是一种折中的方法，因为进度、成本的原因，这也是经常被采用的方法，这个方法有一定的风险，因为准确的确定产品修改部分的相关部分往往很有难度，范围不好确定。<br>具体采用哪种回归方式，要由这个产品的质量要求、人力资源、时间进度等因素来决定。<br>&nbsp;</p>
<p style="COLOR: #003366">如果业务层和数据层之间有依赖关系，你该怎么写单元测试？ <br>&gt;<br>如果有了数据层的实现，就没什么问题了。提出这个问题，主要是在数据层没有实现的情况下，如何对业务层的代码进行单元测试？<br>这个时候我们需要模拟数据层，给业务层提供数据，比如简单的返回各类数据，直接从文本文件、数据库中读取我们需要的测试数据等来完成单元测试。</p>
<p style="COLOR: #003366"><br>你用哪些工具测试代码质量？ <br>&gt;<br>针对代码的测试工具有很多，一般分2大类，是从执行测试的方式上分的，一是静态分析类，一是动态测试类。<br>静态分析类，特点就是不需要执行代码。象logiscope、C++ Test、LINT就属于这一类，主要是检测代码的编写规范，分析代码的复杂度、可能存在的隐患等等。这类工具在对可靠性要求较高的软件领域使用较多，比如航空航天。我们平时做的代码评审，就是在人工做这类工作。<br>动态测试类，主要是发现代码中诸如内存泄露、数据访问越界等这类错误，比如Compuware DevPartner、Rational PurifyPlus、valgrind这类工具。这类测试工具，要求测试代码必须运行起来，只有执行到的代码，存在问题才会被发现。没有执行到的代码即使存在问题也不能被发现。所以使用这类测试，一是靠工具，二是靠你制造的测试输入，如果测试输入不够丰富，很多bug是发现不了的。<br>还有一个很特别的工具PolySpacee，它打乱了上面的这个分类，它是采用静态的方式，却能够发现动态错误，即不需要制定和执行测试用例，只是静态扫描代码，就能够发现内存泄露这类问题。我是从一个好朋友那里了解到的，但没具体使用过，细节不是很了解。<br>象XUnit、覆盖率测试工具这类在代码测试中也会经常用到，但它们属于辅助性工具，本身不能对代码进行什么测试。</p>
<p style="COLOR: #003366"><br>在产品部署之后，你最常碰到的是什么类型的问题？<br>&gt;<br>产品发布后，特殊数据、特殊测试环境导致的问题比较多。易用性上，因为对用户的使用习惯不了解，可能会有有问题反馈。包括性能，因为对用户的实际使用规模估计不足，也可能导致问题。</p>
<p style="COLOR: #003366"><br>什么是代码覆盖率？有多少种代码覆盖率？ <br>&gt;<br>代码覆盖率是单元测试里的概念，指测试结束后，被执行的代码或路径数量占总代码或路径数量的百分比。<br>语句覆盖、分支覆盖、路径覆盖是常见的几种覆盖率方式。<br>统计代码的覆盖率，一般都需要使用测试工具，人工很难做这项工作。</p>
<p style="COLOR: #003366"><br>功能测试和探索性测试的区别是什么？你怎么对网站进行测试？ <br>&gt;<br>功能测试，需要依照事前制定好的测试用例来执行测试。<br>探索性测试，不会事前制定测试用例，是在测试中边设计边执行。其实在功能测试中也有探索性测试的使用，因为测试用例不可能细化到每个细节，测试人员在执行时肯定会做一些探索性测试。探索性测试一般在测试初期对产品不了解时，或者到了后期在现有测试用例基础上发布不了bug时使用。还有在安全性测试中，探索性测试肯定要经常被用到。<br>怎么对网站进行测试？不知道为什么要放到这个问题里来。网站除了一般性的功能测试外，性能、安全性测试也是必须要进行的测试内容。类似安装卸载、升级这类产品测试中关注的内容，网站测试就不需要关注了。</p>
<p style="COLOR: #003366"><br>测试套件、测试用例、测试计划，这三者之间的区别是什么？你怎么组织测试？ <br>&gt;<br>先从大的说。<br>测试计划是指导整个测试过程的一份概述文档，包括测试范围、测试策略、人力物力资源、时间进度、风险分析等内容。<br>测试套件，是测试用例的一个大的分类，按照逻辑，或者说按照测试组的理解把测试用例划分成不同的部分，每个部分就是一个test suite。<br>测试用例，最底层的测试产品，实际覆盖产品各个功能点、非功能点的测试。如果用过XUnit工具，应该对test suite、test case这样的划分不陌生。</p>
<p style="COLOR: #003366"><br>要对电子商务网站做冒烟测试，你会做哪些类型的测试？ <br>&gt;<br>冒烟测试，主要目的是通过执行较少或较简单的测试用例，验证产品基本功能是否正常。如果这个测试都没有通过，就没有必要投入人力进行后续的测试工作了。<br>对电子商务网站理解的不多，如果是我对电子商务网站进行冒烟测试的话，我会执行：用户注册，登陆，检索，挑选商品、购买、付账这些测试，每类只做一项基本测试。另外保证每个链接都是有效的。</p>
<p style="COLOR: #003366"><br>客户在验收测试中会发现不满意的东西，怎样减少这种情况的发生？ <br>&gt;<br>可能比较多的情况是：有些功能实现不是用户想要的；不满足特殊的行业要求；性能没达到用户的要求；使用习惯、易用性不符合用户要求等等这类。比较好的方式是渐近的给用户提供产品，让用户能在产品的不同开发阶段介入，提出意见，每个阶段都进行相应的测试。如果用户能作为开发测试组的一员，那就更好了。</font></strong></p>
<img src ="http://www.cnitblog.com/qiuyangzh/aggbug/54277.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/qiuyangzh/" target="_blank">qiuyangzh</a> 2009-02-05 13:17 <a href="http://www.cnitblog.com/qiuyangzh/archive/2009/02/05/54277.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>valgrind</title><link>http://www.cnitblog.com/qiuyangzh/archive/2007/04/27/26292.html</link><dc:creator>qiuyangzh</dc:creator><author>qiuyangzh</author><pubDate>Fri, 27 Apr 2007 09:44:00 GMT</pubDate><guid>http://www.cnitblog.com/qiuyangzh/archive/2007/04/27/26292.html</guid><wfw:comment>http://www.cnitblog.com/qiuyangzh/comments/26292.html</wfw:comment><comments>http://www.cnitblog.com/qiuyangzh/archive/2007/04/27/26292.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/qiuyangzh/comments/commentRss/26292.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/qiuyangzh/services/trackbacks/26292.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;这段时间我的团队在对一个产品进行稳定性测试，让程序在Purify下运行，结果Purify最后出现了错误。同事告诉我有一款工具——valgrind，可以定位程序内存方面的错误，于是下载下来，运行测试，效果很好，这个工具运行稳定，给出的结果也很清晰。<br>&nbsp;&nbsp;&nbsp; valgrind这款工具是运行在linux下的，可以用来定位c/c++程序中内存使用方面的错误。包括：内存泄漏、使用未初始化的内存、读/写已释放的内存、读/写内存越界、使用malloc/new/new[]和free/delete/delete[]不匹配，等等。<br>&nbsp;&nbsp;&nbsp; valgrind官方网站：<a href="http://valgrind.org/"><u><font color=#800080>http://valgrind.org/</font></u></a>，是一款open source软件。我下载的时候最新版是3.2.3。安装过程很简单——configure，make，make install，安装后不需要任何设置，直接可以开始使用。<br>&nbsp;&nbsp;&nbsp; valgrind运行方法很简单:valgrind --leak-check=full --track-fds=yes 程序 参数<br>&nbsp; 这样你的程序就会在valgrind监控下运行了，结果会直接输出到屏幕上。如果想把结果输出到日志文件（通常也需要这样），用如下的命令：valgrind --log-file=valgrind_log --leak-check=full --track-fds=yes 程序 参数<br>&nbsp; 感谢这款工具的开发者——<font size=2>Jonathan Riddell 。也</font><font size=3>感谢我的同事肖锋，让我知道有这样一款工具</font><font size=2><a href="http://valgrind.org/" target=_blank>。<img border=0 src="http://www.cnitblog.com/images/cnitblog_com/qiuyangzh/snap.jpg"></a></font></p>
<p>*valgrind网站上的，骑士战恶龙</p>
<p><br>PS：说起Run-time错误定位工具，我最初使用的是Boundchecker，那还是在Visual c++ 6.0的时代，那款工具确实很好用，功能、性能都不错，但后来不知道Compuware公司出了什么问题，对这款工具的改进很少，到了MS .net出来以后，我试用过Boundchecker针对.net的版本，性能很差。后来是否再有更新我就不清楚了，因为再也没有使用过Compuware的产品。Purify是现在的公司使用的Run-time错误定位工具，使用方法和Boundchecker非常类似（2002年的时候Compuware指控IBM错误分析器产品中使用自己拥有版权的代码，就是这款产品），也许是因为曾经使用过Boundchecker先入为主的原因，对这款工具始终感觉不是很好，在这次测试过程中，Purify自己竟然宕了。使用过valgrind后，我查了关于它的一些资料，对这款工具评价很好。遇到相同需求的朋友，可以试一下valgrind这款工具，相信不会让你失望！</p>
<img src ="http://www.cnitblog.com/qiuyangzh/aggbug/26292.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/qiuyangzh/" target="_blank">qiuyangzh</a> 2007-04-27 17:44 <a href="http://www.cnitblog.com/qiuyangzh/archive/2007/04/27/26292.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何通过LoadRunner监控Linux和Unix操作系统的资源状况</title><link>http://www.cnitblog.com/qiuyangzh/archive/2006/11/27/19626.html</link><dc:creator>qiuyangzh</dc:creator><author>qiuyangzh</author><pubDate>Mon, 27 Nov 2006 04:02:00 GMT</pubDate><guid>http://www.cnitblog.com/qiuyangzh/archive/2006/11/27/19626.html</guid><wfw:comment>http://www.cnitblog.com/qiuyangzh/comments/19626.html</wfw:comment><comments>http://www.cnitblog.com/qiuyangzh/archive/2006/11/27/19626.html#Feedback</comments><slash:comments>12</slash:comments><wfw:commentRss>http://www.cnitblog.com/qiuyangzh/comments/commentRss/19626.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/qiuyangzh/services/trackbacks/19626.html</trackback:ping><description><![CDATA[
		<div class="wiki-content">
				<p>  我们在使用LR进行性能测试的时候，经常有需要监控OS的资源使用情况的需求。对于Windows系统，这个工作进行起来很方便，直接在LR的资源监控窗口中添加需要被监控的机器名或IP即可，但对于Linux/Unix系统，则要稍微复杂一些，我在这里简单介绍一下如何在LR中监控Linux/Unix系统的资源使用情况：<br /><b><br />  Linux</b></p>
				<p>  对于Linux系统，要想通过LR监控Linux/Unix系统的资源使用情况，需要运行rstatd服务。如果OS没有安装rstatd（可以查找一下系统中是否存在rpc.rstatd这个文件，如果没有，则说明系统没有安装rstatd），则需要进行安装。rstatd安装步骤如下：</p>
				<p>  获得rstatd的安装介质（rstatd.tar.gz）。rstatd可以从redhat的安装CD中获得，或者从网站上下载（给出一个下载地址，sourceforge的：http://heanet.dl.sourceforge.net/sourceforge/rstatd）。</p>
				<p>  将rstatd.tar.gz拷贝到Linux系统中，解压，赋予可执行权限，进入rpc.rstatd目录，依次执行如下命令：<br />      #./configure<br />      #make<br />      #make install <br />  结束后，运行./rpc.rstatd命令，启动服务。这个时候，你就可以在LR中监控Linux资源了。<br /><b><br />  Unix</b></p>
				<p>对于Unix系统，比如Solaris，AIX或者HP UX等，它们的配置过程比较简单——在inetd.conf（在/etc目录下）文件中去掉rstatd前面的注释，然后启动rstatd服务即可。 </p>
		</div>
		<!--
    Root decorator: all decisions about how a page is to be decorated via the
                    inline decoration begins here.
-->
		<!--
    Switch based upon the context. However, for now, just delegate to a decorator
    identified directly by the context.
-->
<img src ="http://www.cnitblog.com/qiuyangzh/aggbug/19626.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/qiuyangzh/" target="_blank">qiuyangzh</a> 2006-11-27 12:02 <a href="http://www.cnitblog.com/qiuyangzh/archive/2006/11/27/19626.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>性能测试总结</title><link>http://www.cnitblog.com/qiuyangzh/archive/2006/11/09/19003.html</link><dc:creator>qiuyangzh</dc:creator><author>qiuyangzh</author><pubDate>Thu, 09 Nov 2006 06:14:00 GMT</pubDate><guid>http://www.cnitblog.com/qiuyangzh/archive/2006/11/09/19003.html</guid><wfw:comment>http://www.cnitblog.com/qiuyangzh/comments/19003.html</wfw:comment><comments>http://www.cnitblog.com/qiuyangzh/archive/2006/11/09/19003.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/qiuyangzh/comments/commentRss/19003.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/qiuyangzh/services/trackbacks/19003.html</trackback:ping><description><![CDATA[<h1><span style="FONT-FAMILY: 黑体">性能测试总结</span> </h1>
<h2 style="TEXT-INDENT: 0cm"><span style="FONT-FAMILY: 宋体">概述</span> </h2>
<p style="TEXT-INDENT: 24pt" class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">对于目前以</span> <span lang=EN-US>B/S</span> <span style="FONT-FAMILY: 宋体">结构为主的产品来说，性能是一项必测的内容。</span> </p>
<p style="TEXT-INDENT: 24pt" class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">关于性能方面的测试，在很多地方又被细分为：负载测试、强度测试、容量测试、压力测试等等。这种细分在概念描述上有一些用处，但在实际工作中很少会只单独的进行其中的某一项测试，实际测试基本上都是交叉性的。我们这里把所有与性能相关的测试统称为性能测试，不做具体区别。</span> </p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">&nbsp; 我们在这里所说的性能测试，指的是对系统整体性能的测试，不涉及单元模块的性能检测。</span> </p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">&nbsp; 我们在这里讨论的内容主要是基于</span> <span lang=EN-US>B/S</span> <span style="FONT-FAMILY: 宋体">架构的应用。</span> </p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">&nbsp; 要讨论性能测试，很难不涉及测试工具，我们在这里以</span> <span lang=EN-US>MI</span> <span style="FONT-FAMILY: 宋体">公司的</span> <span lang=EN-US>LoadRunner</span> <span style="FONT-FAMILY: 宋体">为默认的测试工具。</span> </p>
<h2 style="TEXT-INDENT: 0cm"><span style="FONT-FAMILY: 宋体">性能测试的介入时机</span> </h2>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">性能测试应该在什么时候开始？对测试人员来说，在产品的功能稳定下来后，就应该尽早开始对产品进行性能测试。一般建议在产品的</span> <span lang=EN-US>3</span> <span style="FONT-FAMILY: 宋体">轮完整功能测试后开始。</span> </p>
<h2 style="TEXT-INDENT: 0cm"><span style="FONT-FAMILY: 宋体">测试过程</span> </h2>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">性能测试的整体测试过程如下：</span> </p>
<h3 style="MARGIN-LEFT: 0cm">&nbsp;&nbsp;&nbsp; <span lang=EN-US>1.3.1<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="FONT-FAMILY: 宋体">制定性能测试计划</span></h3>
<h3 style="MARGIN-LEFT: 0cm">&nbsp;&nbsp;&nbsp; <span lang=EN-US>1.3.2<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">搭建测试环境</span></h3>
<h3 style="MARGIN-LEFT: 0cm">&nbsp;&nbsp;&nbsp; <span lang=EN-US>1.3.3<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">编写测试程序</span><span lang=EN-US>/</span><span style="FONT-FAMILY: 宋体">脚本</span></h3>
<h3 style="MARGIN-LEFT: 0cm">&nbsp;&nbsp;&nbsp; <span lang=EN-US>1.3.4<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">测试执行和分析</span></h3>
<h3 style="MARGIN-LEFT: 0cm">&nbsp;&nbsp; &nbsp;<span lang=EN-US>1.3.5<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">编写测试报告，结束测试</span></h3>
<h2 style="TEXT-INDENT: 0cm"><span lang=EN-US>1.4<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">过程说明</span> </h2>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">各个子过程的具体说明：</span> </p>
<h3 style="MARGIN-LEFT: 0cm"><span lang=EN-US>1.4.1<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">制定性能测试计划</span> </h3>
<p style="TEXT-INDENT: 15pt" class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">分析被测试系统的情况，收集性能测试需求。制定测试计划，形成文档。测试计划应考虑以下内容：</span> </p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">&nbsp; 测试对象和场景。即我们要测试的内容是什么。系统最后对外提供的功能有很多，我们不可能也没有必要对系统所有的功能点都进行性能测试。挑选性能测试对象的一般原则是：选取那些在系统实际投入使用后，并发访问量较大的、算法比较复杂的、占用系统资源较多的功能点，也就是压力点。设定好要测试的压力点后，需要详细的描述出具体的操作过程，以及预期应该达到的性能指标。</span> </p>
<p style="LINE-HEIGHT: normal; TEXT-INDENT: 23.65pt" class=MsoNormalIndent><em><span style="FONT-FAMILY: 宋体; FONT-SIZE: 10.5pt">注：在制定测试计划时，对于系统预期应该达到的性能指标，常常是不能获得一个准确的数字。但即使是在没有任何参考数据的情况下，也应该和开发人员一起，设定一个初步的性能指标，作为后面测试的一个参照。有一个初步指标，也比没有任何指标要好。</span> </em><em><span style="FONT-SIZE: 10.5pt" lang=EN-US><o:p></o:p></span></em></p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">&nbsp; 测试环境。具体包括：选用什么样的硬件环境（计算机配置，网络结构）；什么样的软件环境（操作系统，数据库，应用服务器，</span> <span lang=EN-US>Web</span> <span style="FONT-FAMILY: 宋体">服务器）；多大的数据量（数据库，文件系统）。</span> </p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">&nbsp; 需要监控的资源。进行性能测试时，需要监控的系统软硬件资源的占用情况。这和产品的具体情况有关，一般可以考虑的因素包括：</span> <span lang=EN-US>CPU</span> <span style="FONT-FAMILY: 宋体">使用情况、</span> <span lang=EN-US>Memory</span> <span style="FONT-FAMILY: 宋体">的使用情况、磁盘的</span> <span lang=EN-US>I/O</span> <span style="FONT-FAMILY: 宋体">、网络的占用情况、数据库运行状况、</span> <span lang=EN-US>Web/</span> <span style="FONT-FAMILY: 宋体">应用服务器运行状况等。</span> </p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">&nbsp; 测试工具。选用什么工具进行性能测试，是自己开发，还是选用第三方的测试工具。</span> </p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">&nbsp; 进度安排。各阶段的工作内容、时间安排。</span> </p>
<h3 style="MARGIN-LEFT: 0cm">&nbsp;<span lang=EN-US>1.4.2<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="FONT-FAMILY: 宋体">搭建测试环境</span></h3>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">依照测试计划中的测试环境要求，搭建实际的测试环境，安装配置还好硬件、软件，准备好测试数据。</span> </p>
<h3 style="MARGIN-LEFT: 0cm">&nbsp;<span lang=EN-US>1.4.3<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="FONT-FAMILY: 宋体">编写测试程序</span><span lang=EN-US>/</span><span style="FONT-FAMILY: 宋体">脚本</span></h3>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">编写实际的测试程序或脚本。如果能够使用现有的成熟测试工具则尽量选用，如果现有工具不能满足测试要求，则需要编写定制的测试程序。</span> </p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">同时，要为脚本编写说明文档，文档的内容主要是脚本的名称，以及其对应的测试内容。</span> </p>
<h3 style="MARGIN-LEFT: 0cm">&nbsp;<span lang=EN-US>1.4.4<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><span style="FONT-FAMILY: 宋体">测试执行和分析</span></h3>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">设定多种测试场景组合，反复运行测试，记录结果数据，逐步优化系统，最后达到一个可接受的性能结果。测试执行过程中，注意每次测试后下次测试开始前的测试环境恢复工作。<br><br>性能测试和功能测试一样，也有测试迭代的过程，也会有产品版本的更新。在性能测试过程中，需要和开发人员协同工作，一起调优系统。</span> </p>
<h3 style="MARGIN-LEFT: 0cm">&nbsp;<span lang=EN-US>1.4.5<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">编写测试报告，结束测试</span></h3>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体">整理测试数据，总结测试结果，编写测试报告，结束测试。<br><br><br></span></p>
<h3 style="TEXT-INDENT: 0cm"><span style="FONT-FAMILY: 宋体">附录</span> <span lang=EN-US>1 </span><span style="FONT-FAMILY: 宋体">保证<span lang=EN-US>LoadRunner</span>测试脚本的正确性</span> </h3>
<p class=2><span style="FONT-FAMILY: 宋体">在用</span> <span lang=EN-US>LoadRunner</span> <span style="FONT-FAMILY: 宋体">编写完测试脚本后，要保证脚本在以下情况下能够正确运行：</span> </p>
<p style="TEXT-INDENT: 36pt" class=2><span style="FONT-FAMILY: 宋体">在脚本编辑器中：单用户单循环运行脚本；单用户多循环运行脚本。</span> </p>
<p style="TEXT-INDENT: 36pt" class=2><span style="FONT-FAMILY: 宋体">在</span> <span lang=EN-US>controller</span> <span style="FONT-FAMILY: 宋体">中：多用户单循环运行脚本；多用户多循环运行脚本。</span> </p>
<h3 style="TEXT-INDENT: 0cm"><span style="FONT-FAMILY: 宋体">附录</span> <span lang=EN-US>2 </span><span style="FONT-FAMILY: 宋体">性能测试术语解释</span> </h3>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体"><strong>测试场景：</strong>包含一个或多个脚本，设定并发数量，运行方式，模拟系统在现实中的一个情景。</span> </p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体"><strong>事务</strong>：是指一组相关的操作，是性能测试中的计时单位。比如&#8216;登录应用系统&#8217;就可以作为一个事务。</span> </p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体"><strong>集合点：</strong>设置集合点后，先到达的请求会等待，直到所有的请求都到达，然后一起发送请求。设置集合点，是为了进行更严格和精确的并发测试。</span> </p>
<p class=MsoNormalIndent><strong><span lang=EN-US>checkpoint</span> </strong><span style="FONT-FAMILY: 宋体"><strong>：</strong>也叫检查点。和功能测试一样，性能测试也需要检验结果的正确性。</span> <span style="FONT-FAMILY: 宋体">当返回标准的</span> <span style="FONT-FAMILY: Tahoma" lang=EN-US>HTTP</span> <span style="FONT-FAMILY: 宋体">错误时（状态码不是</span> <span style="FONT-FAMILY: Tahoma" lang=EN-US>200</span> +<span style="FONT-FAMILY: 宋体">时），</span><span lang=EN-US>Loadrunner</span><span style="FONT-FAMILY: 宋体">能够识别出来，但如果返回的不是标准</span><span style="FONT-FAMILY: Tahoma" lang=EN-US>HTTP</span><span style="FONT-FAMILY: 宋体">错误，</span><span lang=EN-US>Loadrunner</span><span style="FONT-FAMILY: 宋体">则无法识别，这时只能通过我们设置的</span><span lang=EN-US>check point</span><span style="FONT-FAMILY: 宋体">来发现错误。</span></p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体"><strong>参数化：</strong>为了更真实的模拟现实操作，我们经常需要对测试输入进行参数化。比如登录时的用户名。</span> </p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体"><strong>关联</strong>：对于脚本中动态变化的部分，需要对其进行参数化，</span> <span lang=EN-US>Loadrunner</span> <span style="FONT-FAMILY: 宋体">提供了对这种变量进行参数化的功能，叫做关联。比如下面这种情况：</span> <span style="FONT-FAMILY: 宋体">在一个基于</span> <span style="FONT-FAMILY: Tahoma" lang=EN-US>WEB</span> <span style="FONT-FAMILY: 宋体">的应用中，用户每次登录时会被服务端赋予了一个</span> <span style="FONT-FAMILY: Tahoma" lang=EN-US>SessionID</span> <span style="FONT-FAMILY: 宋体">，该用户的后续操作都必须给出这个</span> <span style="FONT-FAMILY: Tahoma" lang=EN-US>SessionID</span> <span style="FONT-FAMILY: 宋体">。在这种情况下，由于被赋予的</span> <span style="FONT-FAMILY: Tahoma" lang=EN-US>SessionID</span> <span style="FONT-FAMILY: 宋体">是由服务端给出的，每次执行脚本时，获得的</span> <span style="FONT-FAMILY: Tahoma" lang=EN-US>SessionID</span> <span style="FONT-FAMILY: 宋体">都会不同，因此就需要在脚本中取得用户每次登录，服务端返回的</span> <span style="FONT-FAMILY: Tahoma" lang=EN-US>SessionID</span> <span style="FONT-FAMILY: 宋体">，在后续步骤中使用。这时我们就需要对</span> <span style="FONT-FAMILY: Tahoma" lang=EN-US>SessionID</span> <span style="FONT-FAMILY: 宋体">进行参数化。即</span> <span lang=EN-US>Loadrunner</span> <span style="FONT-FAMILY: 宋体">提供的关联功能。</span> </p>
<p class=MsoNormalIndent><span style="FONT-FAMILY: 宋体"><strong>迭代次数：</strong>在性能测试中，对于一个场景，我们需要运行多次取其平均值，即迭代运行多次。目的是为了避免意外因素对测试结果的影响。</span> </p>
<p class=MsoNormalIndent><strong><span lang=EN-US>think time</span> </strong><span style="FONT-FAMILY: 宋体"><strong>：</strong>思考时间。在进行长时间的稳定性测试时，要考虑在脚本中加入适当的</span> <span lang=EN-US>think time</span> <span style="FONT-FAMILY: 宋体">，来更好的模拟现实中的情况。</span> </p>
<img src ="http://www.cnitblog.com/qiuyangzh/aggbug/19003.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/qiuyangzh/" target="_blank">qiuyangzh</a> 2006-11-09 14:14 <a href="http://www.cnitblog.com/qiuyangzh/archive/2006/11/09/19003.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>未来的3G生活</title><link>http://www.cnitblog.com/qiuyangzh/archive/2006/03/18/7737.html</link><dc:creator>qiuyangzh</dc:creator><author>qiuyangzh</author><pubDate>Sat, 18 Mar 2006 04:03:00 GMT</pubDate><guid>http://www.cnitblog.com/qiuyangzh/archive/2006/03/18/7737.html</guid><wfw:comment>http://www.cnitblog.com/qiuyangzh/comments/7737.html</wfw:comment><comments>http://www.cnitblog.com/qiuyangzh/archive/2006/03/18/7737.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/qiuyangzh/comments/commentRss/7737.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/qiuyangzh/services/trackbacks/7737.html</trackback:ping><description><![CDATA[
		<p>看到一些报道，也从一些在相关公司工作的朋友处得知，中国在未来的1，2年内会正式投入使用3G网络。网络设备硬件厂商能获得的巨大利润我不太关心，不过3G网络推广后，软件公司在无线领域所能提供的服务会更加多样。提供移动互联网相关技术和服务的公司，会有很大的发展空间。想想现在靠彩信，铃声之类的业务就养活了多少大大小小的公司。</p>
		<p>期待未来更加方便，多彩的3G生活，期待未来更大的发展。</p>
<img src ="http://www.cnitblog.com/qiuyangzh/aggbug/7737.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/qiuyangzh/" target="_blank">qiuyangzh</a> 2006-03-18 12:03 <a href="http://www.cnitblog.com/qiuyangzh/archive/2006/03/18/7737.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自动化测试的7个步骤(转载)</title><link>http://www.cnitblog.com/qiuyangzh/archive/2006/02/23/6893.html</link><dc:creator>qiuyangzh</dc:creator><author>qiuyangzh</author><pubDate>Thu, 23 Feb 2006 09:44:00 GMT</pubDate><guid>http://www.cnitblog.com/qiuyangzh/archive/2006/02/23/6893.html</guid><wfw:comment>http://www.cnitblog.com/qiuyangzh/comments/6893.html</wfw:comment><comments>http://www.cnitblog.com/qiuyangzh/archive/2006/02/23/6893.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.cnitblog.com/qiuyangzh/comments/commentRss/6893.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/qiuyangzh/services/trackbacks/6893.html</trackback:ping><description><![CDATA[<h3><strong>自动化测试的7个步骤 </strong></h3>
<h3><font size=3>作者：Bret Pettichord　译者：王威　原文地址：</font><a href="http://testing.csai.cn/testtech/No364.htm"><font size=3>http://testing.csai.cn/testtech/No364.htm</font></a></h3>
<p class=main>　　【摘要】 我们对自动化测试充满了希望，然而，自动化测试却经常带给我们沮丧和失望。虽然，自动化测试可以把我们从困难的环境中解放出来，在实施自动化测试解决问题的同时，又带来同样多的问题。在开展自动化测试的工作中，关键问题是遵循软件开发的基本规则。本文介绍自动化测试的 7 个步骤：改进自动化测试过程，定义需求，验证概念，支持产品的可测试性，具有可延续性的设计（ design for sustainability ），有计划的部署和面对成功的挑战。按照以上 7 个步骤，安排你的人员、工具和制定你的自动化测试项目计划，你将会通往一条成功之路。 </p>
<p class=main>　　一个故事 :</p>
<p class=main>　　我在很多软件公司工作过，公司规模有大有小，也和来自其他公司的人员交流，因此经历过或者听说过影响自动化测试效果的各种各样的的问题。本文将提供若干方法规避可能在自动化测试中出现的问题。我先给大家讲一个故事，以便各位了解自动化测试会出现哪些问题。 </p>
<p class=main>　　以前，我们有一个软件项目，开发小组内所有的人都认为应该在项目中采用自动化测试。软件项目的经理是 Anita Delegate 。她评估了所有可能采用的自动化测试工具，最后选择了一种，并且购买了几份拷贝。她委派一位员工 ——Jerry Overworked 负责自动化测试工作。 Jerry 除了负责自动化测试工作，还有其他的很多任务。他尝试使用刚刚购买的自动化测试工具。当把测试工具应用到软件产品测试中的时候，遇到了问题。这个测试工具太复杂，难于配置。他不得不给测试工具的客户支持热线打了几个电话。最后， Jerry 认识到，他需要测试工具的技术支持人员到现场帮助安装测试工具，并找出其中的问题。在打过几个电话后，测试工具厂商派过来一位技术专家。技术专家到达后，找出问题所在，测试工具可以正常工作了。这还算是顺利了。但是，几个月后，他们还是没有真正实现测试自动化， Jerry 拒绝继续从事这个项目的工作，他害怕自动化测试会一事无成，只是浪费时间而已。 </p>
<p class=main>　　项目经理 Anita 把项目重新指派给 Kevin Shorttimer ，一位刚刚被雇佣来做软件测试的人员。 Kevin 刚刚获得计算机科学的学位，希望通过这份工作迈向更有挑战性的、值得去做的工作。 Anita 送 Kevin 参加工具培训，避免 Kevin 步 Jerry 的后尘 —— 由于使用测试工具遇到困难而变得沮丧，导致放弃负责的项目。 Kevin 非常兴奋。这个项目的测试需要重复测试，有点令人讨厌，因此，他非常愿意采用自动化测试。一个主要的版本发布后， Kevin 准备开始全天的自动化测试，他非常渴望得到一个机会证明自己可以写非常复杂的，有难度的代码。他建立了一个测试库，使用了一些技巧的方法，可以支持大部分的测试，这比原计划多花费了很多时间，不过， Kevin 使整个测试工作开展的很顺利。他用已有的测试套测试新的产品版本，并且确实发现了 bug 。接下来， Kevin 得到一个从事软件开发职位的机会，离开了自动化的岗位。 </p>
<p class=main>　　Ahmed Hardluck 接手 Kevin 的工作，从事自动化测试执行工作。他发现 Kevin 留下的文档不仅少，并且没有太多的价值。 Ahmed 花费不少时间去弄清楚已有的测试设计和研究如何开展测试执行工作。这个过程中， Ahmed 经历了很多失败，并且不能确信测试执行的方法是否正确。测试执行中，执行失败后的错误的提示信息也没有太多的参考价值，他不得不更深的钻研。一些测试执行看起来仿佛永远没有结束。另外一些测试执行需要一些特定的测试环境搭建要求，他更新测试环境搭建文档，坚持不懈地工作。后来，在自动化测试执行中，它发现几个执行失败的结果，经过分析，是回归测试的软件版本中有 BUG ，导致测试执行失败，发现产品的 BUG 后，每个人都很高兴。接下来，他仔细分析测试套中的内容，希望通过优化测试套使测试变得更可靠，但是，这个工作一直没有完成，预期的优化结果也没有达到。按照计划，产品的下一个发布版本有几个主要的改动， Ahmed 立刻意识到产品的改动会破坏已有的自动化测试设计。接下来，在测试产品的新版本中，绝大多数测试用例执行失败了， Ahmed 对执行失败的测试研究了很长时间，然后，从其他人那里寻求帮助。经过商讨，自动化测试应该根据产品的新接口做修改，自动化测试才能运转起来。最后，大家根据新接口修改自动化测试，测试都通过了。产品发布到了市场上。接下来，用户立刻打来投诉电话，投诉软件无法工作。大家才发现自己改写了一些自动化测试脚本，导致一些错误提示信息被忽略了。虽然，实际上测试执行是失败的，但是，由于改写脚本时的一个编程错误导致失败的测试执行结果被忽略了。这个产品终于失败了。 </p>
<p class=main>　　这是我的故事。或许您曾经亲身经历了故事当中某些情节。不过，我希望你没有这样的相似结局。本文将给出一些建议，避免出现这样的结局。 </p>
<p class=main>　　问题 </p>
<p class=main>　　这个故事阐明了几个使自动化测试项目陷入困境的原因： </p>
<p class=main>　　自动化测试时间不充足：根据项目计划的安排，测试人员往往被安排利用自己的个人时间或者项目后期介入自动化测试。这使得自动化测试无法得到充分的时间，无法得到真正的关注。 </p>
<p class=main>　　缺乏清晰的目标：有很多好的理由去开展自动化测试工作，诸如自动化测试可以节省时间，使测试更加简单，提高测试的覆盖率，可以让测试人员保持更好的测试主动性。但是，自动化测试不可能同时满足上述的目标。不同的人员对自动化测试有不同的希望，这些希望应该提出来，否则很可能面对的是失望。 </p>
<p class=main>　　缺乏经验：尝试测试自己的程序的初级的程序员经常采用自动化自动化测试。由于缺乏经验，很难保证自动化测试的顺利开展。 </p>
<p class=main>　　更新换代频繁（ High turnover ）：测试自动化往往需要花费很多时间学习的，当自动化测试更新换代频繁的时候，你就丧失了刚刚学习到的自动化测试经验。 </p>
<p class=main>　　对于绝望的反应：在测试还远没有开始的时候，问题就已经潜伏在软件中了。软件测试不过是发现了这些潜伏的问题而已。就测试本身而言，测试是一件很困难的工作。当在修改过的软件上一遍接一遍的测试时，测试人员变得疲劳起来。测试什么时候后结束？当按照计划的安排，软件应该交付的时候，测试人员的绝望变得尤其强烈。如果不需要测试，那该有多好呀！在这种环境中，自动化测试可能是个可以选择的解决方法。但是，自动化测试却未必是最好的选择，他不是一个现实的解决方法，更像是一个希望。 </p>
<p class=main>　　不愿思考软件测试：很多人发现实现产品的自动化测试比测试本身更有趣。在很多软件项目发生这样的情况，自动化工程师不参与到软件测试的具体活动中。由于测试的自动化与测试的人为割裂，导致很多自动化对软件测试并没有太大的帮助。 </p>
<p class=main>　　关注于技术：如何实现软件的自动化测试是一个很吸引人的技术问题。不过，过多的关注如何实现自动化测试，导致忽略了自动化测试方案是否符合测试需要。 </p>
<p class=main>　　遵守软件开发的规则 </p>
<p class=main>　　你可能了解 SEI （软件工程研究所）提出的 CMM （能力成熟度模型）。 CMM 分为 5 个界别，该模型用来对软件开发组织划分等级。 Jerry Weinberg （美国著名软件工程专家）也创建了自己的一套软件组织模型，在他的组织模型中增加了一个额外的级别，他称之为零级别。很显然，一个零模式的组织实际上也是开发软件；零模式组织中，在开发人员和用户之间没有差别 [Weinberg 1992] 。恰恰在这类组织环境中，经常采用自动化测试方法。因此，把资源用于自动化测试，并且把自动化测试当作一个软件开发活动对待，把软件测试自动化提升到一级。这是解决测试自动化的核心的方案。我们应该像运作其他的开发项目一样来运作软件自动化测试项目。 </p>
<p class=main>　　像其他软件开发项目一样，我们需要软件开发人员专注于测试自动化的开发任务；像其他软件开发项目一样，自动化测试可以自动完成具体的测试任务，对于具体的测试任务来说，自动化开发人员可能不是这方面的专家，因此，软件测试专家应该提供具体测试任务相关的咨询，并且提供测试自动化的需求；像其他软件开发项目一样，如果在开发编码之前，对测试自动化作了整体设计有助于测试自动化开发的顺利开展。像其他软件开发项目一样，自动化测试代码需要跟踪和维护，因此，需要采用源代码管理。像其他软件开发项目一样，测试自动化也会出现 BUG ，因此，需要有计划的跟踪 BUG ，并且对修改后的 BUG 进行测试。像其他软件开发项目一样，用户需要知道如何使用软件，因此，需要提供用户使用手册。 </p>
<p class=main>　　本文中不对软件开发做过多讲述。我假定您属于某个软件组织，该组织已经知道采用何种合理的、有效的方法开发软件。我仅仅是推动您在自动化测试开发过程中遵守已经建立的软件开发规则而已。本文按照在软件开发项目中采用的标准步骤组织的，重点关注测试自动化相关的事宜和挑战。 <a></a></p>
<p class=main>　　? 改进软件测试过程 </p>
<p class=main>　　? 定义需求 </p>
<p class=main>　　? 验证概念 </p>
<p class=main>　　? 支持产品的可测试性 </p>
<p class=main>　　? 可延续性的设计（ design for sustainability ） </p>
<p class=main>　　? 有计划的部署 </p>
<p class=main>　　? 面对成功的挑战 </p>
<p class=main>　　<strong>步骤一：改进软件测试过程 </strong></p>
<p class=main>　　如果你负责提高一个商业交易操作的效率，首先，你应该确认已经很好的定义了这个操作的具体过程。然后，在你投入时间和金钱采用计算机提供一套自动化的商业交易操作系统之前，你想知道是否可以采用更简单、成本更低的的方法。同样的，上述过程也是用于自动化测试。我更愿意把 &#8220; 测试自动化 &#8221; 这个词解释成能够使测试过程简单并有效率，使测试过程更为快捷，没有延误。运行在计算机上的自动化测试脚本只是自动化测试的一个方面而已。 </p>
<p class=main>　　例如，很多测试小组都是在回归测试环节开始采用测试自动化的方法。回归测试需要频繁的执行，再执行，去检查曾经执行过的有效的测试用例没有因为软件的变动而执行失败。回归测试需要反复执行，并且单调乏味。怎样才能做好回归测试文档化的工作呢？通常的做法是采用列有产品特性的列表，然后对照列表检查。这是个很好的开始，回归测试检查列表可以告诉你应该测试哪些方面。不过，回归测试检查列表只是合于那些了解产品，并且知道需要采用哪种测试方法的人。 </p>
<p class=main>　　在你开始测试自动化之前，你需要完善上面提到的回归测试检查表，并且，确保你已经采用了确定的的测试方法，指明测试中需要什么样的数据，并给出设计数据的完整方法。如果测试掌握了基本的产品知识，这会更好。确认可以提供上面提到的文档后，需要明确测试设计的细节描述，还应该描述测试的预期结果，这些通常被忽略，建议测试人员知道。太多的测试人员没有意识到他们缺少什么，并且由于害怕尴尬而不敢去求助。这样一份详细的文档给测试小组带来立竿见影的效果，因为，现在任何一个具有基本产品知识的人根据文档可以开展测试执行工作了。在开始更为完全意义上的测试自动化之前，必须已经完成了测试设计文档。测试设计是测试自动化最主要的测试需求说明。不过，这时候千万不要走极端去过分细致地说明测试执行的每一个步骤，只要确保那些有软件基本操作常识的人员可以根据文档完成测试执行工作既可。但是，不要假定他们理解那些存留在你头脑中的软件测试执行的想法，把这些测试设计的思路描述清楚就可以了。 </p>
<p class=main>　　我以前负责过一个软件模块的自动化测试工作。这个模块的一些特性导致实现自动化非常困难。当我了解到这项工作无需在很短的时间内完成后，决定制定一个详细回归测试设计方案。我仔细地检查了缺陷跟踪库中与该模块相关的每个已经关闭的缺陷，针对每个缺陷，我写了一个能够发现该问题的测试执行操作。我计划采用这种方法提供一个详细的自动化需求列表，这可以告诉我模块的那一部分最适合自动化测试。在完成上述工作后，我没有机会完成测试自动化的实现工作。不过，当我们需要对这个模块做完整回归测试的时候，我将上面提到的文档提供给若干只了解被测试产品但是没有测试经验的测试人员。依照文档的指导，几乎不需要任何指导的情况下，各自完成了回归测试，并且发现了 BUG 。从某种角度看，这实际上是一次很成功的自动化测试。在这个项目中，我们与其开发自动化测试脚本，还不如把测试执行步骤文档化。后来，在其它项目中，我们开发了自动化测试脚本，发现相关人员只有接受相关培训才能理解并执行自动化测试脚本，如果测试自动化设计的很好，可能会好一些。不过，经过实践我们总结出完成一份设计的比较好的测试文档，比完成一份设计良好的测试脚本简单的多。 </p>
<p class=main>　　另外一个提高测试效率的简单方法是采用更多的计算机。很多测试人员动辄动用几台计算机，这一点显而易见。我之所以强调采用更多的计算机是因为，我曾经看到一些测试人员被误导在单机上努力的完成某些大容量的自动化测试执行工作，这种情况下由于错误的使用了测试设备、测试环境，导致测试没有效果。因此，自动化测试需要集中考虑所需要的支撑设备。 </p>
<p class=main>　　针对改进软件测试过程，我的最后一个建议是改进被测试的产品，使它更容易被测试，有很多改进措施既可以帮助用户更好的使用产品，也可以帮助测试人员更好的测试产品。稍后，我将讨论自动化测试的可测试需求。这里，我只是建议给出产品的改进点，这样对手工测试大有帮助。 </p>
<p class=main>　　一些产品非常难安装，测试人员在安装和卸载软件上花费大量的时间。这种情况下，与其实现产品安装的自动化测试，还不如改进产品的安装功能。采用这种解决办法，最终的用户会受益的。另外的一个处理方法是考虑开发一套自动安装程序，该程序可以和产品一同发布。事实上，现在有很多专门制作安装程序的商用工具。 </p>
<p class=main>　　另一些产品改进需要利用工具在测试执行的日志中查找错误。采用人工方法，在日志中一页一页的查询报错信息很容易会让人感到乏味。那么，赶快采用自动化方法吧。如果你了解日志中记录的错误信息格式，写出一个错误扫描程序是很容易的事情。如果，你不能确定日志中的错误信息格式，就开始动手写错误扫描程序，很可能面临的是一场灾难。不要忘记本文开篇讲的那个故事中提到的测试套无法判断测试用例是否执行失败的例子。最终用户也不愿意采用通过搜索日志的方法查找错误信息。修改错误信息的格式，使其适合日志扫描程序，便于扫描工具能够准确的扫描到所有的错误信息。这样，在测试中就可以使用扫描工具了。 </p>
<p class=main>　　通过改进产品的性能对测试也是大有帮助的。很显然的，如果产品的性能影响了测试速度，鉴别出性能比较差的产品功能，并度量该产品功能的性能，把它作为影响测试进度的缺陷，提交缺陷报告。 </p>
<p class=main><a></a>　　上面所述的几个方面可以在无需构建自动化测试系统的情况下，大幅度的提高测试效率。改进软件测试过程会花费你构建自动化测试系统的时间，不过改进测试过程无疑可以使你的自动化测试项目更为顺利开展起来。 </p>
<p class=main>　<strong>　步骤二：定义需求 </strong></p>
<p class=main>　　在前面的故事中，自动化工程师和自动化测试的发起者的目标存在偏差。为了避免这种情况，需要在自动化测试需求上保持一致。应该有一份自动化测试需求，用来描述需要测试什么。测试需求应该在测试设计阶段详细描述出来，自动化测试需求描述了自动化测试的目标。很多人认为自动化测试显然是一件好事情，但是，他们不愿意对自动化测试的目标给出清晰的描述。下面是人们选用自动化测试的几个原因： </p>
<p class=main>　　? 加快测试进度从而加快产品发布进度 </p>
<p class=main>　　? 更多的测试 </p>
<p class=main>　　? 通过减少手工测试降低测试成本 </p>
<p class=main>　　? 提高测试覆盖率 </p>
<p class=main>　　? 保证一致性 </p>
<p class=main>　　? 提高测试的可靠性 </p>
<p class=main>　　? 测试工作可以由技术能力不强测试人员完成 </p>
<p class=main>　　? 定义测试过程，避免过分依赖个人 </p>
<p class=main>　　? 测试变得更加有趣 </p>
<p class=main>　　? 提高了编程技能 </p>
<p class=main>　　开发管理、测试管理和测试人员实现自动化测试的目标常常是有差别的。除非三者之间达成一致，否则很难定义什么是成功的自动化测试。 </p>
<p class=main>　　当然，不同的情况下，有的自动化测试目标比较容易达到，有的则比较难以达到。测试自动化往往对测试人员的技术水平要求很高，测试人员必须能理解充分的理解自动化测试，从而通过自动化测试不断发现软件的缺陷。不过，自动化测试不利于测试人员不断的积累测试经验。不管怎么样，在开始自动化测试之前应该确定自动化测试成功的标准。 </p>
<p class=main>　　手工测试人员在测试执行过程中的一些操作能够发现不引人注意的问题。他们计划并获取必要的测试资源，建立测试环境，执行测试用例。测试过程中，如果有什么异常的情况发生，手工测试人员立刻可以关注到。他们对比实际测试结果和预期测试结果，记录测试结果，复位被测试的软件系统，准备下一个软件测试用例的环境。他们分析各种测试用例执行失败的情况，研究测试过程可疑的现象，寻找测试用例执行失败的过程，设计并执行其他的测试用例帮助定位软件缺陷。接下来，他们写作缺陷报告单，保证缺陷被修改，并且总结所有的缺陷报告单，以便其他人能够了解测试的执行情况。 </p>
<p class=main>　　千万不要强行在测试的每个部分都采用自动化方式。寻找能够带来最大回报的部分，部分的采用自动化测试是最好的方法。或许你可能发现采用自动化执行和手动确认测试执行结果的方式是个很好的选择，或许你可以采用自动化确认测试结果和手工测试执行相结合和方式。我听到有人讲，除非测试的各个环节都采用自动化方式，否则不是真正意义上的自动化测试，这真是胡言乱语。如果仅仅是为了寻找挑战，可以尝试在测试的每个环节都采用自动化方法。但是，如果寻找成功测试的方法，请关注那些可以快速建立的，可以反复利用的自动化测试。 </p>
<p class=main><a></a>　　定义自动化测试项目的需求要求我们全面地、清楚地考虑各种情况，然后给出权衡后的需求，并且可以使测试相关人员更加合理的提出自己对自动化测试的期望。通过定义自动化测试需求，距离成功的自动化测试近了一步。 </p>
<p class=main>　　<strong>步骤三：验证概念 </strong></p>
<p class=main>　　在前面的故事当中，那个自动化测试人员在对测试方向一片茫然的情况下一头扎进了自动化测试项目中。不过，在项目的进行中，他得到了来自各个方面的支持。 </p>
<p class=main>　　你可能还没有认识到这一点，不过，你必须验证自动化测试项目的可行性。验证过程花费的时间往往比人们预期的要长，并且需要来自你身边的各种人的帮助。 </p>
<p class=main>　　很多年前，我从事一个测试自动化项目的工作，参加项目的人员有各种各样的好点子。我们设计了一个复杂的自动化测试系统，并且非常努力工作去实现系统的每个模块。我们定期的介绍测试自动化的设计思路和工作进度，甚至演示已经完成的部分功能。但是，我们没有演示如何利用该套测试自动化系统如何开展实际的测试工作。最后，整个项目被取消了，此后，我再也没有犯这个错误。 </p>
<p class=main>　　你需要尽可能快地验证你采用的测试工具和测试方法的可行性，站在产品的角度验证你所测试的产品采用自动化测试的可行性。这通常是很困难的，需要尽快地找出可行性问题的答案，需要确定你的测试工具和测试方法对于被测试的产品和测试人员是否合适。你需要做是验证概念 —— 一个快速、有说服力的测试套可以证明你选在测试工具和测试方法的正确性，从而验证了你的测试概念。你选择的用来验证概念的测试套是评估测试工具的最好的方式。 </p>
<p class=main>　　对于很多人来说，自动化测试意味着 GUI 自动化测试，我不同意这种观点。我曾经做过 GUI 和非 GUI 自动化测试，并惊奇的发现这两类测试的测试计划有很大的互补性。不过， GUI 测试工具很昂贵、并且过分讲究。选择合适的 GUI 测试工具是很重要的，因为，如果没有选择合适的测试工具，你会遇到很多不可预测的困难。 Elisabeth Hendrickson 曾经写过一篇关于选择测试的工具的指导性文章 [Hendrickson 1999] 。我建议在评估测试工具中，找出能够验证你的想法的证据是很重要的环节。这需要测试工具至少有一个月试用期，你可能打算现在购买一份测试工具，然后直到评估完成后再购买更多份。你需要在付出大笔金钱购买测试工具的之前，找出工具存在的问题。这样，你可以从测试工具供应商得到更好的帮助，当你打算更换工具的时候，你不会感觉很为难。 </p>
<p class=main>　　下面是一些候选的验证概念的试验： </p>
<p class=main>　　回归测试：你准备在每个版本运行同样的测试用例吗？回归测试是最宜采用自动化测试的环节。 </p>
<p class=main>　　配置测试：你的软件支持多少种不同的平台？你打算在所有支持的平台上测试执行所有的测试用例吗？如果是的，那么采用自动化测试是有帮助的。 </p>
<p class=main>　　测试环境建立：对于大量不同的测试用例，可能需要相同的测试环境搭建过程。在开展自动化测试执行之前，先把测试环境搭建实现自动化。 </p>
<p class=main>　　非 GUI 测试：实现命令行和 API 的测试自动化比 GUI 自动化测试容易的多。 </p>
<p class=main><a></a>　　无论采用什么测试方法，定义一个看得见的目标，然后集中在这个目标上。验证你自动化测试概念可以使自动化更进一步迈向成功之路。 </p>
<p class=main>　　<strong>步骤四：支持产品的可测试性 </strong></p>
<p class=main>　　软件产品一般会用到下面三种不同类别的接口：命令行接口（ command line interfaces ，缩写 CLIs) 、应用程序接口（ API ）、图形用户接口（ GUI ）。有些产品会用到所有三类接口，有些产品只用到一类或者两类接口，这些是测试中所需要的接口。从本质上看， API 接口和命令行接口比 GUI 接口容易实现自动化，去找一找你的被测产品是否包括 API 接口或者命令行接口。有些时候，这两类接口隐藏在产品的内部，如果确实没有，需要鼓励开发人员在产品中提供命令行接口或者 API 接口，从而支持产品的可测试性。 </p>
<p class=main>　　下面，更多多的讲解 GUI 自动化测试相关内容。这里有几个原因导致 GUI 自动化测试比预期的要困难。第一个原因是需要手工完成部分脚本。绝大多数自动化测试工具都有 &#8220; 录制回放 &#8221; 或者 &#8220; 捕捉回放 &#8221; 功能，这确实是个很好的方法。可以手工执行测试用例，测试工具在后台记住你的所有操作，然后产生可以用来重复执行的测试用例脚本。这是一个很好的方法，但是很多时候却不能奏效。很多软件测试文章的作者得出结论 &#8220; 录制回放 &#8221; 虽然可以生成部分测试脚本，但是有很多问题导致 &#8220; 录制回放 &#8221; 不能应用到整个测试执行过程中。 [Bach 1996, Pettichord 1996, Kaner 1997, Linz 1998, Hendrickson 1999, Kit 1999, Thomson 1999, Groder 1999]. 结果， GUI 测试还是主要由手工完成。 </p>
<p class=main>　　第二个原因，把 GUI 自动化测试工和被测试的产品有机的结合在一起需要面临技术上的挑战。经常要在采用众多专家意见和最新的 GUI 接口技术才能使 GUI 测试工具正常工作。这个主要的困难也是 GUI 自动化测试工具价格昂贵的主要原因之一。非标准的、定制的控件会增加测试的困难，解决方法总是有的，可以采用修改产品源代码的方式，也可以从测试工具供应商处升级测试工具。另外，还需要分析测试工具中的 BUG ，并且给工具打补丁。也可能测试工具需要做相当的定制，以便能有效地测试产品界面上的定制控件。 GUI 测试中，困难总是意外出现，让人惊奇。你也可能需要重新设计你的测试以规避那些存在问题的界面控件。 </p>
<p class=main>　　第三个原因， GUI 设计方案的变动会直接带来 GUI 自动化测试复杂度的提高。在开发的整个过程中，图形界面经常被修改或者完全重设计，这是出了名的事情。一般来讲，第一个版本的图形界面都是很糟糕。如果处在图形界面方案不停变动的时候，就开展 GUI 自动化测试是不会有任何进展的，你只能花费大量的时间修改测试脚本，以适应图形界面的变更。不管怎样，即便界面的修改会导致测试修改脚本，你也不应该反对开发人员改进图形界面。一旦原始的设计完成后，图形界面接口下面的编程接口就固定下来了。 </p>
<p class=main>　　上面提到的这些原因都是基于采用 GUI 自动化测试的方法完成产品的功能测试。图形界面接口当然需要测试，可以考虑实现 GUI 测试自动化。不过，你也应该考虑采用其他方法测试产品的核心功能，并且这些测试不会因为图形界面发生变化而被中断，这类测试应该采用命令行接口或者 API 接口。我曾经看到有人选择 GUI 自动化测试，因为，他们不打算修改被测试产品，但是，最终他们认识到必须对产品做修改，以保证 GUI 测试自动化可以正常工作。无论你选择哪种方法，自动化都需要对被测试的产品做修改。因此，采用可编程的接口是最可靠的。 </p>
<p class=main>　　为了让 API 接口测试更为容易，应该把接口与某种解释程序，例如 Tcl 、 Perl 或者 Python 绑定在一起。这使交互式测试成为可能，并且可以缩短自动化测试的开发周期。采用 API 接口的方式，还可以实现独立的产品模块的单元测试自动化。 </p>
<p class=main>　　一个关于隐藏可编程接口的例子是关于 InstallShield—— 非常流行的制作安装盘的工具。 InstallShield 有命令行选项，采用这种选项可以实现非 GUI 方式的安装盘，采用这种方式，从提前创建好的文件中读取安装选项。这种方式可能比采用 GUI 的安装方式更简单更可靠。 </p>
<p class=main>　　另一个例子是关于如何避免基于 WEB 软件的 GUI 自动化测试。采用 GUI 测试工具可以通过浏览器操作 WEB 界面。 WEB 浏览器是通过 HTTP 协议与 WEB 服务器交互的，所以直接测试 HTTP 协议更为简单。 Perl 可以直接连接 TCP/IP 端口，完成这类的自动化测试。采用高级接口技术，譬如客户端 JAVA 或者 ActiveX 不可能利用这种方法。但是，如果在合适的环境中采用这种方式，你将发现这种方式的自动化测试比 GUI 自动化测试更加便宜更加简单。 </p>
<p class=main>　　我曾经受雇在一家公司负责某个产品 GUI 相关的自动化测试，该产品也提供命令行接口，不过，他们已经实现了 GUI 的自动化测试。经过一段时间的研究，我发现找到图形界面中的 BUG 并不困难，不过，用户并不关注图形界面，他们更喜欢使用命令行。我还发现我们还没有针对最新的产品功能（这些功能即可通过 GUI 的方式，也可以通过命令行的方式使用）实现自动化测试。我决定推迟 GUI 自动化测试，扩展命令行测试套，测试新增的产品功能。现在回过头看这个决定，我没有选择 GUI 自动化测试是最大的成功之处，如果采用了 GUI 自动化测试所有的时间和努力都会浪费在其中。他们已经准备好做 GUI 自动化测试了，并且已经购买了一套测试工具和其他需要的东西，但我知道在开展具体的 GUI 自动化测试活动中，会遇到各种各样的困难和障碍。 </p>
<p class=main><a></a>　　无论你需要支持图形界面接口、命令行接口还是 API 接口，如果你尽可能早的在产品设计阶段提出产品的可测试性设计需求，未来的测试工作中，你很可能成功。尽可能早的启动自动化测试项目，提出可测试性需求，会使您走向自动化测试成功之路。 </p>
<p class=main>　<strong>　步骤五：具有可延续性的设计 </strong></p>
<p class=main>　　在开篇的故事中，我们看到由于自动化工程师把注意力仅仅集中在如何使自动化运转起来，导致测试自动化达不到预期的效果。自动化测试是一个长期的过程，为了与产品新版本的功能和其他相关修改保持一致，自动化测试需要不停的维护和扩充。自动化测试设计中考虑自动化在未来的可扩充性是很关键的，不过，自动化测试的完整性也是很重要的。如果自动化测试程序报告测试用例执行通过，测试人员应该相信得到的结果，测试执行的实际结果也应该是通过了。其实，有很多存在问题的测试用例表面上执行通过了，实际上却执行失败了，并且没有记录任何错误日志，这就是失败的自动化。这种失败的自动化会给整个项目带来灾难性的后果，而当测试人员构建的测试自动化采用了很糟糕的设计方案或者由于后来的修改引入了错误，都会导致这种失败的测试自动化。失败的自动化通常是由于没有关注自动化测试的性能或者没有充分的自动化设计导致的。 </p>
<p class=main>　　性能： 提高代码的性能往往增加了代码的复杂性，因此，会威胁到代码的可靠性。很少有人关心如何对自动化本身加以测试。通过我对测试套性能的分析，很多测试套都是花费大量的时间等候产品的运行。因此，在不提高产品运行性能的前提下，无法更有效的提高自动化测试执行效率。我怀疑测试自动化工程师只是从计算机课程了解到应该关注软件的性能，而并没有实际的操作经验。如果测试套的性能问题无法改变，那么应该考虑提高硬件的性能；测试套中经常会出现冗余，也可以考虑取出测试套中的冗余或者减少一个测试套中完成的测试任务，都是很好的办法。 </p>
<p class=main>　　便于分析： 测试自动化执行失败后应该分析失败的结果，这是一个棘手的问题。分析执行失败的自动化测试结果是件困难的事情，需要从多方面着手，测试上报的告警信息是真的还是假的？是不是因为测试套中存在缺陷导致测试执行失败？是不是在搭建测试环境中出现了错误导致测试执行失败？是不是产品中确实存在缺陷导致测试执行失败？有几个方法可以帮助测试执行失败的结果分析，某些方法可以找到问题所在。通过在测试执行之前检查常见的测试环境搭建问题，从而提高测试套的可靠性；通过改进错误输出报告，从而提高测试自动化的错误输出的可分析性；此外，还可以改进自动化测试框架中存在的问题。训练测试人员如何分析测试执行失败结果。甚至可以找到那些不可靠的、冗余的或者功能比较独立的测试，然后安全地将之删除。上面这些都是减少自动化测试误报告警、提高测试可分析性的积极有效的方法。另外，有一种错误的测试结果分析方法，那就是采用测试结果后处理程序对测试结果自动分析和过滤，尽管也可以采用这种测试结果分析方法，不过这种方法会使自动化测试系统复杂化，更重要的是，后处理程序中的 BUG 会严重损害自动化测试的完整性。如果由于自动化测试本身存在的缺陷误把产品中的正常功能视为异常，那该怎么办？我曾经看到测试小组花费开发测试自动化两倍的时间来修改测试脚本，并且不愿意开展培训过程。那些仅仅关注很浅层次测试技术的测试管理者对这种方法很感兴趣，他们排斥采用隐藏测试复杂度的方法。 </p>
<p class=main>　　综上所述，应该集中精力关注可以延续使用的测试套，从以下几方面考虑，测试的可检视性、测试的可维护性、测试的完整性、测试的独立性、测试的可重复性。 </p>
<p class=main>　　可读性： 很多情况下，在测试人员开始测试项目之前，公司已经有了一套测试脚本，并且已经存在很多年了。我们可以称之为 &#8220; 聪明的橡树 &#8221;(wise oak tree)[Bach 1996] 。大家很依赖它，但是并不知道它是什么。由于 &#8220; 聪明的橡树 &#8221; 类型的测试脚本缺乏可读性，在具体应用中，那些脚本常常没有多大的实用价值，越来越让人迷惑。因此，测试人员很难确定他们实际在测试什么，反而会导致测试人员对自身的测试能力有过高的估计。测试人员能够检视测试脚本，并且理解测试脚本究竟测试了什么，这是很关键的。好的文档是解决问题的手段之一，对测试脚本全面分析是另外一个手段。由上面两种方法可以引申出其它的相关方法，我曾经在一个项目中使用过引申之后的方法。在测试脚本中插桩，把所有执行的产品相关的命令记录到日志里。这样，当分析日志确定执行了哪些产品命令，命令采用了何种参数配置时，可以提供一个非常好的测试记录，里面记录了自动化测试执行了什么，没有执行什么。如果测试脚本可读性不好，很容易变得过分依赖并没有完全理解的测试脚本，很容易认为测试脚本实际上做的工作比你想象中的还要多。测试套的可读性提高后，可以更容易的开展同行评审活动。 </p>
<p class=main>　　可维护性： 在工作中，我曾经使用过一个测试套，它把所有的程序输出保存到文件中。然后，通过对比输出文件内容和一个已有的输出文件内容的差别，可以称已有的输出文件为 &#8220; 标准文件 &#8221; （ &#8220;gold file&#8221; ）。在回归测试中，用这个方法查找 BUG 是不是明智之举。这种方法太过于敏感了，它会产生很多错误的警告。随着时间的推移，软件开发人员会根据需要修改产品的很多输出信息，这会导致很多自动化测试失败。很明显，为了保证自动化测试的顺利进行，应该在对 &#8220; 标准文件 &#8221; 仔细分析的基础上，根据开发人员修改的产品输出信息对之做相应的修改。比较好的可维护性方法是，每次只检查选定的产品的某些特定输出，而不是对比所有的结果输出。产品的接口变动也会导致原来的测试无法执行或者执行失败。对于 GUI 测试，这是一个更大的挑战。研究由于产品接口变化引起的相关测试修改，并研究使测试修改量最小的方法，测试中采用库是解决问题的方法。当产品发生变化的时候，只需要修改相关的库，保证测试与产品的变动同步修改即可。 </p>
<p class=main>　　完整性： 当自动化测试执行后，报告测试执行通过，可以断定这是真的吗？这就是我称之为测试套的完整性。在前面的故事中，当没有对自动化测试完整性给予应有的关注的时候，发生了富有喜剧性的情况。我们应该在多大程度上相信自动化化测试执行结果？自动化测试执行中的误报告警是很大的问题。测试人员特别讨厌由于测试脚本自身的问题或者是测试环境的问题导致测试执行失败，但是，对于自动化测试误报告警的情况，大家往往无能为力。你期望自己设计的测试对 BUG 很敏感、有效，当测试发现异常的时候，能够报告测试执行失败。有的测试框架支持对特殊测试结果的分类方法，分类包括 PASS ， FAIL 和第三种测试结果 NOTRUN 或者 UNRESOLVED 。无论你怎么称呼第三种测试结果，它很好的说明了由于某些测试失败导致其他测试用例无法执行而并非执行失败的情况。得到正确的测试结果是自动化测试完整性定义的一部分，另一部分是能够确认执行成功的测试确确实实已经执行过了。我曾经在一个测试队列中发现一个 BUG ，这个 BUG 引起测试队列中部分测试用例被跳过，没有执行。当测试队列运行完毕后，没有上报任何错误，我不得不通过走读代码的方式发现了这个 BUG 。如果，我没有关注到这个 BUG ，那么可能在认识到自动化测试已经出现问题之前，还在长时间运行部分测试用例。 </p>
<p class=main>　　独立性： 采用自动化方法不可能达到和手工测试同样的效果。当写手工测试执行的规程时候，通常假定测试执行将会由一个有头脑、善于思考、具有观察力的测试人员完成的。如果采用自动化，测试执行是由一台不会说话的计算机完成的，你必须告诉计算机什么样的情况下测试执行是失败的，并且需要告诉计算机如何恢复测试场景才能保证测试套可以顺利执行。自动化测试可以作为测试套的一部分或者作为独立的测试执行。测试都需要建立自己所需要的测试执行环境，因此，保证测试执行的独立性是唯一的好方法。手工回归测试通常都相关的指导文档，以便一个接着一个有序地完成测试执行，每个测试执行可以利用前一个测试执行创建的对象或数据记录。手工测试人员可以清楚地把握整个测试过程。在自动化测试中采用上述方法是经常犯的错误，这个错误源于 &#8220; 多米诺骨牌 &#8221; 测试套，当一个测试执行失败，会导致后续一系列测试失败。更糟糕的是，所有的测试关联紧密，无法独立的运行。并且，这使得在自动化测试中分析合法的执行失败结果也困难重重。当出现这种情况后，人们首先开始怀疑自动化测试的价值。自动化测试的独立性要求在自动化测试中增加重复和冗余设计。具有独立性的测试对发现的缺陷的分析有很好的支持。以这种方式设计自动化测试好像是一种低效率的方式，不过，重要的是在不牺牲测试的可靠性的前提下保证测试的独立性，如果测试可以在无需人看守情况下运行，那么测试的执行效率就不是大问题了。 </p>
<p class=main>　　可重复性： 自动化测试有时能够发现问题，有时候又无法发现问题，对这种情况实在没有什么好的的处理办法。因此，需要保证每次测试执行的时候，测试是以同样的方式工作。这意味着不要采用随机数据，在通用语言库中构造的随机数据经常隐藏初始化过程，使用这些数据会导致测试每次都以不同的方式执行，这样，对测试执行的失败结果分析是很让人沮丧的。这里有两个使用随机数据发生器的的方法可以避免上述情况。一种方法是使用常量初始化随机数据发生器。如果你打算生成不同种类的测试，需要在可预测，并且可控制的情况下建立不同类型的随机数据发生器。另外一个办法是提前在文件中或数据库中建立生成随机测试数据，然后在测试过程中使用这些数据。这样做看起来似乎很好，但是我却曾经看到过太多违反规则的做法。下面我来解释到底看到了什么。当手动执行测试的时候，往往匆匆忙忙整理文件名和测试数据记录。当对这些测试采用自动化测试方法，该做哪些工作呢？办法之一是，可以为测试中使用的数据记录给固定的命名。如果这些数据记录在测试完成后还要继续使用，那么就需要制定命名规则，避免在不同的测试中命名冲突，采用命名规则是一种很好的方法。然而，我曾经看到有些测试只是随机的命名数据记录，很不幸，事实证明采用这种随机命名的方式不可避免的导致命名冲突，并且影响测试的可重复性。很显然，自动化工程师低估了命名冲突的可能性。下面的情况我遇到过两次，测试数据记录的名字中包含四个随机产生的数字，经过简单的推算如果我们采用这种命名方式的时候，如果测试使用了 46 条记录，会存在 10% 冲突的可能性，如果使用 118 条记录，冲突的几率会达到 50% 。我认为测试当中使用这种随机命名是出于偷懒的想法 —— 避免再次测试之前写代码清除老的数据记录，这样引入了问题，损害了测试的可靠性和测试的完整性。 </p>
<p class=main>　　测试库： 自动化测试的一个通用策略是开发可以在不同测试中应用的测试函数库。我曾经看到过很多测试函数库，自己也写了一些。当要求测试不受被测试产品接口变动影响的时候，采用测试库方法是非常有效的。不过，根据我的观察测试库已经使用的太多了，已经被滥用了，并且测试库往往设计的不好，没有相关的文档支撑，因此，使用测试库的测试往往很难开展。当发现问题的时候，往往不知道是测试库自身的问题，还是测试库的使用问题。由于测试库往往很复杂，即便在发现测试库存在问题，相关的维护人员也很不愿意去修改问题。通过前文中的论述，可以得出结论，在一开始就应该保证测试库设计良好。但是，实际情况是测试自动化往往没有花费更多的精力去保证一个优良设计的测试库。我曾经看到有些测试库中的功能根本不再使用了或仅仅使用一次。这与极限编程原则保持一致，即 " 你将不需要它 " 。这会导致在测试用例之间的代码出现一些重复，我发现微小的变化可能仍然存在，很难与测试库功能协调。你可能打算对测试用例作修改，采用源代码的方式比采用库的方式更容易修改。如果有几个测试，他们有某些共同的操作，我使用剪切和粘贴的方式去复制代码，有的人认为我采用的方法不可理喻。这允许我根据需要修改通用代码，我不必一开始尝试和猜测如何重用代码。我认为我的测试是很容易读懂的，因为阅读者不必关心任何测试库的语法。这种办法的优势是很容易理解测试，并且很方便扩展测试套。在开发软件测试项目的时候，大多数程序员找到与他们打算实现功能类似的源代码，并对源代码做修改，而不是从头开始写代码。同样，在写测试套的过程中可以采用上述方法，这也是代码开发方式所鼓励的方法。我比较喜欢写一些规模比较小的测试库，这些库可以被反复的使用。测试库的开发需要在概念阶段充分定义，并且文档化，从始至终都应该保持。我会对测试库作充分的测试后，才在测试中使用这些测试库。采用测试库是对所有面临的情况作权衡的。千万不要打算写一个大而全的测试库，不要希望有朝一日测试人员会利用你的测试库完成大量的测试，这一天恐怕永远不会到来。 </p>
<p class=main>　　数据驱动测试： 把测试数据写入到简单表格中，这种测试技术得到了越来越广泛的应用，这种方法被称为表驱动（ table-driven ），数据驱动 (data-driven) 或者 &#8220; 第三代 &#8221; 自动化测试（ "third generation" automation ）。这需要写一个解析器，用来解释表格中的数据，并执行测试。该测试架构的最主要的好处是，它允许把测试内容写在具有一定格式的表格中，这样方便数据设计和数据的检视。如果测试组中有缺少编程经验的业务专家参与测试，采用数据驱动测试方法是很合适的。数据驱动测试的解析器主要是由测试库和上层的少量开发语言写成的代码组成的，所以，上面关于测试库的说明放在这里是同样合适的。在针对上面提到的少量代码的设计、开发、测试的工作，还存在各种困难。代码所采用的编程语言是不断发展的。也许，测试人员认为他们需要把第一部分测试的输出作为第二部分测试的输入，这样，加入了新的变量。接下来，也许有人需要让测试中的某个环节运行一百次，这样加入一个循环。你可以采用其他语言，不过，如果你预料到会面临上述情况的时候，那么做好采用一些能够通过公开的渠道获取的编程语言，比如 Perl,Python 或者 TCL ，这样比设计你自己的语言要快的多。 </p>
<p class=main>　　启发式确认： 我曾经看到很多测试自动化没有真正意义上的结果校验，其原因有两个，一个原因是做完全意义上的自动化测试结果确认从技术上讲是很困难的，另外一个原因是通过测试设计规格很难找出自动化测试的预期结果。这很不幸。不过，采用手工校验测试结果的方法是真正意义上的测试校验。标准文件（ Gold file ）是另外一中校验测试结果的方法。首先，捕获被测试程序的输出，并检视程序的输出，然后，把输出信息文档化，并归档，作为标准文件。以后，自动化测试结果与标准文件作比较，从而达到结果校验的目的。采用标准文件的方法，也有弊端。当产品发生变化，自动化测试的环境配置发生变化，产品的输出发生变化的时候，采用标准文方法，会上报大量的误报告警。做好的测试结果校验方法是，对输出结果的特定内容作分析，并作合理的比较。有时候，很难知道正确的输出结果是什么样的，但是你应该知道错误的输出结果是什么样的。开展启发式的结果校验是很有帮助的。我猜想一些人在自动化测试中设计了大而全的测试结果校验方法，是因为担心如果结果校验漏掉了任何信息，可能导致自动化测试自身出现错误。不过，我们在测试过程中往往采用折衷的做法，没有采用大而全的测试结果校验方法，这样就不得不面对少量漏测情况的出现的风险。自动化测试不能改变这种情况的出现。如果自动化工程师不习惯采用这种折衷的方法，那么他必须找相关人员咨询，寻找一种合适的测试结果校验策略，这需要有很大的创造性。目前有很多技术可以保证在不产生误报告警的情况下，找到被测试产品的缺陷。 </p>
<p class=main><a></a>　　把注意力放在通过设计保证测试的可延续性上，选择一个合适的测试体系架构，你将进一步迈向成功的自动化测试。 </p>
<p class=main>　　<strong>步骤六：有计划的部署 </strong></p>
<p class=main>　　在前面的故事中，当自动化工程师没有提供打包后的自动化测试程序给测试执行人员，会影响到测试执行，测试执行人员不得不反过来求助自动化工程师指出如何使用自动化测试程序。 </p>
<p class=main>　　作为自动化工程师，你知道如何利用自动化方法执行测试和分析执行失败的结果。不过，测试执行人员却未必知道如何使用自动化测试。因此，需要提供自动化测试程序的安装文档和使用文档，保证自动化测试程序容易安装和配置。当安装的环境与安装的要求不匹配，出现安装错误的时候，能够给出有价值的提示信息，便于定位安装问题。 </p>
<p class=main>　　能够把自动化测试程序和测试套作为产品对待，那真是太好了。你应该对自动化测试程序和测试套开展测试，保证它们不依赖于任何专用的库或者是设备上的任何其他程序。 </p>
<p class=main>　　保证其他测试人员能够随时利用已经提供的自动化测试程序和测试套开展测试工作；保证自动化测试是符合一般测试执行人员的思维习惯的；保证测试执行人员能够理解测试结果，并能够正确分析失败的测试执行结果；这需要自动化工程师提供自动动化测试相关的指导性文档和培训。 </p>
<p class=main>　　作为测试管理者，你希望在自动化工程师离开前，能够识别并修改测试套中的所有问题。自动化工程师迟早会离开的，如果你没有及时的把测试套中的问题提出来，就会面临废弃已有的测试套的决定。 </p>
<p class=main>　　良好的测试套有多方面的用处。良好的测试套支持对产品新版本的测试；良好的测试套在新的软件平台上可以很方便的验证产品的功能；良好的测试套支持每天晚上开始的软件每日构造过程；甚至开发人员在代码 check in 之前，用良好的测试套验证代码的正确性。 </p>
<p class=main>　　测试套的共享也很重要。很难预见以后什么人会继续使用你开发的测试套。因此，尽量让产品开发测试团队中的成员都很容易获得你的测试套。可以把测试套放在公司的内部网络上，这是个很好的办法。这样，大家就不必为了获取一份需要的测试套而四处打听。有些人总是感觉自己的测试套还没有最终完工或者不够完美，而没有拿出来与人分享，这种做法一定要改变，共享出来的测试套不一定非常完美，共享才是关键。 </p>
<p class=main><a></a>　　有计划的自动化测试部署，保证你的测试套能够被产品相关人员获取到，你就向成功的自动化测试又迈进了一步。并且你的自动化测试会被一次又一次的重用。 </p>
<p class=main>　　<strong>步骤七：面对成功的挑战 </strong></p>
<p class=main>　　当你完成了所有的事情，测试套已经文档化了，并且文档已经交付了。测试执行人员能够理解要开展的测试，并知道如何完成测试执行。随着你所负责产品的进一步开发和维护，测试被反复重用。虽然，在自动化使测试变简单的同时，也总是使测试过程复杂化。测试人员需要学习如何诊断自动化测试执行失败的情况，如果不这样做，测试执行人员会认为执行失败的情况是由自动化引起，然后，自动化工程师被叫过来帮助诊断每一个执行失败的情况，开发人员往往也会认为执行失败是由于自动化测试自身引起的问题，这样，测试执行人员就不得不学习通过手工的方式，或者通过采用少量脚本的方式重现自动化测试发现的问题，以证明他们确实发现了产品当中的 BUG 。 </p>
<p class=main>　　测试套的相关工作还没有结束，为了提高测试覆盖率或者测试新的产品特性，需要增加更多的测试。如果已有的测试不能正常工作，那么需要对之修改；如果已有的测试是冗余的，那么需要删除这部分测试。 </p>
<p class=main>　　随着时间的推移，开发人员也会研究你设计的测试，改进产品的设计并且通过模拟你的测试过程对产品做初步测试，研究如何使产品在第一次测试就通过，这样，你设计的测试很可能无法继续发现新的问题，这种现象被称为一种杀虫剂悖论。这时候，会有人对你的测试有效性提出质疑，那么，你必须考虑是否应该挖掘更严格的测试，以便能够发现开发人员优化之后的产品中的缺陷。 </p>
<p class=main>　　以前，我提到过一个基本上无法实现的设想，设想通过按下一个按钮就完成了所有的测试工作。自动化测试是不是全能的，手工测试是永远无法完全替代的。 </p>
<p class=main>　　有些测试受测试环境的影响很大，往往需要采用人工方法获取测试结果，分析测试结果。因此，很难在预先知道设计的测试用例有多大的重用性。自动化测试还需要考虑成本问题，因此，千万不要陷入到一切测试都采用自动化方法的错误观念中。 </p>
<p class=main>　　我曾经主张保证给与测试自动化持续不断的投入。但是，在开展自动化测试的时候，一个问题摆在面前，测试自动化应该及时的提供给测试执行人员，这个不成问题，但是如何保证需求变更后，能够及时提供更新后的自动化测试就是个大问题了。如果自动化测试与需求变更无法同步，那么自动化测试的效果就无法保证了，测试人员就不愿意花费时间学习如何使用新的测试工具和如何诊断测试工具上报的错误。识别项目计划中的软件发布日期，然后把这个日期作为里程碑，并计划达到这个里程碑。当达到这个里程碑后，自动化工程师应该做什么呢？如果自动化工程师关注当前产品版本的发布，他需要为测试执行人员提供帮助和咨询，但是，一旦测试执行人员知道如何使用自动化测试，自动化测试工程师可以考虑下一个版本的测试自动化工作，包括改进测试工具和相关的库。当开发人员开始设计产品下一个版本中的新特性的时候，如果考虑了自动化测试需求，那么自动化测试师的设计工作就很好开展了，采用这种方法，自动化测试工程师可以保持与开发周期同步，而不是与测试周期同步。如果不采用这种方式，在产品版本升级的过程中，自动化测试无法得到进一步的改进。 </p>
<p class=main>　　持续在在自动化投入，你会面临成功的挑战，当自动化测试成为测试过程可靠的基础后，自动化测试的道路将会越来越平坦。 </p>
<img src ="http://www.cnitblog.com/qiuyangzh/aggbug/6893.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/qiuyangzh/" target="_blank">qiuyangzh</a> 2006-02-23 17:44 <a href="http://www.cnitblog.com/qiuyangzh/archive/2006/02/23/6893.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>