2

QA 测试员正在阅读 HTML/JS 代码以编写 Web 表单的功能测试,并看到:

if (form_field == empty)
{
...do stuff for empty field
}
else if (form_field != empty)
{
...do stuff for non-empty field
}
else
{
...do stuff that will never be done
}

经过几次尴尬的尝试后,测试人员意识到他们无法触发隐藏在第三个区块中的警报字符串。

我想知道这个问题是否或多或少是特定于语言的(非 JS 人可以在这里学习课程吗?)并且代码以这种方式结束是否有正当的理由?

我怎样才能找到/解决问题?

4

13 回答 13

8

尽管第三个块不能在 Javascript 中触发,但并非所有语言都如此。在 T-SQL 中:

declare @test as int

set @test = null

if @test = 1 
  print 1
else if not @test = 1
  print 2
else 
  print 3

这将打印 3,因为 NULL 既不等于也不等于任何其他值。

于 2008-10-22T17:13:30.233 回答
4

如果您使用设计不佳的布尔值(在没有真正布尔类型的早期 C 中很常见),就会发生这种情况。你仍然可以在 Windows 中找到这些东西。

BOOL result = SomeWindowsAPI();
if (result == TRUE)
{
    // success
}
else if (result == FALSE)
{
    // failure
}
else
{
    // wtf?
}

这里的关键是对“TRUE”的显式测试,它假设布尔值只有一种方式可以具有真值。当使用整数作为布尔值时,这是不正确的。

在某些计算机上的某些语言(VMS 上的 Fortran)中,可能有许多不同的整数值解析为 true,许多不同的值解析为 false。在 Windows 上,HRESULT 被解释为 SUCCESS 或 FAILURE 时的方式相同。

于 2008-10-22T17:27:13.683 回答
3

我见过 else if 曾经在那里有其他东西(AND/OR)的情况,而修复它的人只是“修复它”并且没有深入探讨。

于 2008-10-22T17:10:27.117 回答
2

静态分析会告诉你第三种情况是“死代码”

像这样的代码来自对布尔逻辑的误解,或者不同人随着时间的推移多次编辑 - 或两者兼而有之;-)

这不是 Javascript 特有的,这种错误可以在任何具有 if-else 结构(或其合理的复制品)的语言中发生

于 2008-10-22T17:11:49.690 回答
2

这个问题或多或少是特定于语言的(非 JS 的人可以在这里学习吗?)

这是一个与语言无关的问题。用 Java 编写以下代码非常容易,例如:

if(x)
{
  //do something
}
else if(!x)
{
  //do something else
}
else
{
  //never, ever, do anything
}

要记住的关键是“if(!x)”不是必需的。把它变成一个简单的“else”会创建更简单的代码。

Are there legitimate reasons code ended up this way?

有点。当需要失败时,总是存在 else 条件是标准做法。问题是程序员并没有很清楚地认为他的“(form_field!= empty)”与简单的“else”完全相同。把它指出给他,他应该踢自己。如果他不这样做,请质疑他在团队中的角色。

应该使用什么方法来查找/解决问题(代码覆盖率、代码审查、黑盒测试等)

静态代码分析工具可以捕捉到这类问题。但是,我不知道任何 Javascript。JSLint可以捕捉到很多不好的东西,但不能捕捉到逻辑流问题。

于 2008-10-22T17:16:50.863 回答
1

我不相信这个问题完全是特定于语言的。您可以用多种其他语言构造类似(有缺陷的)条件语句。

另外,我认为条件语句以这种方式构造没有正当理由。正如您在评论中所说,第三块中的语句永远不会完成。

通过代码审查,您可能最有效地发现这样的错误。但是,由于这需要至少一名开发人员花费相当多的时间,因此开发高质量的单元测试和检查代码覆盖率可能会更好地为您服务。在这种情况下,您可能会注意到条件语句的第三部分从未使用过。

于 2008-10-22T17:10:20.690 回答
1

我知道我记得在我大学的第一年或第二年写过一些类似的东西,在我知道之前。但我现在找不到这样做的理由。

它甚至接近合法的唯一方法是如果“空”或“form_field”是一个不稳定的值,类似于 VB 的 Now() 函数。但在那种情况下,我不会这样写。相反,您在 if 块上方捕获该值并测试捕获的值。

于 2008-10-22T17:11:43.667 回答
1

也许不是在 JavaScript 中,但任何支持多线程编程的语言,以这样的方式声明 form_field ,以便在多个线程之间共享,实际上可以看到这种情况发生。

例如,彼得森的算法包含一个类似无用的双重检查:

     turn = 1;
     while( flag[1] && turn == 1 );

不过,这可以防止竞争条件。生成一个测试来引起它仍然是非常困难的。

如果没有可能的竞争条件,那么当我与 NASA 签约时,我们曾经开玩笑地称之为“宇宙射线检查”。:-)

于 2008-10-22T17:34:53.480 回答
0

一般形式

if (a)
  //1
else if (!a)
  //2
else
  //3

总是可以简化为

if (a)
  //1
else
  //2

没有副作用。

于 2008-10-22T17:10:47.977 回答
0
  • 这个问题或多或少是特定于语言的(非 JS 的人可以在这里学习吗?)

不,你可以在任何语言中遇到这种带有分支和比较的代码。

  • 代码以这种方式结束是否有正当理由?
  • 应该使用什么方法来查找/解决问题(代码覆盖率、代码审查、黑盒测试等)

不,不是。我猜该代码开始于布尔比较以外的其他东西。也许它是空的、数字的或非数字的,或者是空的,1-5 个字符,或者超过 5 个字符,诸如此类。当逻辑更改为空或非空时,应该删除第三个块 - 这通常会在同行评审或类似的事情中被发现。

根据语言的不同,一些编译器甚至可能会捕捉到这一点。审查会抓住它;黑盒测试不会,因为您不会检查代码,但白盒测试会(尽管在实际完成任何测试之前,您也应该在看到代码后立即注意到它)。

于 2008-10-22T17:15:00.447 回答
0

如果您正在测试单个条件 A,则此类问题很容易发现,因为您知道您可以有 A 和非 A。

如果您有条件 A 和 B,这也不难做到。您寻找 A、非 A 和 B、非 A 和非 B(例如)——您可以很容易地看出您已经涵盖了所有案例。

有时,无论出于何种原因,条件可能会被重构,然后(以上面人为的例子)同时留下三个块,以及由此产生的 WTF。

但是,如果您有条件 A、B、C 和 D 怎么办?堆叠 if-else 确实是一种粗糙的方法,但有时这就是它的完成方式。

通过创建完整的真值表很容易发现逻辑覆盖中的“漏洞”。一个很好的方法是使用卡诺图。卡诺图上的维基百科条目是一个很好的起点(甚至还有图片!)。对于软件编码,您希望完全覆盖地图而没有重叠(至少,通常是这样)。

于 2008-10-22T17:23:34.050 回答
0

不同的气味会出现不同的测量结果。

我发现圈复杂度工具很有用。任何复杂度超过 5 的东西都值得仔细研究。

于 2008-10-22T17:39:14.237 回答
0

这发生在我们公司,我认为第二个 else 中的“死代码”被执行是最有趣的事情。在我们的例子中,它是一个无类型指针(不要问为什么我们有这些),它被错误地设置并强制转换为具有布尔字段的类。

if (A = TRUE) .. else if (A == FALSE) .. else ..”应用于布尔字段。生成的 asm 代码如下:

cmp al,$01
jnz +$0c
...
test al,al
jnz +$0c
...

清除al中的值 > 1 并且它下降到else ..

编码员写这个期望它发生的事实是另一回事......

于 2009-10-20T09:59:55.063 回答