⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 200602281036115.html

📁 软件工程的红包书
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<P>3、它是一种编写文档的行为。<BR>&nbsp;&nbsp;&nbsp; 单元测试是一种无价的文档,它是展示函数或类如何使用的最佳文档。这份文档是可编译、可运行的,并且它保持最新,永远与代码同步。</P>
<P>4、它具有回归性。<BR>&nbsp;&nbsp;&nbsp; 自动化的单元测试避免了代码出现回归,编写完成之后,可以随时随地的快速运行测试。 </P>
<P><STRONG>单元测试的范畴</STRONG></P>
<P><BR>&nbsp;&nbsp;&nbsp; 如果要给单元测试定义一个明确的范畴,指出哪些功能是属于单元测试,这似乎很难。但下面讨论的四个问题,基本上可以说明单元测试的范畴,单元测试所要做的工作。</P>
<P>1、 它的行为和我期望的一致吗?<BR>&nbsp;&nbsp;&nbsp; 这是单元测试最根本的目的,我们就是用单元测试的代码来证明它所做的就是我们所期望的。</P>
<P>2、 它的行为一直和我期望的一致吗?<BR>&nbsp;&nbsp;&nbsp; 编写单元测试,如果只测试代码的一条正确路径,让它正确走一遍,并不算是真正的完成。软件开发是一个项复杂的工程,在测试某段代码的行为是否和你的期望一致时,你需要确认:在任何情况下,这段代码是否都和你的期望一致;譬如参数很可疑、硬盘没有剩余空间、缓冲区溢出、网络掉线的时候。</P>
<P>3、 我可以依赖单元测试吗?<BR>&nbsp;&nbsp;&nbsp; 不能依赖的代码是没有多大用处的。既然单元测试是用来保证代码的正确性,那么单元测试也一定要值得依赖。</P>
<P>4、 单元测试说明我的意图了吗?<BR>&nbsp;&nbsp;&nbsp; 单元测试能够帮我们充分了解代码的用法,从效果上而言,单元测试就像是能执行的文档,说明了在你用各种条件调用代码时,你所能期望这段代码完成的功能。</P>
<P><STRONG>不写测试的借口</STRONG></P>
<P><BR>&nbsp;&nbsp;&nbsp; 到这里,我们已经列举了使用单元测试的种种理由。也许,每个人都同意,是的,该做更多的测试。这种人人同意的事情还多着呢,是的,该多吃蔬菜,该戒烟,该多休息,该多锻炼……这并不意味着我们中的所有人都会这么去做,不是吗?</P>
<P>1、 编写单元测试太花时间了。<BR>&nbsp;&nbsp;&nbsp; 我们知道,在开发时越早发现BUG,就能节省更多的时间,降低更多的风险。<BR>&nbsp;&nbsp;&nbsp; 下图表摘自&lt;&lt;实用软件度量&gt;&gt;(Capers Jones,McGraw-Hill 1991),它列出了准备测试,执行测试,和修改缺陷所花费的时间(以一个功能点为基准),这些数据显示单元测试的成本效率大约是集成测试的两倍,是系统测试的三倍(参见条形图)。</P>
<P>&nbsp;&nbsp;&nbsp; 术语:域测试(Field test)意思是在软件投入使用以后,针对某个领域所作的所有测试活动。<BR>&nbsp;&nbsp;&nbsp; 如果你仍然认为在编写产品代码的时候,还是没有时间编写测试代码,那么请先考虑下面这些问题:<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1)、对于所编写的代码,你在调试上面花了多少时间。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2)、对于以前你自认为正确的代码,而实际上这些代码却存在重大的bug,你花了多少时间在重新确认这些代码上面。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3)、对于一个别人报告的bug,你花了多少时间才找出导致这个bug 的源码位置。<BR>&nbsp;&nbsp;&nbsp; 回答完这些问题,你一定不再以“太花时间”作为拒绝单元测试的借口。</P>
<P>2、 运行测试的时间太长了。<BR>&nbsp;&nbsp;&nbsp; 合适的测试是不会让这种情况发生的。实际上,大多数测试的执行都是非常快的,因此你在几秒之内就可以运行成千上万个测试。但是有时某些测试会花费很长的时间。这时,需要把这些耗时的测试和其他测试分开。通常可以每天运行这种测试一次,或者几天一次。</P>
<P>3、 测试代码并不是我的工作。<BR>&nbsp;&nbsp;&nbsp; 你的工作就是保证代码能够正确的完成你的行为,恰恰相反,测试代码正是你不可缺少的工作。</P>
<P>4、 我并不清楚代码的行为,所以也就无从测试。<BR>&nbsp;&nbsp;&nbsp; 如果你实在不清楚代码的行为,那么估计现在并不是编码的时候。如果你并不知道代码的行为,那么你又如何知道你编写的代码是正确的呢?</P>
<P>5、 但是这些代码都能够编译通过。<BR>&nbsp;&nbsp;&nbsp; 我们前面已经说过,代码通过编译只是验证它的语法通过。但并不能保证它的行为就一定正确。</P>
<P>6、 公司请我来是为了写代码,而不是写测试。<BR>&nbsp;&nbsp;&nbsp; 公司付给你薪水是为了让你编写产品代码,而单元测试大体上是一个工具,是一个和编辑器、开发环境、编译器等处于同一位置的工具。</P>
<P>7、 如果我让测试员或者QA(Quality Assurance)人员没有工作,那么我会觉得很内疚。</P>
<P>&nbsp;&nbsp;&nbsp; 你并不需要担心这些。请记住,我们在此只是谈论单元测试,而它只是一种针对源码的、低层次的,为程序员而设计的测试。在整个项目中,还有其他的很多测试需要这些人来完成,如:<a href="200604241204115.html" tppabs="http://www.itisedu.com/phrase/200604241204115.html" target="_new">功能测试</a>、<a href="200603282249515.html" tppabs="http://www.itisedu.com/phrase/200603282249515.html" target="_new">验收测试</a>、<a href="200603291559575.html" tppabs="http://www.itisedu.com/phrase/200603291559575.html" target="_new">性能测试</a>、环境测试、有效性测试、正确性测试、正规分析等等。</P>
<P>8、 我的公司并不会让我在真实系统中运行单元测试。<BR>&nbsp;&nbsp;&nbsp; 我们所讨论的只是针对开发者的单元测试。也就是说,如果你可以在其他的环境下(例如在正式的产品系统中)运行这些测试的话,那么它们就不再是单元测试,而是其他类型的测试了。实际上,你可以在你的本机运行单元测试,使用你自己的<a href="200602271218062.html" tppabs="http://www.itisedu.com/phrase/200602271218062.html" target="_new">数据库</a>,或者使用mock 对象。</P>
<P><BR><STRONG>测试代码编写</STRONG></P>
<P><STRONG></STRONG><BR>  多数讲述单元测试的文章都是以Java为例,本文以C++为例,后半部分所介绍的单元测试工具也只介绍C++单元测试工具。下面的示例代码的开发环境是VC6.0。</P>
<P>产品类:<BR><a href="javascript:if(confirm('http://www.itisedu.com/phrase/200604231359565.html  \n\nThis file was not retrieved by Teleport Pro, because it was unavailable, or its retrieval was aborted, or the project was stopped too soon.  \n\nDo you want to open it from the server?'))window.location='http://www.itisedu.com/phrase/200604231359565.html'" tppabs="http://www.itisedu.com/phrase/200604231359565.html" target="_new">class</a> CMyClass <BR>{<BR>public:<BR>&nbsp;&nbsp;&nbsp; int Add(int i, int j);<BR>&nbsp;&nbsp;&nbsp; CMyClass();<BR>&nbsp;&nbsp;&nbsp; virtual ~CMyClass();</P>
<P>private:<BR>&nbsp;&nbsp;&nbsp; int mAge;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //年龄<BR>&nbsp;&nbsp;&nbsp; CString mPhase; //年龄阶段,如"少年","青年"<BR>};</P>
<P>建立对应的测试类CMyClassTester,为了节约编幅,只列出源文件的代码:<BR>void CMyClassTester::CaseBegin()<BR>{<BR>&nbsp;&nbsp;&nbsp; //pObj是CMyClassTester类的成员变量,是被测试类的对象的指针,<BR>&nbsp;&nbsp;&nbsp; //为求简单,所有的测试类都可以用pObj命名被测试对象的指针。<BR>&nbsp;&nbsp;&nbsp; pObj = new CMyClass();<BR>}</P>
<P>void CMyClassTester::CaseEnd()<BR>{<BR>&nbsp;&nbsp;&nbsp; delete pObj;<BR>}<BR>测试类的函数CaseBegin()和CaseEnd()建立和销毁被测试对象,每个测试用例的开头都要调用CaseBegin(),结尾都要调用CaseEnd()。</P>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -