Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何为细微错误设计软件测试_C_Testing - Fatal编程技术网

C 如何为细微错误设计软件测试

C 如何为细微错误设计软件测试,c,testing,C,Testing,这是一个超级简单的例子,在这里用C来说明一个微妙的错误,我不知道如何通过测试将其暴露为bug 考虑: #include <stdio.h> int main() { int a; int b; int input; printf("Enter 1 or 2: "); scanf("%d", &input); switch(input) { case 1: a = 10; /* ERROR HERE, I FORGOT A B

这是一个超级简单的例子,在这里用C来说明一个微妙的错误,我不知道如何通过测试将其暴露为bug

考虑:

#include <stdio.h>

int main() 
{
  int a;
  int b;
  int input;

  printf("Enter 1 or 2: ");
  scanf("%d", &input);

  switch(input) {
  case 1:
    a = 10;
    /* ERROR HERE, I FORGOT A BREAK! */
  case 2:
    b = 20;
    break;
  default:
    printf("You didn't listen!\n");
    return 1;
    break;
  }

  if(input == 1) {
    b = 30;
    printf("%d, %d\n", a, b);
  } else {
    printf("%d\n",b);
  }

  return 0;
}
#包括
int main()
{
INTA;
int b;
int输入;
printf(“输入1或2:”);
scanf(“%d”,输入(&I));
开关(输入){
案例1:
a=10;
/*这里出错了,我忘记休息了*/
案例2:
b=20;
打破
违约:
printf(“您没有听!\n”);
返回1;
打破
}
如果(输入=1){
b=30;
printf(“%d,%d\n”,a,b);
}否则{
printf(“%d\n”,b);
}
返回0;
}
如代码中所述,缺少一个
中断
,因此当输入1时,将进入案例2。但是1的输出没有反映这一点,因为它稍后会覆盖
b
。因此,我们可以设计的所有测试,比如从集合
{1,2,10}
中输入一个数字,都会得到正确的输出

实际上,
开关
内的分配可能非常昂贵,因此此错误可能非常昂贵。但是,假设它是从第一天开始这样写的,没有基准可以看出成本高于预期

那么,我们可以做些什么来消除这些错误呢?有没有办法设计测试用例以在生产软件中公开它

编辑 所以我想我并不完全清楚——我用C写它是为了说明遇到的问题类型,但实际上它并不特定于C。我想指出的是,代码进入了我们从未打算进入的部分(在这种情况下,是因为一个被遗忘的
中断
,来说明这一点)。我的实际案例是一个有700000行的Fortran代码,它正在进入我们从未打算进入的分支,因为糟糕的if/开关设计从语言角度来看是合法的,但可能非常昂贵


是否有可能设计一个测试或查看来自某个工具的一些数据,这些数据会告诉我们它将进入不应该进入的分支?我在所有案例中打印“我不应该在这里!”时发现了一个错误,并看到它被打印出来,一定有比随机查看和打印语句更好的方法。

您可以为switch语句定义编码约定,这样每个分支都会施加一种特殊状态。就像一个变量被赋值一样。例如:

switch (v) {
case 1: 
    vcheck = 1;
    ...
    break;
case 2:
    vcheck = 2;
    ...
    break;
}
并在测试用例中测试
vcheck

除此之外,您还可以使用对验证执行静态代码分析的工具,并将它们应用到构建过程中。他们会引起一些想法…:-)


最后,(我最喜欢的)您可以编写一个脚本,用于检查此类情况并再次发出警告。

您可以为switch语句定义编码约定,以便每个分支都会施加特殊状态。就像一个变量被赋值一样。例如:

switch (v) {
case 1: 
    vcheck = 1;
    ...
    break;
case 2:
    vcheck = 2;
    ...
    break;
}
并在测试用例中测试
vcheck

除此之外,您还可以使用对验证执行静态代码分析的工具,并将它们应用到构建过程中。他们会引起一些想法…:-)


最后,(我最喜欢的)您可以编写一个脚本来检查此类情况并再次发出警告。

情况1的正确状态是不会设置b

检查是否设置了b

如果以后要设置b,可能需要将代码分解成更小的段来测试这一点,但这就是良好的模块化

您似乎在问“如何测试不稳定的代码?”。答案是,编写可测试代码需要技巧和计划,不能只是事后的想法

web上有很多东西可以帮助您编写可测试代码:


情况1的正确状态是不会设置b

检查是否设置了b

如果以后要设置b,可能需要将代码分解成更小的段来测试这一点,但这就是良好的模块化

您似乎在问“如何测试不稳定的代码?”。答案是,编写可测试代码需要技巧和计划,不能只是事后的想法

web上有很多东西可以帮助您编写可测试代码:


如果
输入==1
并且您在输出上看到
b=30
,您就知道出了问题。另外,请记住在else子句中,在阅读b之前,您应该先给b写一些东西。在
default:
(例如,
input==100
)的情况下,您可能会在没有正确设置的情况下从某个位置读取


此外,如果你负担得起的话,代码审查应该会对找到类似的东西有很大帮助。

如果
input==1
并且你在输出上看到
b=30
,你就知道出了问题。另外,请记住在else子句中,在阅读b之前,您应该先给b写一些东西。在
default:
(例如,
input==100
)的情况下,您可能会在没有正确设置的情况下从某个位置读取


此外,如果你能负担得起的话,代码审查应该对找到类似的东西有很大帮助。

对于你的具体例子,从定义上讲,这绝不是一个错误/bug。在语言中,需要的是突破的可能性。如果你想禁止某些危险的语言特性,那么这是一条路要走


为了避免完全不可预见的错误,有一条规则:总是防御性地编写代码,并使用
assert
s(您可以将它们放在任何地方)。

对于您的特定示例,从定义上讲,这决不是错误/bug。在语言中,需要的是突破的可能性。如果你想禁止某些危险的语言特性,那么这是一条路要走


为了避免完全不可预见的错误,有一条规则:总是防御性地编写代码,并使用
assert
s来放置它们。

为什么我会问这个错误?使用任何类型的黑盒测试代码都有效。因此,如果唯一的需求