2

我有一个Coordinate类,它有一个add(Coordinate)方法。在为此类编写单元测试时,我对assertEqual结果进行了测试:


a = Coordinate(1,2,3)
b = Coordinate(5,6,7)

result = a.add(b) 

assertEqual(result.x, 6)
assertEqual(result.y, 8)
assertEqual(result.z,10) 

我可以很容易地“伪造”这个:


def add(self, other):
    return Coordinate(6,8,10)

这是测试失败的最简单的解决方案。下一步是编写第二个测试,以防止我以这种方式伪造它。我可以:

  • assertEqual用不同的数字编写另一个测试(所以假装Coordinate(6,8,10)不通过,或者
  • 使用两个不同的输入编写assertNotEqual测试,确保结果不是6,8,10.

如果我编写一个assertEquals测试,我会得到两个看起来非常非常相似的测试。这是一个问题吗?如果我在项目中看到类似的代码,我会很想重构它。我是否也应该为测试代码这样做 - 如果是这样,这是否意味着对测试最终都会被重构?

如果我写一个assertNotEqual,测试只是测试“假结果”——我很确定这永远不会来自算法错误。本质上,一旦我编写了测试,就停止伪造结果,这样两个测试都通过了,assertNotEquals测试可以安全地删除,我仍然对代码有信心——所以我会编写测试,修复假的,删除测试,这似乎很愚蠢。

在这种情况下我应该怎么做?

4

5 回答 5

2

另一个不同数字的 assertEqual 测试就足够了。如果可能,请采用“边界”或不常见的情况,例如:

a = Coordinate(1,2,3)
b = Coordinate(-5,-6,-7)
...

AssertNotEqual 测试对于 IMO 读者来说是荒谬且不直观的。

无论如何,我不会太担心这种测试。作为读者,很明显,编写它们的开发人员只是想测试几个案例,而想要重构它们需要一个真正的重构极端分子。我的意思是,它只有 2 次测试,几乎没有重复,意图很明显,而且当对象发生变化时,你不必重写 300 行代码......

于 2012-08-09T18:09:15.300 回答
2

正如您所描述的那样,我不会太担心能够“假通过”测试-始终可以if在您的方法中编写一个复杂的语句以使您的每个测试用例都通过。相反,请查看您的方法中涉及的逻辑,add并确保您的测试用例涵盖所有代码分支——我认为这应该足够好了。

于 2012-08-09T11:51:45.860 回答
2

根据测试代码使用的特定情况编写测试来防止有人恶意编写代码以伪造测试代码是不可能的。所以你不应该尝试。

当我说“不可能”时,我的意思不仅仅是“非常难”,它可能是打破正式系统的骗子悖论的一个实例。

于 2012-08-09T11:52:12.667 回答
1

注意:为了简单起见,我将 Coordinate 更改为 Int。下面的语法也是组成的..所以不会执行。但这应该让我明白我的意思

testAdd()
  assertThat(2.Add(2), isEqualTo(4))

然后,您可以通过始终使 Add return 4 来伪造这一点。在三角测量旁边(通过改变某些参数来驱动通用代码)。

testAdd()
  assertThat(2.Add(2), isEqualTo(4))
  assertThat(3.Add(5), isEqualTo(8))

现在你需要做一些实际的工作。一旦它是绿色的,你可以让这两个测试保持不变,或者你可以删除简单/琐碎的测试——只要它不会让你的信心下降。如果重复困扰您,您可以查看您的测试运行程序是否支持“参数化测试”

[2,2,4]
[3,5,8]
testAdd(operand1, operand2, expectedResult)
  assertThat(operand1.Add(operand2), isEqualTo(expectedResult))
于 2012-08-10T05:48:06.503 回答
0

Coordinate.Add() 方法是什么样的?

似乎方法应该处理如何添加(没有必要伪造它),然后您需要做的就是:

# In your test setUp code
testCoord = Coordinate(6, 8, 10)  # Explicitly setting the value you expect the test to return.
addCoord1 = Coordinate(1, 2, 3)
addCoord2 = Coordinate(5, 6, 7)

# The test
addCoord1.add(addCoord2)
assertEqual(testCoord, addCoord1, "Testing addition of coordinates using add() method.")

如果我错了,请纠正我,但是您使用的是单元测试框架吗?我个人会将对象创建放在测试用例的 setUp 中unittest

于 2012-08-09T12:47:35.277 回答