单元测试的基本测试方法
作者:网络转载 发布时间:[ 2010/11/12 14:39:27 ] 推荐标签:
用打桩来解决可测性问题也是一种思路。打桩是单元测试的常用技术,可用以将影响测试的外部系统隔离:一是将不可控的、费时的实际系统隔离,例如访问网络、数据库、硬件等,二是将复杂的底层系统隔离,采用相对简单的模拟系统来代替,但用打桩尤其是工具自动打桩来解决不当耦合造成的可测性问题,则不见得实用,举个例子来说明:
void Sort(int[10] data)
{
…
Swap(int[a], int[b]);
…
}
Sort是排序函数,调用了Swap实现两个数的交换,假如用一个自动生成的桩来代替Swap,那么这个桩通常是什么也没做,只是能通过编译而已,这样,两个数的交换过程根本没有完成,整个Sort函数的功能完全不同了,这样的测试,除了看一下程序是否会崩溃之外,还有什么意义呢?要做到打桩后不改变代码的功能,并非易事,并且打桩并未改良产品代码的结构,还是重构更有价值,下面是几种典型的不当耦合及重构方法:
把代码写在界面类中
问题:如果把业务代码写在界面类中,测试时把界面类加入测试工程,会产生编译错误。
解决:把业务代码独立出来,写到相应的实体类中,对这些实体类进行测试。界面类只负责数据的显示和接受用户的输入,具体的计算由实体类负责。
说明:把业务代码写在界面类中,这些代码将很难管理和维护,复用更谈不上了,这是一定要避免的。
实体类混合了边界代码
问题:例如,一个表示用户的类CUser,它的对象的数据保存在数据库中,如果在CUser类中直接读写数据库,是实体类混合了边界代码,这也是一种不当耦合,测试CUser类时要察看数据库,或者要打桩,甚至会产生编译错误。
解决:把执行数据库操作的代码写到CDatabase类中,CUser类和CDatabase类没有任何关联,由界面类或用于协调各对象工作的控制类来操作这两个类的对象进行数据读写,现在对CUser类的测试完全和数据库无关了。
说明:经过重构后,代码的可扩展性、可复用性都有了很大提高,也便于进行单元测试和将来的维护。
无意中形成了高耦合
问题:例如,CMyClass类中一个函数中有这样的语句:
CDemoApp* pApp = (CDemoApp*)AfxGetApp();
UNIT var = pApp->GetXXX()->Getxxxx();
由于CDemoApp是工程的高层类,可能跟工程中的所有类关联,这两行代码造成被测试对象跟工程中的所有类耦合。耦合具有扩散性,纵向来说,CMyClass类的所有子类也可能跟工程中的所有类关联,横向来说,所有使用了CMyClass类的类,也可能跟工程中的所有类关联,从而形成了盘根错节的关系。这种问题往往很难发现,但把代码加入测试工程后,一般来说是通不过编译的,从而使问题暴露。
解决:修改被测试代码,去除耦合。把需要从pApp指针中取得的数据改为由参数传进来,这两行代码移到客户程序(即调用被测试函数的代码)中,如果客户程序也是实体类,则继续往上移,直到界面类。
说明:这类无意中形成的耦合非常常见,一般的代码审查、静态扫描都很难发现这类问题,但把代码加入测试工程后,编译器却能轻松发现。这类问题只要及时发现了,消除并不难,经过简单的代码重构,可以有效地提高代码质量,特别是提高代码的可复用性,也使单元测试可以顺利进行。
开发工具生成的代码形成了不当耦合
有时候,开发工具生成的代码也形成了不当耦合,例如,VC6.0生成的类代码中,源文件会添加下面的代码:
#include "ProjectName.h" //ProjectName是工程名
如果在另一个不同名的工程中复用代码,这一行会产生编译错误。进行单元测试时,这一行形成的不当耦合也可能会导致编译错误,因此应删除它。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11