我有一个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
测试可以安全删除,我将仍然有信心在代码 - 所以我写了测试,修复假,删除测试,这似乎相当愚蠢。
在这种情况下我该怎么做?
答案 0 :(得分:2)
我不会太担心能够如你所描述的那样“假冒”测试 - 总是可以在你的方法中编写一个复杂的if
语句来制作你的每个测试用例通过。相反,请查看add
方法中涉及的逻辑,并确保您的测试用例涵盖所有代码分支 - 在我看来应该足够好。
答案 1 :(得分:2)
根据测试代码使用的特定情况,编写防止恶意编写代码以伪造测试代码的测试是不可能的。所以你不应该尝试。
当我说“不可能”时,我并不仅仅意味着“非常努力”,它可能是Liar Paradox打破正式系统的一个实例。
答案 2 :(得分:2)
另一个具有不同数字的assertEqual测试将足够好。如果可能的话,采取“边缘”或不常见的情况,如:
a = Coordinate(1,2,3)
b = Coordinate(-5,-6,-7)
...
AssertNotEqual测试对于读者IMO来说是荒谬的并且不直观。
无论如何,我不会太担心这种测试。作为读者,显而易见的是,编写它们的开发人员只是想测试几个案例,并且需要一个真正的重构极端主义者来重构它们。我的意思是,它只有2个测试,几乎没有重复,意图是显而易见的,并不像你必须在对象改变时重写300行代码......
答案 3 :(得分:1)
注意:为了简单起见,我将把Coordinate更改为Int。以下语法也是由...组成的。所以不会执行。但它应该得到我的观点
testAdd()
assertThat(2.Add(2), isEqualTo(4))
然后你可以通过总是添加返回4来伪造这个。在三角测量旁边(通过改变某些参数来驱动通用代码)。
testAdd()
assertThat(2.Add(2), isEqualTo(4))
assertThat(3.Add(5), isEqualTo(8))
现在你需要让Add来做一些实际的工作.. 一旦它是绿色的,你可以让两个测试保持不变,或者你可以删除简单/琐碎的测试 - 只要它不会让你的信心下降。如果复制困扰您,您可以看看您的测试运行器是否支持“参数化测试”
[2,2,4]
[3,5,8]
testAdd(operand1, operand2, expectedResult)
assertThat(operand1.Add(operand2), isEqualTo(expectedResult))
答案 4 :(得分: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.")
如果我错了,请纠正我,但你使用的是单元测试框架吗?我个人在unittest
中将对象创建放在了测试用例的setUp中。