27 | 深入浅出之动态测试方法

人工动态方法

单元测试中三个最主要的难点:
  •         单元测试用例“输入参数”的复杂性;
  •         单元测试用例“预期输出”的复杂性;
  •         关联依赖的代码不可用。
单元测试用例“输入参数”的复杂性
  1. 被测试函数的输入参数
  2. 被测试函数内部需要读取的全局静态变量
  3. 被测试函数内部需要读取的类成员变量
  4. 函数内部调用子函数获得的数据
  5. 函数内部调用子函数改写的数据
  6. 嵌入式系统中,在中断调用中改写的数据
单元测试用例“预期输出”的复杂性
  1. 被测函数的返回值
  2. 被测函数的输出参数
  3. 被测函数所改写的成员变量和全局变量
  4. 被测函数中进行的文件更新、数据库更新、消息队列更新等(在实际的单元测试实践中,因为测试解耦的需要,所以一般不会真正去做这些操作,而是借助对 Mock 对象的断言来验证是否发起了相关的操作)
关联依赖的代码不可用

        假设被测函数中调用了其他的函数,那么这些被调用的其他函数就是被测函数的关联依赖代码。

        假定函数 A 调用了函数 B,而函数 B 由其他开发团队编写,且未实现,那么我们就可以用桩函数来代替函数 B,使函数 A 能够编译链接,并运行测试。

        桩函数要具有与原函数完全相同的原形,仅仅是内部实现不同,这样测试代码才能正确链接到桩函数。一般来讲桩函数主要有两个作用,一个是隔离和补齐,另一个是实现被测函数的逻辑控制。

自动动态方法

        自动动态方法的重点是:如何实现边界测试用例的自动生成。

        解决这个问题最简单直接的方法是,根据被测函数的输入参数生成可能的边界值。

        具体来讲,任何数据类型都有自己的典型值和边界值,我们可以预先为它们设定好典型值和边界值,然后组合就可以生成了。

        比如,函数 int func(int a, char *s),就可以按下面的三步来生成测试用例集。

        第一步、定义各种数据类型的典型值和边界值。 比如,int 类型可以定义一些值,如 int 的最小值、int 的最大值、0、1、-1 等;char* 类型也可以定义一些值,比如“”、“abcde”、“非英文字符串”等。

        第二步、根据被测函数的原形,生成测试用例代码模板,比如下面这段伪代码:

try{
  int a= @a@;
  char *s = @s@;
  int ret = func(a, s);
}
catch{
  throw exception();
}

        第三步、将参数 @a@和 @s@的各种取值循环组合,分别替换模板中的相应内容,即可生成用例集。

        由于该方法不可能自动了解代码所要实现的功能逻辑,所以不会验证“预期输出”,而是通过 try…catch 来观察是否会引发代码的异常、崩溃和超时等具有边界特征的错误。

你可能感兴趣的:(测试,接口测试,自动化测试,单元测试,软件测试,自动化测试,软件测试52讲,单元测试难点)