单元测试之关键问题解答

前端之家收集整理的这篇文章主要介绍了单元测试之关键问题解答前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
当你打开CSDN首页上的一位专家的最新博文,你以为你能学到什么东西,结果看完以后你觉得什么都没有学到,这种感觉是不是非常不爽?

这篇博文的重点:
  1. 单元测试的目的是什么;
  2. 单元测试测试什么;
  3. 在敏捷开发中,如何进行单元测试;
  4. 测试的分配与配合;
  5. 如何设计好的单元测试案例;
因为我的打字不快,外加国内对知识产权的轻视,我不准备花大篇幅写详细文章内容只是点到为止。你想学到更高深的知识,请在参加我开设的培训(我没有组织任何培训,也没有自己的培训机构,所以上一句话是说了白说)。

有人认为大多数程序员知道单元测试的重要性。事实上只有少数人知道单元测试的重要性,大多数程序员都懒得写单元测试,大多数公司都在使用流水性工程管理。XP,敏捷开发,或是精简敏捷开发都没有想像的那样广泛应用,甚至在很多地方XP,敏捷开发的应用都不正确。甚至在我现在的公司里,很多人都不知道如何运用JUnit/NUnit来进行单元测试。他们对JUnit/NUnit会有各种错误假设,然后设计出来的单元测试根本解决不了实际问题。更多的公司根本不懂自动化测试或单元测试,所以他们所有的测试多半是半自动半人为的测试。有一部分可能还只是人为测试,效率低下。

单元测试的目的
我也不重复很多地方已经重复过的什么是单元测试,单元测试的目的,我只想说说我的看法。单元测试的目的就是在最早的开发阶段进行测试。这么做的好处,最大的好处是,每次开发对一个个单元(也就是类)进行更改,再运行一下单元测试就知道自己有没有破坏单元希望达到的功能。TDD的目的是用测试来推动开发的进行。在单元没有成形之前,单元测试案例被设计出来模拟假想中的单元是如何被利用的,这时单元测试案例的运行肯定是不及格的,然后开发就开始设计单元来让单元测试案例的运行达到及格。以后的修改中,所有的单元测试要运行来保证单元的修改没有造成运行的错误

当然,并不是所有的开发团队都进行TDD,单元测试还是可以帮助这些小组,单元测试可以间接地测量一个单元的可测试性,要是一个单元要依靠很多其他单元才能完成一个操作,那么这个单元对其他部件的依赖性过大,那么可测性就很低。单元与单元的依赖可以依靠Mock对象来测试,但是过于复杂的依赖特别是实类和实类的依赖,在单元测试中可以马上检测出程序的可测性。

单元测试的目的,好处,并不是显而易见的。了解这些细节只能从详细阅读理解书籍和网上的资料,或者从我这样的人交流获得。现在很少人能够一字一句地将书或文章读透。所以最好的学习方法还是通过面对面的交流。

单元测试测试什么
单元测试的是一个源码中最小单元的代码是否正确处理它该处理的任务。源码中最小单元的代码可以是一个类中的类函数。也可以是类的本身(几个类函数一起合作处理类所应该进行的操作)。这里为什么有两种不同,因为单元测试设计者的风格不同,导致设计的不同,但是任何测试结合几个已开发的实单元,就不算单元测试。使用Mock单元来协助现有单元的测试是单元测试,因为Mock单元不是已开发的实单元,它是一个假的,辅助性的单元。所以使用Mock单元最终测试的也只是现有开发的单元。

任何测试,如业务功能,或是接口型测试都不算是单元测试。严格地说单元测试在面向对象程序设计里,就是对类为单元的测试。业务功能,接口测试已经是QA测试负责的业务。在XP,敏捷,精简敏捷开发里,业务功能,接口测试是接受性测试中的部分。QA在开发者开发的同时,必须对业务功能定义并设计接受性测试。只有通过了接受性测试,代码的初级接受性才能认可。单元测试是开发者自己的接受性测试,目的是保证自己开发的单元合乎自己的期望。QA的接受性测试往往是以业务功能定义和接口为目标的局部结合性测试,甚至有时是复杂的头到尾测试。单元测试和QA接受性测试都不能忘记边界情况,边界数据的处理等等案例。

单元测试的目标是,在最快的速度内让任何人能够设计一个测试案例,然后能够马上执行,案例与案例间不能有任何序列的依赖,每个单元测试都有自己的测试前设置,和测试後清除步骤(所以两个测试案例不用相互依赖)。

在敏捷开发中,如何进行单元测试
在敏捷开发中,自动化,经常性的单元测试是一个项目成功的关键。所有的自动化测试在每一次的构建後都要运行,任何错误都会造成构建失败,这样才能督促开发者或测试修改出错的地方。构建可以是每日构建(Daily Build),甚至是随时只要有变化就进行构建(Constant Continuous Build)。

敏捷开发的目标是,在开发中出现任何变化,整个团队都能敏捷地转换自己的开发方向来顺应变化的要求。TDD所要达到的目的是用需求来引导单元的业务功能,用测试先模拟业务功能的实现,在引导开发者实现单元的的业务功能。开发者必须对单元进行分割和重组,利用OO最佳设计结构和设计模式(Design Pattern)来实现OCP(Open for extension,Close for modification Principle)。利用OCP达到的目的是让整个系统变得更易延伸,更易维护。TDD也会驱使开发者对程序系统的构架进行层次分化,将系统分割成用户界面,商业逻辑,和后台存储的三层结构。三层结构是具有测试性的, 用户界面是用手动测试,和专业自动化测试工具进行的。商业逻辑和后台存储这两层都能用单元测试来实施自动话和单元化测试。 具体如何做到这些,必须通过实际案例的剖析来理解。

敏捷开发另一目标是,快速为客户提供期望的价值,所以,在最短时间内,一个完整的简单的软件系统必须形成,然后不同的部件在独立开发测试后,马上能够和现有的产品(也就是一个完整的简单的软件系统)集成。这就需要开发者,QA合作进行测试。开发者至少要做到用单元测试来保证部件质量。QA必须在集成的基础上开发结合性测试,头到尾测试,以整个系统为整体的方式进行测试。
具体的测试方法应该有实际情况出发,就像独孤九剑那样,随机应变。任何流程只要适应团队的发展,就是好的流程。

测试的分配与配合
理想情况下,单元测试是由开发者自己进行,或是在QA的指导下设计。现实中,开发者的测试能力有限,有时因为懒或不得不进行的赶工,他们不写或进行很少的单元测试,所以,测试帮助开发者进行单元测试,是一种必要。开发者和测试的合作可以是一起设计或是分工。仅仅让开发者搞单元测试,或把所有的单元测试扔给测试做都是比较极端的做法。我认为平衡点是,测试从黑箱的角度进行单元测试,程序从最基本的行为正确的目的用白箱的角度进行单元测试。两者的努力可以重叠。

在这个话题上,各个公司的运作都是不一样的,有些公司所有的测试都是设计完成后的测试(结果就是整个系统根本没有测试性,所有的东西都结在一起了),有些从最早就开始搞单元测试,有些把单元测试全部推给QA。也有很多是开发者和QA重复了许多同样的工作,等于是过多地重复地进行了许多同样的单元测试。

如何平衡开法者和QA的单元测试,这里没有一个简单的回答。这是开发团队和QA团队必须相互磨合最后达到的一种高效率的平衡。软件开发本身就是人与人的互动。所以没有相互交流相互沟通的开发肯定会把产品推向错误的发展方向。
如何设计好的单元测试案例
这是一个测试战术的问题,各个公司的在战术运用上都是不一样的。可能大的框架是一样的,但是在执行的过程中,具体细节都是不同的。不管变化是什么,只要坚持了正确的原则,测试的结果一定会很好,首先,了解整个团队期望的目标,然后熟悉使用的工具,最后是遵循业界公认的正确准则。我所知道的 工具是NUnit和JUnit,CxxTest,和几种不同的构建系统(微软的构建系统,Maven 1/2,FireFox的构建系统我只知道一点点,还有一些杂毛系统)。NUnit/JUnit的特性是任何单元测试都能在任何顺序下运行,单元测试本身就是一个独立的程序,它不需要依赖其他单元测试。它有自己的设置函数和任何情况下都能执行的清除 函数。知道这些我就知道如何设计一个独立的,不依赖其他单元测试的测试案例。CxxTest是有一定的不同,但是也是多少差不多。单元测试的目的是测试一个最基本的单元代码,当然对于QA,NUnit/JUnit都可以用于更复杂的测试案例的设计和执行。对于开法者来说,最简单最直接的就是测试一个最小单元的代码。更复杂的测试案例就超出了单元测试的范围。

所有的测试都应该在构建后运行,构建应该越频繁越好。现实中,所有的测试都运行可能会造成构建速度太慢。所以平衡测试数量和分割测试案例运行都要团队根据实际情况解决。而且,不被经常运行的测试案例如何在其他形式中运行,也要根据 团队根据实际情况来决定。测试案例太多而导致无法经常运行是一个很大的问题。找到平衡甚至能够超越平衡而达到频繁运行所有测试案例,是衡量测试团队敏捷处事的指标之一。能够频繁地运行大量耗时的测试案例,是一个团队所能达到的一个了不起的成就。

结束语
这又是一篇废话连篇的总结性博文,我实在也写不出什么,很多东西必须用案例的运用来说明。很多情况下开发者的单元测试和QA的测试没有明显的界限,两者交际的区域是一种灰色地带,有时QA水平很低下,开发者就必须进行很多QA形式的测试,有时两者的程序设计能力都很强,但是交流不够,两者会设计很多相同重复的测试案例。有时开发者根本不进行单元测试或是简单至极的单元测试,很多没有涉及的方面都由QA进行覆盖。如何确立QA开发者的测试方向,如何建立有效的测试机制,每个公司的测试战略,测试流程的规划。具体事宜,还是需要实际情况和长期的协调来决定的。
我个人想要做到的是,公司个人可以向我咨询具体解决方法,我以自己经验对这些具体情况提供一些指导。请留言处留言。

猜你在找的设计模式相关文章