|
知识路径: > 测试技术的分类 > 面向对象的软件测试技术 > 面向对象软件的测试策略 >
|
相关知识点:16个
|
|
|
|
传统的单元测试是针对程序的函数、过程或完成某一特定功能的程序块,可沿用单元测试的概念,来实际测试类成员函数。一些传统的测试方法在面向对象的单元测试中都可以使用。如等价类划分法、因果图法、边值分析法、逻辑覆盖法、路径分析法、程序插装法等。单元测试一般建议由程序员完成。
|
|
|
用于单元级测试的测试分析(提出相应的测试要求)和测试用例(选择适当的输入,达到测试要求),规模和难度等均远小于后面将介绍的对整个系统的测试分析和测试用例,而且强调对语句应该有100%的执行代码覆盖率。在设计测试用例选择输入数据时,可以基于以下两个假设(假设使用C++编程语言):
|
|
|
. 如果函数(程序)对某一类输入中的一个数据正确执行,对同类中的其他输入也能正确执行。
|
|
|
. 如果函数(程序)对某一复杂度的输入正确执行,对更高复杂度的输入也能正确执行。例如,需要选择字符串作为输入时,基于本假设,就无须计较字符串的长度。除非字符串的长度是要求固定的,如IP地址字符串。
|
|
|
在面向对象程序中,类成员函数通常都很小,功能单一,函数之间调用频繁,容易出现一些不宜发现的错误。例如:
|
|
|
|
该语句没有全面检查write()的返回值,无意中只断然假设了数据被完全写入和没有写入两种情况。当测试也忽略了数据部分的写入情况时,就给程序遗留了隐患,建议加入else语句。
|
|
|
. 按程序的设计,使用函数strrchr()查找最后的匹配字符,但错误程序中写成了函数strchr(),使程序功能实现时查找的是第一个匹配字符。
|
|
|
. 程序中将if(strncmp(str1,str2,strlen(str1)))误写成了if(strncmp(str1,str2,strlen (str2)))。如果测试用例中使用的数据str1和str2长度一样,就无法检测出来。
|
|
|
因此,在做测试分析和设计测试用例时,应该注意面向对象程序的这个特点,仔细地进行测试分析和设计测试用例,尤其是针对以函数返回值作为条件判断选择,字符串操作等情况。
|
|
|
面向对象编程的特性使得对成员函数的测试,不完全等同于传统的函数或过程测试。尤其是继承特性和多态特性,使子类继承或过载的父类成员函数出现了传统测试中未遇见的问题。Brian Marick给出了两方面的考虑如下:
|
|
|
|
对父类中已经测试过的成员函数,有两种情况需要在子类中重新测试:
|
|
|
①继承的成员函数在子类中做了改动;②成员函数调用了改动过的成员函数的部分。例如:假设父类Bass有两个成员函数:Inherited()和Redefined(),子类Derived只对Redefined()做了改动。Derived::Redefined()显然需要重新测试。对于Derived::Inherited(),如果它有调用Redefined()的语句(如:x=x/Redefined()),就需要重新测试,反之,无此必要。
|
|
|
|
延用上面的假设,Base::Redefined()和Derived::Redefined()已经是不同的成员函数,它们有不同的服务说明和执行。对此,照理应该对Derived::Redefined()重新进行测试分析,设计测试用例。但由于面向对象的继承使得两个函数有相似之处,故只需在Base::Redefined()的测试要求和测试用例上添加对Derived::Redfined()的新的测试要求和增补相应的测试用例。例如:Base::Redefined()函数中含有如下语句
|
|
|
|
在原有的测试上,对Derived::Redfined()的测试只需做如下改动:将value==0的测试结果期望改动;增加value==99的测试。
|
|
|
多态有几种不同的形式,如参数多态、包含多态、过载多态。包含多态和过载多态在面向对象语言中通常体现在子类与父类的继承关系上,对这两种多态的测试参见上述对父类成员函数继承和过载的论述。包含多态虽然使成员函数的参数可有多种类型,但通常只是增加了测试的复杂度。对具有包含多态的成员函数进行测试时,只需要在原有的测试分析和基础上增加对测试用例中输入数据的类型的考虑。
|
|
|