快捷搜索:

测试是一件有趣的事情?真的吗?

测试。憎恶!我不停憎恶做测试。测试(单元测试和功能测试)是防碍“真正”事情的工作。每小我都确信自己的代码是完美的,不是吗?在确凿必要变动代码的极少数事故中,注释编写得如斯之好,乃至每小我都能领会此中的含义。我必要前进(或许还必要作一些咨询)。

在以前的几年里,单元测试已成为我编写软件的核心环节,多亏了一种称为极限编程 (XP) 的简便编程措施(请参阅 参考资本)。这种措施要求我为添加的每个函数编写单元测试,并且要掩护这些测试。假如单元测试掉败,我就无法整合任何代码。跟着代码库的赓续增大年夜,这些测试将使开拓职员能够很有把握地完成变动。

起先,我觉得有了单元测试,就没需要再进行功能测试。噢,又错了。功能测试与单元测试相差甚远。我花了很长一段光阴理解二者的差别,以及若何结合应用两者来改进开拓历程。

本文商量单元测试与功能测试之间的差别。并概述了在日常开拓中应用这两种测试的措施。

测试与开拓历程

测试对付开拓职员极为紧张,您必须在开拓历程中赓续进行测试。测试不应该只属于开拓周期的某个特定阶段。它毫不应该是您将系统交给客户前要完成的着末一项义务。若何才能知道您何时就完成了所有义务呢?若何才能知道对一个小差错的修恰是否破坏了系统的主要功能呢?今朝想像中的系统若何才能演化为实其着实的系统呢?单元测试和功能测试都应该是开拓历程中弗成瓜分的一部分。

单元测试应成为您编写代码的核心环节,当您所做的项目时限很紧并且您盼望节制开拓进度时尤其如斯。因为单元测试是如斯紧张,以是您应该先编写测试,再编写代码。

一套适当的单元测试具有以下功能:

阐明可能的最实用设计 供给类文档的最佳款式 确定一个类何时完成 增强开拓职员对代码的信心 作为快速重构的根基

单元测试创建随系统自然成长的设计文档。再读一遍上一句话。文档随系统 自然成长,这是软件开拓的“圣杯”。有什么措施比经由过程供给一个用例编码集来记录一个类效果更好呢?那便是单元测试:一系列记录类所干事情的用例代码,供给输出节制。这样,因为单元测试必须经由过程,以是设计文档老是最新的。

您应该首先编写测试,然后再编写代码。这样就为要测试的类供给了一种设计,这种设计使您每一时候都只需集中斟酌一小块代码。这种做法也使设计变得不再繁杂。您没有试图为今后着想而实现一些不需要的功能。先编写测试还使您知道该类何时完成。一旦经由过程所有测试,义务也就完成了。

着末,单元测试可使您高度自大,这又会转化为开拓职员的知足度。假如只要变动代码即运行单元测试,您急速就能发明您所做的变动是否对系统造成了破坏。

功能测试比单元测试更紧张,由于功能测试将验证系统是否可以发行了。功能测试以一种有用的要领对您的事情系统进行阐明。一套适当的功能测试具有以下功能:

以有效要领捕获用户需求 增强小组(用户和开拓职员)在系统满意用户需求方面的信心

功能测试以有效要领捕获用户需求。传统开拓经由过程用例来捕获需求。平日,人们评论争论用例并花很长光阴对它们进行细化。他们着末所获得的只是一纸空文。功能测试就像自验证式用例。极限编程措施可解释这一观点。XP Stories 将成为未来用户与开拓职员进行沟通的协议。功能测试就是这种沟通的结果。未经功能测试的 Stories 弗成能很完善。

功能测试填补单元测试留下的空缺,并可增强小组对代码的信心。单元测试遗漏落许多差错。只管它可以供给您所需的整个 代码,但它可能无法供给您所需的整个 系统功能。功能测试将裸露单元测试漏掉的问题。一套适当的自动化功能测试也弗成能捕捉到每个差错,然则它能比最好的单一单元测试捕捉更多的差错。

回页首

单元测试与功能测试

单元测试向开拓职员注解代码 精确履行操作;而功能测试向开拓职员注解代码 履行精确的操作。

单元测试

单元测试是从法度榜样员的角度编写的。它确保类的某个特定措施成功履行一系列特定的义务。每个测试都确保只要给定输入,措施将输出预期的结果。

假如没有测试框架,编写一套可掩护的自动化单元测试险些是弗成能的。在开始编写测试之前,请选择一个小组公认的框架。您将常常性地应用这个框架,是以您最好对它有点好感。极限编程网站供给了几个单元测试框架(请参阅 参考资本 )。我最认识的框架是 JUnit,它专门用来测试 Java 代码。

功能测试

功能测试是从用户的角度编写的。这种测试确保系统履行用户期望它履行的事情。

很多时刻,系统开拓好比修建房屋。只管这种类比不很恰当,但为了理解单元测试与功能测试的差别,我们可以扩充这种类比。单元测试好比房屋修建现场的修建监理员。他关心房屋的各个内部系统,如地基、构架、供电系统和管道设备等。他确保(测试)房屋每一部分的事情都安然、正常,即相符修建阐明。这种环境下,功能测试类似于视察同一修建现场的房东。他假定内部系统将正常运作,并假定修建监理员在履行其义务。房东关心的是住在这所屋子里将会如何。他关心屋子的外不雅若何,各个房间的大年夜小是否相宜,屋子能否满意家庭的必要,以及窗户的位置是否有利于采光。房东对屋子履行功能测试。他从用户的角度斟酌问题。修建监理员对屋子履行单元测试。他从修建工人的角度斟酌问题。

就像单元测试一样,假如没有测试框架,编写一套可掩护的自动化功能测试实际上是弗成能的。JUnit 异常得当编写单元测试;然则,当试图编写功能测试时,它就显得力不从心了。就功能测试而言,没有与 JUnit 相称的框架。也有几种用于功能测试的产品,但我从来没见过它们利用于临盆情况。假如找不到满意您的必要的框架,您就必须创建一个。

无论我们多么擅擅长构建手头的项目,也不管我们正在创建的系统多么机动,假如我们的产品分歧用,那我们便是白搭光阴。是以,功能测试是开拓最紧张的部分。

因为两种测试都必弗成少,您就必要懂得编写它们应遵照的原则。

回页首

若何编写单元测试

刚开始编写单元测试时很轻易恢心。最佳的入手要领便是为 新代码创建单元测试。(只管为现有代码创建单元测试对照艰苦,但并非无法实现)。首先重新代码动手,待您习气了全部历程今后,再针对现有代码创建测试法度榜样。

如上文所述,应该首先编写单元测试,然后再编写这些单元测试要测试的代码。若作甚尚不存在的代码编写测试呢?问得异常好。掌握这一措施必要 90% 的思维加 10% 的技巧。我的意思是,您只需假定您正在为其编写测试的类已经存在。接下来的义务便是编写测试。起先会犯很多语法差错,但您先别管它。这一步您要做的便是定义该类要实现的接口。下一步便是运行您的单元测试,修正语法差错(即,编写一个类,使它实现您的测试刚定义的接口),并再次运行测试。重复这一历程,每次仅编写修正故障的代码。运行测试,直到测试整个经由过程为止。一旦经由过程整个单元测试,代码也就完成了。

一样平常而言,类的每个公共措施都应有一个单元测试。然则,功能简单的措施(例如,getter 措施和 setter 措施)不必要单元测试,除非它们以某种特其余要领进行获取和设置。应该遵照下面这条很好的原则:即只要您觉得有需要对代码中的某个行径加注,就编写一个单元测试。假如您像其他许多法度榜样员一样不爱好为代码加注,则单元测试是记录代码行径的一种措施。

将单元测试与被测试的相关类放在同一个包内。这种组织要领使每个单元测试都能造访被测试类中带有 package 或 protected 造访修饰符的措施和引用变量。

在单元测试中避免应用域工具。域工具是特定于某个利用法度榜样的工具。例如,一个电子表格利用法度榜样可能包孕一个注册工具;这个注册工具便是一个域工具。假如您有一个已知这些域工具的类,则在测试中完全可以应用这些工具。然则假如您有一个根本不应用这些域工具的类,在测试中就不要将这些工具联系到该类上。应该避免这种情形完全是由于代码重用。为某一项目创建的类常常要用于其他项目。重用这些类可能很简单。然则,假如对重用类的测试顶用到了另一个项目的域工具,则使测试能够正常运行这一事情就会相称耗时。平日环境下,这个测试将被删除或重写。

这些机制为您供给很好的赞助,然则假如您不运行这些测试,一套综合的单元测试就变得一文不值。尽早运行测试平日使您在任何时刻都对代码充溢信心。您将跟着项目进展赓续添加功能。运行这些测试将会看护您刚刚实现的新功能是否对系统造成了破坏。

在您掌握了编写单元测试的技术之后,我们再来看看现有代码。为现有代码编写测试可能是个寻衅。不要为测试而测试。当您发明有需要对一个未经很好测试(或者根本就没有测试)的类进行改动时,请“随时”编写测试。现在是添加测试的时刻了。像往常那样,该类的单元测试应该捕获其每个措施的功能。找出应该进行哪些测试的最轻易的措施之一是:查看现有代码中的注释。任何注释都应在单元测试内捕获。将位于措施开首、阐明该措施所起感化的注释块翻译为单元测试。

回页首

若何编写功能测试

只管功能测试很紧张,但它却没有受到足够的注重。多半项目都有零丁的一个组来做功能测试。平日有一大年夜群人赓续地与系统交互,以确定系统是否精确事情。这种不雅念和设置专门的功能测试小组的做法很不明智。

对功能测试的处置惩罚与对单元测试的处置惩罚不应该有太大年夜的差别。只要您编写的代码用来孕育发生要求用户与之交互的组件(如对话框),就要编写测试,但实际上编写测试要在编写代码之提高行。请与用户一路编写获取用户需求的功能测试。无论何时开始一项新义务,都要在功能测试框架中描述此义务。您的开拓事情将继承向前成长,当添加新代码时,请履行单元测试。当所有的单元测试都停止今后,运行最初的功能测试,看看它是否能够经由过程,或者是否必要改动。

从理论上讲,功能测试小组的观点该消掉了。开拓职员应与用户合营编写功能测试。在对系统所做的一系列功能测试停止之后,开拓组中认真功能测试的成员就应该用初始测试的各类变更形式来轰击系统。

回页首

单元测试与功能测试的边界

平日单元测试与功能测试之间并没有明确的边界。老实说,无意偶尔我也不清楚这个边界在什么位置。在编写单元测试时,我根据以下原则来确定当前编写的单元测试实际上是否是功能测试:

假如单元测试超过类界限,则它就可能是功能测试。 假如单元测试变得很繁杂,则它可能是功能测试。 假如单元测试很脆弱(也便是说,虽然它是一个有效测试,但它必须赓续改变以处置惩罚不合的用户组合),则它可能是功能测试。 假如编写单元测试比编写其所测试的代码更难,则它可能是功能测试。

请留意“它 可能是功能测试”这一语言。本文无法供给硬性而快速的规则。单元测试与功能测试中之间有一个边界,但边界的详细位置要由您来确定。您用单元测试用得越纯熟,某个特定测试是单元测试照样功能测试的边界就越显着。

回页首

小结

单元测试是从开拓职员的角度启程编写的,并且关注的是所测试的类的特定措施。当编写单元测试时,请应用以下这些原则:

首先编写单元测试,然后再编写要测试的类代码 在单元测试中捕获代码注释。 测试所有履行“令人感兴趣的”功能(即,不是 getter 和 setter,除非它们以某种独特的要领履行获取和设置操作)的公共措施。 将每个测试实例与它要测试的类放在同一个包内,以得到对包成员和保护成员的造访权。 避免在单元测试中应用特定于域的工具。

功能测试是从用户的角度启程编写的,并且关注用户感兴趣的系统行径。找一个优秀的功能测试框架,或者开拓一个测试框架,并应用这些功能测试识别用户的真实需求。这样,功能测试职员即可得到一种自动化对象以及应用这一对象的动手点。

使单元测试和功能测试成为您开拓历程中的中间环节。假如您这样做了,您将对系统的运行及扩展充溢信心。假如您没有这样做,您对系统就没有实足的把握。测试可能不那么有趣,然则在开拓历程中进行单元测试和功能测试使开拓变得相称有趣。

您可能还会对下面的文章感兴趣: