类所实现的功能,都是通过类的成员函数执行。在测试类的功能实现时,应该首先保证类成员函数的正确性。单独的看待类的成员函数,与面向过程程序中的函数或过程没有本质的区别,几乎所有传统的单元测试中所使用的方法,都可在面向对象的单元测试中使用。具体的测试方法在面向对象的单元测试中介绍。类函数成员的正确行为只是类能够实现要求的功能的基础,类成员函数间的作用和类之间的服务调用是单元测试无法确定的。因此,需要进行面向对象的集成测试。具体的测试方法在面向对象的集成测试中介绍。需要着重声明,测试类的功能,不能仅满足于代码能无错运行或被测试类能提供的功能无错,应该以所做的OOD结果为依据,检测类提供的功能是否满足设计的要求,是否有缺陷。必要时(如通过OOD结仍不清楚明确的地方)还应该参照OOA的结果,以之为最终标准。
六 面向对象的单元测试(OO Unit Test)
传统的单元测试是针对程序的函数、过程或完成某一定功能的程序块。沿用单元测试的概念,实际测试类成员函数。一些传统的测试方法在面向对象的单元测试中都可以使用。如等价类划分法,因果图法,边值分析法,逻辑覆盖法,路径分析法,程序插装法等等,方法的具体实现参见[6]。单元测试一般建议由程序员完成。
用于单元级测试进行的测试分析(提出相应的测试要求)和测试用例(选择适当的输入,达到测试要求),规模和难度等均远小于后面将介绍的对整个系统的测试分析和测试用例,而且强调对语句应该有100%的执行代码覆盖率。在设计测试用例选择输入数据时,可以基于以下两个假设:
1. 如果函数(程序)对某一类输入中的一个数据正确执行,对同类中的其他输入也能正确执行。
2. 如果函数(程序)对某一复杂度的输入正确执行,对更高复杂度的输入也能正确执行。例如需要选择字符串作为输入时,基于本假设,就无须计较于字符串的长度。除非字符串的长度是要求固定的,如IP地址字符串。在面向对象程序中,类成员函数通常都很小,功能单一,函数的间调用频繁,容易出现一些不宜发现的错误。例如: · if (-1==write (fid, buffer, amount)) error_out();
该语句没有全面检查write()的返回值,无意中断然假设了只有数据被完全写入和没有写入两种情况。当测试也忽略了数据部分写入的情况,就给程序遗留了隐患。
· 按程序的设计,使用函数strrchr()查找最后的匹配字符,但误程序中写成了函数strchr(),使程序功能实现时查找的是第一个匹配字符。
· 程序中将if (strncmp(str1,str2,strlen(str1)))误写成了if (strncmp(str1,str2,strlen(str2)))。如果测试用例中使用的数据str1和str2长度一样,就无法检测出。 因此,在做测试分析和设计测试用例时,应该注意面向对象程序的这个特点,仔细的进行测试分析和设计测试用例,尤其是针对以函数返回值作为条件判断选择,字符串操作等情况。
面向对象编程的特性使得对成员函数的测试,又不完全等同于传统的函数或过程测试。尤其是继承特性和多态特性,使子类继承或过载的父类成员函数出现了传统测试中未遇见的问题。在[7]中,Brian Marick 给出了二方面的考虑:
1. 继承的成员函数是否都不需要测试?
根据[7]中的论述,对父类中已经测试过的成员函数,两种情况需要在子类中重新测试:a)继承的成员函数在子类中做了改动;b)成员函数调用了改动过的成员函数的部分。例如:
假设父类Bass有两个成员函数:Inherited()和Redefined(),子类Derived只对Redefined()做了改动。 Derived::Redefined()显然需要重新测试。对于Derived::Inherited(),如果它有调用Redefined()的语句(如:x=x/Redefined()),就需要重新测试,反之,无此必要。
文章来源于领测软件测试网 https://www.ltesting.net/