单元测试思想之单元测试的实施

上一篇 / 下一篇  2006-12-14 11:42:21

  单元测试由谁来做?单元测试由测试部门来做还是由开发部门来做,是一个引起广泛争论的话题。我们的观点是:由测试部门和开发部门共同来做:测试部门负责制定规范、培训,并检查测试效果;由开发部门负责具体的实施,最好是边开发边测试。
  测试部门可能不具备实施单元测试的足够人手,即使测试部门有足够的人手,即使项目时间允许,完全由测试部门实施单元测试也会造成资源的较大浪费,因为测试人员要花很多时间来重新理解代码,同时,充分的单元测试通常会发现很多细小的错误,程序员修改代码时,又要再一次理解代码;另一方面,如果等编码基本完成再由测试部门进行单元测试,也就不能发挥单元测试对代码整体结构的约束效果,测试部门拿到代码时,往往会发现难于测试。当然,已经完成编码的项目也不是不能进行单元测试,只不过可能要花费一定的时间成本对代码进行整理重构,后文会有进一步的论述。
  由开发人员实施单元测试,当然也有问题,主要有:一是程序员可能不喜欢做单元测试;二是开发部门可能担心影响开发进度;三是由于思维定势的原因,不容易保证测试的完整性。我们在设计VU的过程中,充分考虑了这三个问题,提供了切实可行的解决方法和工具。
  很多开发人员不喜欢做单元测试,甚至抵制单元测试,对于这种现象,常见的说法是程序员太自信,觉得自己的代码不会有错,所以不愿意进行单元测试。这种说法就好象在说程序员“自以为是,不负责任”,所以不愿意做单元测试。事实是这样的吗?作为程序员,我们自己并无这种心理,也调查过一些程序员,没有谁真的有这种心理,实际上,哪个程序员没有翻江倒海地排查一个小小错误的经历?谁写的代码也不能保证毫无错误,人不是机器,即使编程时思维缜密到没有任何疏漏,也还可能有“笔误”呢。那么,程序员为什么不喜欢做单元测试呢?我们认为,主要还是程序员的工作特点造成的。编程是创造性的工作,编程的最大乐趣就在于看到了自己的劳动成果出现在眼前,这就使程序员常有一种“立即实现”的冲动;另一方面,程序员的思维往往是跳跃向前的,当程序员开始了编程思路之后,一般就不愿意中断思路,花较多时间去编写测试代码了;再一方面,跟测试工具也有一定关系,一般的单元测试工具只显示“通过”,“失败”两种状态,相对而言,在产品工程中直接观看代码的运行结果更有吸引力,更容易产生成就感。
  VU在设计上,力求让程序员自然地喜欢单元测试。一方面,VU自动生成测试代码,不需花费时间、中断思路去编写测试代码;另一方面,VU全方位地示出代码的行为:显示各种数据的输入输出值,显示不同输入时程序所执行的代码;画出逻辑结构图及不同输入时程序的执行路径,程序员可以随时“欣赏”自己的劳动成果;再一方面,VU还帮助程序员快速地排除错误和高效地调试,尽可能减少程序员查找某种错误的时间,使程序员的思维始终集中在程序逻辑上。VU的这些功能,使测试工作费时极少,同时又提高了编程的效率,总体来说,边编码边用VU进行测试,在达到完整测试的同时,还能大幅度减少开发时间。
  VU具有强有力的保证测试完整性的功能:轻松完成100%语句、条件、分支、路径覆盖,提供详尽的测试报告和待测试文件列表,随时可以检验测试效果、找出遗漏代码或未完成覆盖的代码,保证测试的完整性。
  在具体的实施过程中,可以根据实际情况调整测试部门和开发部门的分工,例如,如果测试部门人手充裕,也可以由开发部门边开发边完成功能方面的测试,由测试部门完成白盒覆盖和执行边界测试。

  单元测试的“单元”一般是指函数或类。以类为测试单元,如果类比较复杂,测试会变得很复杂,即使是三五个成员变量,十个八个成员函数这样一个很普通的类,要考虑清楚类的功能,以类为考核对象进行完整的测试,也是很不容易的。我们认为,以函数为测试单元,更符合简单实用的原则。面向对象的测试与面向结构的测试的主要区别在于,对象是有状态的,面向对象的测试要考虑对象的状态。对象的状态是什么?简单点说就是成员变量的值,执行了某个操作后,对象的状态有了变化,也就是对象的成员变量的值有了变化,我们可以把对象的状态作为函数的输入输出的一部分:执行操作前对象的状态也是一种输入,执行操作后对象的状态也是一种输出。如果对象的每一个操作,其输出都是正确的,那么,可以肯定这个对象在任何时候,其状态都是正确的。

  总的来说,单元测试越早越好。早到什么程度?XP开发理论主张测试驱动开发,先编写测试代码,再进行开发,这样的话,单元测试就不仅仅是测试,还是一种设计了。事物总有两面性,这种方式不便于使用测试工具自动生成测试代码,因为测试工具要先了解被测试对象的基本信息才能生成测试代码。我们主张,先编写类的声明,然后生成该类的测试类,先编写函数的声明,然后生成对应的测试函数,编写产品函数的代码时,每写一个功能点都运行测试,随时补充测试用例,这样可以最高效。

  单元测试一般测试底层的业务类,中层的控制类,一般不测试边界类(界面类),所以不要把业务代码直接写在边界类里。

  除了很简单的函数,例如GetMember()/SetMember(),其他函数都应该测试,而不要以是否公有来决定是否测试,因为私有函数也可能很复杂,同样可能隐藏着错误。VU使用一种简单的机制来区隔需测试的函数:在源文件中编写实现代码的函数视为需测试的函数,在头文件中编写实现的函数(一般是简单的内联函数)视为不需要测试的函数。

TAG:

dumb_dora的个人空间 引用 删除 dumb_dora   /   2010-04-07 15:52:05
VU是什么?现在有这样的工具了吗?在哪里可以找到
 

评分:0

我来说两句

Open Toolbar