<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_关河的测试生活</title><subtitle type="text">生活不是测试，但测试确实是一种生活</subtitle><id>http://feed.cnblogs.com/blog/u/19737/rss</id><updated>2010-12-15T09:02:14Z</updated><author><name>关河</name><uri>http://www.cnblogs.com/guanhe/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/guanhe/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/19737/rss"/><entry><id>http://www.cnblogs.com/guanhe/archive/2010/12/15/agiletesting1.html</id><title type="text">敏捷测试专栏之一 《什么是敏捷软件测试》</title><summary type="text">在与不少测试从业人员讨论到敏捷的时候，被问得最多的大约是两个问题：“到底什么是敏捷软件测试？”，“敏捷软件开发还需要测试工程师吗？”。前一个问题是对于敏捷测试本身定义的疑问，第二个问题则是对敏捷开发将测试工程师排除在外的担心。其实，在探寻这两个问题答案的过程中，我们可以更清晰的了解敏捷软件开发中测试的工作定义，测试价值观，以及敏捷开发中开发与测试工程师的配合。鉴于这两个问题的意义，在本敏捷测试专栏的第一篇文章中，本人尝试从自己的实践出发，尽可能清楚的回答这两个问题。确实，相对于敏捷开发红遍大江南北的状况而言，对敏捷测试的讨论则低调得多。敏捷联盟定义了敏捷的4个价值声明，以及伴随的12条支持原则，这12条原则中没有一条单独提到测试。这是不是意味着测试在敏捷开发中并不重要呢？实际上，如果仔细研读敏捷的12个原则，以及各种不同的敏捷实践，就会发现，测试在敏捷开发中占有非常重要的地位。无论是原则中的“频繁交付”，还是对“可工作的软件”的度量，或是敏捷开发实践中的“测试驱动开发”，“行为驱动开发”，都离不开测试的支持。在本人看来，敏捷开发中不把测试单独拿出来描述的原因，恰恰是因为在敏捷开发中</summary><published>2010-12-15T09:02:00Z</published><updated>2010-12-15T09:02:00Z</updated><author><name>关河</name><uri>http://www.cnblogs.com/guanhe/</uri></author><link rel="alternate" href="http://www.cnblogs.com/guanhe/archive/2010/12/15/agiletesting1.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/guanhe/archive/2010/12/15/agiletesting1.html"/><content type="html">&lt;div&gt;&lt;span style="font-family: 'Times New Roman'; line-height: normal; font-size: medium; border-collapse: collapse; "&gt;&lt;p style="margin-left: 36pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;span style="font-size: 10pt; font-family: Verdana; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;&lt;br /&gt;本文已经首发于&lt;/span&gt;&lt;a href="http://www.infoq.com/cn" target="_blank" style="color: #0000cc; "&gt;&lt;span style="font-size: 10pt; font-family: Verdana; color: #000099; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap; "&gt;InfoQ中文站&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 10pt; font-family: Verdana; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;，版权所有，原文为《XXX》，&lt;wbr&gt;如需转载，请务必附带本声明，谢谢。 &lt;/span&gt;&lt;/p&gt;&lt;p style="margin-left: 36pt; margin-top: 0pt; margin-bottom: 0pt; "&gt;&lt;a href="http://www.infoq.com/cn" target="_blank" style="color: #0000cc; "&gt;&lt;span style="font-size: 10pt; font-family: Verdana; color: #000099; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap; "&gt;InfoQ中文站&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 10pt; font-family: Verdana; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;是一个面向中高端技术人员的在线独立社区，&lt;wbr&gt;为Java、.NET、Ruby、SOA、敏捷、&lt;wbr&gt;架构等领域提供及时而有深度的资讯、高端技术大会如&lt;/span&gt;&lt;a href="http://www.qconbeijing.com/" target="_blank" style="color: #0000cc; "&gt;&lt;span style="font-size: 10pt; font-family: Verdana; color: #000099; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap; "&gt;QCon&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 10pt; font-family: Verdana; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt; 、线下技术交流活动&lt;/span&gt;&lt;a href="http://www.infoq.com/cn/qclub/" target="_blank" style="color: #0000cc; "&gt;&lt;span style="font-size: 10pt; font-family: Verdana; color: #000099; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap; "&gt;QClub&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 10pt; font-family: Verdana; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;、免费迷你书下载如&lt;/span&gt;&lt;a href="http://www.infoq.com/cn/architect/" target="_blank" style="color: #0000cc; "&gt;&lt;span style="font-size: 10pt; font-family: Verdana; color: #000099; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: underline; vertical-align: baseline; white-space: pre-wrap; "&gt;《架构师》&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: 10pt; font-family: Verdana; color: #000000; background-color: transparent; font-weight: normal; font-style: normal; text-decoration: none; vertical-align: baseline; white-space: pre-wrap; "&gt;等。&amp;#8203;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;div&gt;&lt;span style="border-collapse: separate; font-family: Lucida, 'Lucida Grande', Arial, 宋体, sans-serif; line-height: 16px; font-size: 10.8333px; "&gt;&lt;p&gt;&lt;span style="font-size: 10pt; "&gt;在与不少测试从业人员讨论到敏捷的时候，被问得最多的大约是两个问题：&amp;#8220;到底什么是敏捷软件测试？&amp;#8221;，&amp;#8220;敏捷软件开发还需要测试工程师吗？&amp;#8221;。前一个问题是对于敏捷测试本身定义的疑问，第二个问题则是对敏捷开发将测试工程师排除在外的担心。其实，在探寻这两个问题答案的过程中，我们可以更清晰的了解敏捷软件开发中测试的工作定义，测试价值观，以及敏捷开发中开发与测试工程师的配合。鉴于这两个问题的意义，在本敏捷测试专栏的第一篇文章中，本人尝试从自己的实践出发，尽可能清楚的回答这两个问题。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt; "&gt;确实，相对于敏捷开发红遍大江南北的状况而言，对敏捷测试的讨论则低调得多。敏捷联盟定义了敏捷的4个价值声明，以及伴随的12条支持原则，这12条原则中没有一条单独提到测试。这是不是意味着测试在敏捷开发中并不重要呢？实际上，如果仔细研读敏捷的12个原则，以及各种不同的敏捷实践，就会发现，测试在敏捷开发中占有非常重要的地位。无论是原则中的&amp;#8220;频繁交付&amp;#8221;，还是对&amp;#8220;可工作的软件&amp;#8221;的度量，或是敏捷开发实践中的&amp;#8220;测试驱动开发&amp;#8221;，&amp;#8220;行为驱动开发&amp;#8221;，都离不开测试的支持。在本人看来，敏捷开发中不把测试单独拿出来描述的原因，恰恰是因为在敏捷开发中，测试不再是一个单独的、和开发独立的过程，而是变成了驱动开发、衡量产出的主要的手段，成为了敏捷开发中所有工程师在工作时必须时刻考虑和实践的一个部分。简而言之，敏捷软件测试更多的是一种理念，而非过程。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt; "&gt;既然是这样，为什么我们还要在这个专栏中专门来讨论&amp;#8220;敏捷软件测试&amp;#8221;？本人接触过不少软件开发和测试工程师，他们所处的组织有的正在努力向敏捷开发转型，有的已经实践了一段实践的敏捷开发，但由于由来已久的工作习惯，他们中的绝大多数并不能自觉的认识到测试在敏捷开发中的关键作用，而是有意无意的将测试仍然看作是与开发截然分开的&amp;#8220;下一个阶段&amp;#8221;，导致在实践敏捷开发的过程中遇到种种问题：要么是忽略了代码质量，导致在频繁的迭代过程中，每一个迭代的问题层出不穷；或是沿用原有的方法安排对系统的系统测试，导致测试团队疲于奔命，却总也赶不上开发所要求的进度。在这种情况下，专门来讨论敏捷软件开发中的测试，也就是敏捷软件测试的话题，对这些工程师应该会有一些帮助。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt; "&gt;那么，到底什么是敏捷软件测试？很难给敏捷测试下一个精确、完善的定义，在本人看来，接纳了敏捷的核心价值观（沟通，简单，反馈，勇气，尊重），在敏捷软件开发过程中开展的测试就可以被称作是敏捷软件测试。因此，敏捷软件测试并不是一个与敏捷软件开发同一层次的划分，而是敏捷软件开发中的一部分，与传统的测试不同，敏捷软件测试并不是一个独立的过程，相反，它与整个敏捷开发中的其他活动交织在一起，处处都能看到它的影子。由于敏捷软件测试并不倾向于一个单独的过程定义，本人拟从敏捷软件测试与传统测试观点的比较、敏捷软件测试中采用的方法、测试工程师在敏捷软件测试过程中的工作等方面来阐述之。在这篇文章中，我们主要从宏观的角度来描述敏捷软件测试，而在本专栏的后续文章中，我们将对敏捷软件测试中采用的方法、工程师在敏捷软件测试中的工作内容等进行进一步的描述。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt; "&gt;敏捷软件测试是建立在敏捷核心价值观的基础上，为了更生动的描述其与传统软件测试的区别，本人从自己的实践经验出发，尝试给出包含了本人认为包含了敏捷测试关键要素的&amp;#8220;敏捷测试检查表&amp;#8221;：&lt;/span&gt;&lt;/p&gt;&lt;table cellspacing="0" cellpadding="0" border="1px"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td width="83" valign="top" style="font-size: small; "&gt;&lt;p&gt;&lt;strong&gt;项目&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;&lt;td width="290" valign="top" style="font-size: small; "&gt;&lt;p&gt;&lt;strong&gt;检查点&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;&lt;td width="251" valign="top" style="font-size: small; "&gt;&lt;p&gt;&lt;strong&gt;注释&lt;/strong&gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td width="83" valign="top" style="font-size: small; "&gt;&lt;p&gt;团队&lt;/p&gt;&lt;/td&gt;&lt;td width="290" valign="top" style="font-size: small; "&gt;&lt;ul&gt;&lt;li&gt;测试工程师是否与开发工程师建立了紧密联系？&lt;/li&gt;&lt;li&gt;测试工程师是否与客户建立和紧密联系？&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;td width="251" valign="top" style="font-size: small; "&gt;&lt;ul&gt;&lt;li&gt;是否参加每日站立会议？是否与开发工程师可以展开随时的，面对面的，对等的讨论？&lt;/li&gt;&lt;li&gt;是否保持和客户的良好沟通？是否和客户一起维护良好定义的验收测试？&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td width="83" valign="top" style="font-size: small; "&gt;&lt;p&gt;反馈&lt;/p&gt;&lt;/td&gt;&lt;td width="290" valign="top" style="font-size: small; "&gt;&lt;ul&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;/ul&gt;&lt;/td&gt;&lt;td width="251" valign="top" style="font-size: small; "&gt;&lt;ul&gt;&lt;li&gt;使用Dashboard、燃尽图等方式展示当前工作与可交付产品之间的距离&lt;/li&gt;&lt;li&gt;建立单元测试覆盖率等度量指标&lt;/li&gt;&lt;li&gt;使用持续集成或频繁的构建让开发工程师快速得到提交代码的质量反馈&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td width="83" valign="top" style="font-size: small; "&gt;&lt;p&gt;质量文化&lt;/p&gt;&lt;/td&gt;&lt;td width="290" valign="top" style="font-size: small; "&gt;&lt;ul&gt;&lt;li&gt;是否建立了开发与测试工程师共享质量目标的原则？&lt;/li&gt;&lt;li&gt;团队是否注重开发质量，并在工作中尽可能保证高的开发/代码质量？&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;td width="251" valign="top" style="font-size: small; "&gt;&lt;ul&gt;&lt;li&gt;共享质量目标意味着质量责任由所有工程师共同承担&lt;/li&gt;&lt;li&gt;不仅关注最终的产出，不断对代码进行重构，保证代码质量&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td width="83" valign="top" style="font-size: small; "&gt;&lt;p&gt;开发测试&lt;/p&gt;&lt;/td&gt;&lt;td width="290" valign="top" style="font-size: small; "&gt;&lt;ul&gt;&lt;li&gt;是否进行了充分的开发测试？&lt;/li&gt;&lt;li&gt;是否设立了持续集成环境，并以持续集成的结果作为能够继续提交代码和发布的条件？&lt;/li&gt;&lt;li&gt;是否建立了足够多的自动化测试，以及在设计时关注自动化测试的要求？&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;td width="251" valign="top" style="font-size: small; "&gt;&lt;ul&gt;&lt;li&gt;开发测试应该建立一定的测试覆盖率标准，例如，在单元测试这个级别上，建立60%或80%的覆盖率要求&lt;/li&gt;&lt;li&gt;通过使用TDD、BDD等技术，保证产品和代码的可测试性&lt;/li&gt;&lt;li&gt;建立足够多的自动化测试，保证测试能够满足快速迭代的要求&lt;/li&gt;&lt;/ul&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;&lt;span style="font-size: 10pt; "&gt;检查表提到了&amp;#8220;团队&amp;#8221;、&amp;#8220;反馈&amp;#8221;、&amp;#8220;质量文化&amp;#8221;和&amp;#8220;开发测试&amp;#8221;四个方面的内容，在本人看来，这四个方面体现的就是敏捷软件测试与传统软件测试的最大的不同。传统软件测试关注的是通过尽可能完备的&amp;#8220;覆盖&amp;#8221;去发现尽可能多的问题，把测试和开发当成是两个独立的过程，测试是对开发阶段产生成果的&lt;/span&gt;&lt;strong style="font-size: 10pt; "&gt;验证&lt;/strong&gt;。&lt;span style="font-size: 10pt; "&gt;而敏捷软件测试则建立了一种不同的质量文化：测试的目的是为了保证产品快速发布，也就是对生产率本身的提高。基于&amp;#8220;&lt;/span&gt;&lt;strong style="font-size: 10pt; "&gt;验证&lt;/strong&gt;&lt;span style="font-size: 10pt; "&gt;&amp;#8221;的出发点必然会要求测试与开发的独立，以及尽可能&amp;#8220;客观&amp;#8221;和&amp;#8220;完备&amp;#8221;的度量产品质量；而基于&amp;#8220;&lt;/span&gt;&lt;strong style="font-size: 10pt; "&gt;生产率&lt;/strong&gt;&lt;span style="font-size: 10pt; "&gt;&amp;#8221;的出发点则要求建立敏捷的团队，要求测试与开发尽可能紧密，要求建立具有高度可测试性的软件，以及基于这些的高度自动化测试。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt; "&gt;在检查表列出的所有项目中，&amp;#8220;质量文化&amp;#8221;是基础，&amp;#8220;团队&amp;#8221;是敏捷软件测试得以实施的条件，&amp;#8220;反馈&amp;#8221;和&amp;#8220;开发测试&amp;#8221;则是敏捷软件测试的具体方法。当然，你可以可以从敏捷的核心价值观来阶段这些项目：&amp;#8220;团队&amp;#8221;关注的是&lt;/span&gt;&lt;strong style="font-size: 10pt; "&gt;沟通&lt;/strong&gt;&lt;span style="font-size: 10pt; "&gt;与&lt;/span&gt;&lt;strong style="font-size: 10pt; "&gt;尊重&lt;/strong&gt;&lt;span style="font-size: 10pt; "&gt;；&amp;#8220;反馈&amp;#8221;直接对应于&lt;/span&gt;&lt;strong style="font-size: 10pt; "&gt;反馈&lt;/strong&gt;&lt;span style="font-size: 10pt; "&gt;；&amp;#8220;质量文化&amp;#8221;基于&lt;/span&gt;&lt;strong style="font-size: 10pt; "&gt;勇气&lt;/strong&gt;&lt;span style="font-size: 10pt; "&gt;（承担质量责任的勇气）与&lt;/span&gt;&lt;strong style="font-size: 10pt; "&gt;尊重&lt;/strong&gt;&lt;span style="font-size: 10pt; "&gt;；而&amp;#8220;开发测试&amp;#8221;则是&lt;/span&gt;&lt;strong style="font-size: 10pt; "&gt;反馈&lt;/strong&gt;&lt;span style="font-size: 10pt; "&gt;与&lt;/span&gt;&lt;strong style="font-size: 10pt; "&gt;简单&lt;/strong&gt;&lt;span style="font-size: 10pt; "&gt;的具体体现。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt; "&gt;另一个在本文最初提出来的问题是：&amp;#8220;敏捷软件开发还需要测试工程师吗？&amp;#8221;，对这个问题，业界有不同的观点。有人认为需要，因为总有一些是需要测试工程师的技能完成的工作；当然，也有人认为不需要，因为敏捷开发中的测试注重开发测试与自动化测试，开发工程师就可以自己搞定与测试相关的工作。在实践中，那些大规模实践敏捷开发的公司（例如Google），倾向于在组织中设置数量较少的测试工程师，在项目中分配较少的测试资源，甚至对某些项目，完全不使用测试工程师。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 10pt; "&gt;就我的个人实践经验，对大部分的项目，尤其是为明确的&lt;/span&gt;&lt;strong style="font-size: 10pt; "&gt;客户&lt;/strong&gt;&lt;span style="font-size: 10pt; "&gt;开发的项目，需要在敏捷开发团队中设置专职的测试工程师，因为：&lt;/span&gt;&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-size: 10pt; "&gt;测试与开发具有不同的思维方式：测试更注重全面的验证和检查一个系统，而开发工程师往往很难在大的范围内建立这样的思维方式。因此，无论是从系统的层面验证产品，或是从应用系统的角度发现值得测试和验证的点（access point），专职的测试工程师都更有效。&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: 10pt; "&gt;专职的测试工程师能够更关注于测试基础，建立测试需要的基础架构：由于测试工程师具有更好的对测试的理解，通常他们能够更多的考虑测试的需求而开发适合项目的测试基础架构（自动化测试框架），而开发工程师可以使用这些框架来建立面向功能或代码的测试。&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;/div&gt;&lt;span  style="border-collapse: separate; font-family: Lucida, 'Lucida Grande', Arial, 宋体, sans-serif; line-height: 16px; font-size: 10pt; "&gt;但是，不得不说的是，敏捷开发对开发和测试工程师都提出了更要的要求，尤其是对测试工程师而言，传统的只能&amp;#8220;精确模拟用户操作&amp;#8221;的测试工程师，因为不能为产品带来生产率的提升，在敏捷开发的团队中，很难有所作为。在本专栏的后续文章中，我们会进一步讨论测试工程师在敏捷软件开发中的工作和任务。&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;&lt;img src="http://www.cnblogs.com/guanhe/aggbug/1907019.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/guanhe/archive/2010/12/15/agiletesting1.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/guanhe/archive/2010/11/15/1878034.html</id><title type="text">对Singleton类解依赖</title><summary type="text">上周六在杭州的《互联网软件测试大会》上做演讲的时候提到可测试性的话题，顺手举了一个例子：“B类存在对A类的依赖，A类是一个Singleton类，B类使用到了A类中的一个需要被mock的函数，这种情况下如何处理？” 本来，这是《修改代码的艺术》上曾经提到的一个典型模式，该书中有非常详细的描述。但今天收到某位听众的邮件，问这个问题应该怎么回答。 正好好久没有写过blog了，于是顺手写了一段简单的代码来说明这个问题。</summary><published>2010-11-15T15:14:00Z</published><updated>2010-11-15T15:14:00Z</updated><author><name>关河</name><uri>http://www.cnblogs.com/guanhe/</uri></author><link rel="alternate" href="http://www.cnblogs.com/guanhe/archive/2010/11/15/1878034.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/guanhe/archive/2010/11/15/1878034.html"/><content type="html">&lt;p&gt;上周六在杭州的《互联网软件测试大会》上做演讲的时候提到可测试性的话题，顺手举了一个例子：&amp;#8220;B类存在对A类的依赖，A类是一个Singleton类，B类使用到了A类中的一个需要被mock的函数，这种情况下如何处理？&amp;#8221; 本来，这是《修改代码的艺术》上曾经提到的一个典型模式，该书中有非常详细的描述。但今天收到某位听众的邮件，问这个问题应该怎么回答。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;正好好久没有写过blog了，于是顺手写了一段简单的代码来说明这个问题。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;问题：&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;类Singleton是一个单件类，该类实现了一个名为getUserName()的函数，getUserName函数需要连接到数据库并从数据库中取出用户名称。类DependsOnSingleton类是被测类，该类中的sayHello函数使用到了Singleton类的getUserName函数，在对DependsOnSingleton类进行单元测试的时候，显然我们并不想设置一个真正的数据库，所以最理想的情况是使用mock方式得到一个可以被控制的Singleton类的getUserName函数的实现。如果Singleton类不是一个单件类，这件事情非常简单，使用接口提取的方法从Singleton类提取接口，然后就可以使用mock技术了。但由于Singleton是一个单件类，这件事情就比较棘手了：Singleton.getInstance会返回一个由getInstance自身逻辑决定的Singleton对象，这样就没法直接塞入一个mock对象了。&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;代码：&lt;/strong&gt;&lt;/p&gt;&lt;div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding-left:5px;padding-right:5px;" onclick="cnblogs_code_show('3ee4c89f-bd00-4b03-afd5-6e44251e3127')"&gt;&lt;img src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif"  id="code_img_opened_8373d73a-b286-4a22-86ab-b0c7cb5a5155" onclick="cnblogs_code_hide('8373d73a-b286-4a22-86ab-b0c7cb5a5155',event)"&gt;&lt;div id="cnblogs_code_open_8373d73a-b286-4a22-86ab-b0c7cb5a5155"&gt;&lt;div&gt;&lt;!--&lt;br/ /&gt;&lt;br/ /&gt;Code highlighting produced by Actipro CodeHighlighter (freeware)&lt;br/ /&gt;http://www.CodeHighlighter.com/&lt;br/ /&gt;&lt;br/ /&gt;--&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;1&lt;/span&gt;&amp;nbsp;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;junit.framework.Assert;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;2&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;junit.framework.TestCase;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;3&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;4&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;import&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;org.easymock.EasyMock;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;5&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;6&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;TestDependsOnSingleton&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;extends&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;TestCase&amp;nbsp;{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;7&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;testSayHello()&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;throws&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;Exception{&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;8&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Singleton&amp;nbsp;depend&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;EasyMock.createMock(Singleton.&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;&amp;nbsp;9&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Singleton.setTestingInstance(depend);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;10&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;11&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EasyMock.expect(depend.getUserName()).andReturn(&lt;/span&gt;&lt;span style="color: #000000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;Dennis&lt;/span&gt;&lt;span style="color: #000000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;12&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EasyMock.replay(depend);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;13&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;14&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DependsOnSingleton&amp;nbsp;itu&amp;nbsp;&lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;nbsp;DependsOnSingleton();&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;15&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Assert.assertEquals(&lt;/span&gt;&lt;span style="color: #000000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;Hi,&amp;nbsp;Dennis&lt;/span&gt;&lt;span style="color: #000000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;,&amp;nbsp;itu.sayHello());&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;16&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;EasyMock.verify(depend);&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;17&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #008080;"&gt;18&lt;/span&gt;&amp;nbsp;&lt;span style="color: #000000;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/guanhe/aggbug/1878034.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/guanhe/archive/2010/11/15/1878034.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/guanhe/archive/2010/05/20/1740149.html</id><title type="text">我们为什么要使用开源测试工具？</title><summary type="text">为什么要使用开源测试工具？作为一个开源测试工具的推崇者，我经常被问到这个问题。许多测试工程师对商业测试工具情有独钟，总觉得商业测试工具既好用又强大，而开源测试工具功能弱，缺陷多，而且不好用。对开源测试工具的偏见一方面来自于商业测试工具的宣传，另一方面，也来自部分测试工程师在使用开源测试工具过程中的心态。在本人所在的组织中，公司内使用的绝大多数测试工具或多或少都有开源测试工具的影子，从开源测试工具在本组织的应用中看来，使用开 源测试工具带来的优势非常明显…</summary><published>2010-05-20T08:23:00Z</published><updated>2010-05-20T08:23:00Z</updated><author><name>关河</name><uri>http://www.cnblogs.com/guanhe/</uri></author><link rel="alternate" href="http://www.cnblogs.com/guanhe/archive/2010/05/20/1740149.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/guanhe/archive/2010/05/20/1740149.html"/><content type="html">&lt;div &gt;&#xD;
			&lt;p&gt;为什么要使用开源测试工具？&lt;/p&gt;&#xD;
&lt;p&gt;作为一个开源测试工具的推崇者，我经常被问到这个问题。许多测试工程师对商业测试工具情有独钟，总觉得商业测试工具既好用又强大，而开源测试工具功&#xD;
能弱，缺陷多，而且不好用。对开源测试工具的偏见一方面来自于商业测试工具的宣传，另一方面，也来自部分测试工程师在使用开源测试工具过程中的心态。&lt;span id="more-37"&gt;&lt;/span&gt;&lt;/p&gt;&#xD;
&lt;p&gt;在本人所在的组织中，公司内使用的绝大多数测试工具或多或少都有开源测试工具的影子，从开源测试工具在本组织的应用中看来，使用开 &#xD;
源测试工具带来的优势非常明显：&lt;/p&gt;&#xD;
&lt;ol&gt;&lt;li&gt;极低的License费用：这个是显而易见的一个优点。设想，如果公司需要对Web应用进行上万并发的性能测试，使用LoadRunner等商业&#xD;
 测试工具的费用绝对不是一个小数字；&lt;/li&gt;&lt;li&gt;更高的集成度：大多数商业测试工具本身也号称提供了自己的&amp;#8220;完整解决方案&amp;#8221;，但商业测试工具往往只能覆盖测试中一部分的领域，对于集成测试或是针&#xD;
 对应用的接口测试方面，商业测试工具很难提供企业需要的好的解决方案。这样一来，这部分企业自己建立的自动化测试工具就很难被集成到商业测试工具形成的&#xD;
 &amp;#8220;测试框架&amp;#8221;中。而采用开源测试工具解决方案的话，这个问题根本就不是问题；&lt;/li&gt;&lt;li&gt;更适合企业需要：出于商业利益的考虑，商业测试工具总是试图覆盖&amp;#8220;最大的用户群体&amp;#8221;，因此商业测试工具往往是那种&amp;#8220;谁都可以用&amp;#8221;，但&amp;#8220;在哪里都不&#xD;
 是特别好用&amp;#8221;的那一类工具，反之，开源测试工具在这方面具有显然的优势；&lt;/li&gt;&lt;li&gt;更适合提高企业的测试技术水平：许多开源测试工具中都体现和非常值得学习的测试思想和方法，由于开源本身的特性，这些思想和方法是非常容易通过对&#xD;
 开源测试工具的研究来进行学习和掌握的。&lt;/li&gt;&lt;/ol&gt;&#xD;
&lt;p&gt;以JMeter这个工具为例，我在许多场合下向测试工程师推荐这个性能测试工具，的确也有一些测试工程师尝试了这个工具，但从他们那里，我得到的反&#xD;
馈往往是：&amp;#8220;为什么这个工具的界面这么难看？&amp;#8221;，&amp;#8220;为什么这个工具没有xx功能（与商业测试工具相比）？&amp;#8221;，&amp;#8220;为什么这个工具没有漂亮的文档？&amp;#8221;。许多人&#xD;
在第一印象上便认为，这个工具比不上商业测试工具，然后就弃之如敝屐。实际上真是这样吗？我所在的组织的性能测试几乎完全依赖于JMeter，通过在&#xD;
JMeter上扩展的图表功能，支持集群等功能，通过少量的代码，JMeter可以生成比商业测试工具更加漂亮，更加有价值的图表，而且，更重要的&#xD;
是，100%适合我们自己的环境需要。&lt;/p&gt;&#xD;
&lt;p&gt;当然，除了看到开源测试工具的优点，我们也应该看到开源测试工具的不便之处。与商业测试工具相比，开源测试工具在产品的用户交互性，易用性，易学习&#xD;
性方面显然 &#xD;
不是那么好（当然，在我看来，这方面不是测试工具的重点）。因此，要在组织中使用和引入开源测试工具的话，对组织中的成员，组织环境是有一定的要求的。&lt;/p&gt;&#xD;
&lt;p&gt;就本人的经验而言，许多目前的开源测试工具，例如Mantis、Testlink、JMeter、Selenium/Webdriver、 &#xD;
xUnit等都已经是非常成熟的测试工具，拥有了大量的使用者，也有许多成功的应用实例，本人的实践已经充分证明了这些工具在实际工作中能够带来的收益：&#xD;
 &#xD;
即使只是简单的使用开源测试工具去完成某个特定的任务，或是用来搭建公司内部的测试管理平台，也能从这些工具中受益不少；更何况开源测试工具拥有众多的开&#xD;
 &#xD;
发者，处于不断的完善和提高中，具有良好的扩展性，给你充分修改和改造的自由，从这个角度来说，如果你拥有足够的资源，想要打造属于自己的测试平台，开源&#xD;
 测试工具绝对是一个好的平台。&lt;/p&gt;&#xD;
		&lt;/div&gt;&lt;img src="http://www.cnblogs.com/guanhe/aggbug/1740149.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/guanhe/archive/2010/05/20/1740149.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/guanhe/archive/2010/01/08/1642301.html</id><title type="text">在第四届软件质量年会上的演讲（视频与PPT）</title><summary type="text">在第四届软件质量年会上的演讲，标题是”让测试敏捷起来“。 下面的链接是InfoQ上的视频和PPT：http://www.infoq.com/cn/presentations/duannian-agile-test</summary><published>2010-01-08T07:59:00Z</published><updated>2010-01-08T07:59:00Z</updated><author><name>关河</name><uri>http://www.cnblogs.com/guanhe/</uri></author><link rel="alternate" href="http://www.cnblogs.com/guanhe/archive/2010/01/08/1642301.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/guanhe/archive/2010/01/08/1642301.html"/></entry><entry><id>http://www.cnblogs.com/guanhe/archive/2009/11/14/1603133.html</id><title type="text">敏捷测试感悟（之二）</title><summary type="text">在本系列的第一部分中，我们简要回顾了敏捷开发，以及敏捷测试与传统测试的不同。在第一部分中，我们特别提到，敏捷测试的要点之一就是，不依据于角色而是依据于任务来考虑整个开发过程中的测试。但是，对一个开发组织来说，组织中一定存在开发工程师和测试工程师的角色划分，作为一个敏捷团队中的测试工程师，他的主要工作职责是什么呢？或者说，他可以在哪些工作上发挥自己的作用呢？</summary><published>2009-11-14T13:19:00Z</published><updated>2009-11-14T13:19:00Z</updated><author><name>关河</name><uri>http://www.cnblogs.com/guanhe/</uri></author><link rel="alternate" href="http://www.cnblogs.com/guanhe/archive/2009/11/14/1603133.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/guanhe/archive/2009/11/14/1603133.html"/></entry><entry><id>http://www.cnblogs.com/guanhe/archive/2009/11/06/1597628.html</id><title type="text">敏捷测试感悟（之一）</title><summary type="text">Agile testing（敏捷测试）基本上是伴随着敏捷开发的概念成长起来的，但在受关注程度上，远远不及敏捷开发本身。自然，开发队伍从数量和活跃度上来讲大于测试队伍，是其中的一个原因；除了这个原因之外，“敏捷测试究竟如何在项目中发挥作用”这个问题可能也是导致敏捷测试概念的流行度远远不如敏捷开发的原因之一。在敏捷环境中工作了几年之后，对敏捷测试有了一些感悟，希望和大家分享。</summary><published>2009-11-06T11:03:00Z</published><updated>2009-11-06T11:03:00Z</updated><author><name>关河</name><uri>http://www.cnblogs.com/guanhe/</uri></author><link rel="alternate" href="http://www.cnblogs.com/guanhe/archive/2009/11/06/1597628.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/guanhe/archive/2009/11/06/1597628.html"/></entry><entry><id>http://www.cnblogs.com/guanhe/archive/2009/06/01/1493789.html</id><title type="text">《Google API大全：编程·开发·实例》一书将在本周末的GDD（Google开发者大会）上首发</title><summary type="text">我也是本书的作者之一，虽然只在其中占了两章的内容：）《Google API大全：编程·开发·实例》这本书是国内的第一本较为完整的介绍Google API的书，内容囊括了所有主要的Google API，并用大量的实例展示了Google API的应用方法。在这本书的首页上，我选择了“Google是一种生活方式”作为我对这本书的推荐语。“Google是一种生活方式”，此言不虚，现在的网名，或多或少的被搜索引擎影响着使用Internet的方式，Google在其中的贡献不言而喻。当然，对我而言，“Google是一种生活方式”更有所指，Google的产品一向以良好的编程接口著称，对于以技术工作为主的工程师们，基于Google的产品构建自己的产品，更是一件值得一试的事情。《Google API大全：编程·开发·实例》作者序：</summary><published>2009-06-01T07:46:00Z</published><updated>2009-06-01T07:46:00Z</updated><author><name>关河</name><uri>http://www.cnblogs.com/guanhe/</uri></author><link rel="alternate" href="http://www.cnblogs.com/guanhe/archive/2009/06/01/1493789.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/guanhe/archive/2009/06/01/1493789.html"/></entry><entry><id>http://www.cnblogs.com/guanhe/archive/2009/03/11/1408595.html</id><title type="text">4月份到上海出差</title><summary type="text">4月份到上海出差，有机会的话希望能够和上海的测试同行们见见面：）不知道有没有感兴趣的朋友？我到上海会住在南京路附近。&amp;#160;</summary><published>2009-03-11T03:39:00Z</published><updated>2009-03-11T03:39:00Z</updated><author><name>关河</name><uri>http://www.cnblogs.com/guanhe/</uri></author><link rel="alternate" href="http://www.cnblogs.com/guanhe/archive/2009/03/11/1408595.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/guanhe/archive/2009/03/11/1408595.html"/></entry><entry><id>http://www.cnblogs.com/guanhe/archive/2008/09/11/1289078.html</id><title type="text">拿到了TD的3G测试手机</title><summary type="text">从小到大，除非是人人都有奖的那种，否则我就和抽奖无缘。一直以为这就是我的命，没想到，居然有例外——几个月前申请TD的3G社会化测试，居然中彩被抽中了，太难得了。我拿到的是新邮通的 N269 这一款手机，样子倒是中规中矩的长方形，不过不知道怎么回事，看到这个手机的第一眼就觉得有典型的山寨机风格。到今天为止大约使用了一周左右的该手机，接听和打了几个电话，和另一个测试用例视频了一次，用手机浏览器上网浏览了一些网站，用笔记本连接手机上网，总体感觉是，除了连接笔记本上网感觉上比GPRS和CDMA 1X明显快之外，别的3G的优势就没有明显的体会了。</summary><published>2008-09-11T05:59:00Z</published><updated>2008-09-11T05:59:00Z</updated><author><name>关河</name><uri>http://www.cnblogs.com/guanhe/</uri></author><link rel="alternate" href="http://www.cnblogs.com/guanhe/archive/2008/09/11/1289078.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/guanhe/archive/2008/09/11/1289078.html"/></entry><entry><id>http://www.cnblogs.com/guanhe/archive/2008/05/16/1200041.html</id><title type="text">天佑中华</title><summary type="text">这些天来，没有什么比得上对四川地震的关注，心里一直被塞得满满的，同情，难过，悲伤。&#xD;&#xD;恨不能和那些可爱的救援者一样，在现场亲手挽救同胞的生命，可是理智却告诉我，对他们最大的帮助是做我能够做的。&#xD;&#xD;看着新闻中的英雄们，在网站上读着感人至深的故事，看着那些放弃了自己的休息时间忙碌着筹集捐款，组织献血，人肉搜索，尽自己能力帮助他人的同事们，感动到无语。&#xD;&#xD;逝者已矣，祝他们在天堂安好。我们能做的，是为那些需要帮助的人提供尽可能的帮助。看到网上很多和自己亲人失散的朋友焦急地打听自己亲人的消息，或许可以尝试这个：&#xD;&#xD;http://www.google.cn/intl/zh-CN/qinren/cse.html&#xD;&#xD;我在blog的右侧也加上了这个搜索框，即使这样只能帮到一个朋友，我也会发自内心的感到高兴。&#xD;&#xD;太沉重，不能再说些什么了，我们经历了灾难，受难的人们正在经历苦难，但只要希望在，就能期待光明。&#xD;&#xD;天佑中华！&#xD;&#xD;</summary><published>2008-05-16T02:29:00Z</published><updated>2008-05-16T02:29:00Z</updated><author><name>关河</name><uri>http://www.cnblogs.com/guanhe/</uri></author><link rel="alternate" href="http://www.cnblogs.com/guanhe/archive/2008/05/16/1200041.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/guanhe/archive/2008/05/16/1200041.html"/></entry></feed>
