我最近加入了一家他们使用TDD的公司,但我仍然不清楚,例如,我们有一个测试:
[TestMethod]
public void ShouldReturnGameIsRunning()
{
var game = new Mock<IGame>();
game.Setup(g => g.IsRunning).Returns(true);
Assert.IsTrue(game.Object.IsRunning);
}
它的目的是什么?据我了解,这不测试任何东西!我这样说是因为它在嘲笑一个界面,并且说,对于IsRunning,它返回true,它永远不会返回不同的值......
我可能错了,因为每个人都说这是一个很好的做法等等......或者这个测试错了吗?
答案 0 :(得分:6)
此测试超出了界面,并验证界面是否公开了名为IsRunning
的布尔getter。
这个测试可能是在interface
存在之前编写的,可能在任何具体的IGame
类存在之前就已经存在了。我想,如果项目有任何成熟度,那么还有其他测试可以运用实际的实现并验证该级别的行为,并且可能在更传统的隔离主义上下文中使用模拟而不是扼杀理论形状。
这些测试的价值在于它迫使人们思考如何使用形状或物体。 “我不知道游戏究竟会做什么,但我确实知道我要检查它是否正在运行......”。因此,这种测试方式更多的是推动设计决策,以及验证行为。
这不是地球上最有价值的测试,但在我看来是有用的。
编辑:昨晚我打火车的时候我在火车上,但我想直接在答案中解答Andrew Whitaker的评论。
有人可能会争辩说,界面本身的签名足以执行所需的合同。但是,这实际上取决于您对接口的处理方式以及最终验证您要测试的系统的方式。
明确说明此功能作为测试可能有实际价值。您明确验证这是IGame
所需的功能。
让我们看一个用例,让我们说作为设计师你知道你想要为IsRunning
公开一个公共getter,所以你将它添加到界面。但是让我们说另一个开发人员得到这个并看到一个属性,但是在代码中的任何其他位置都没有看到它的任何用法,人们可能会认为它有资格删除(或删除代码腐烂,这通常是一件好事)没有伤害。然而,该测试的存在明确指出应该存在这种适当性。
如果没有这个测试,开发人员可以修改接口,删除实现,项目仍然可以正常编译和运行。直到很久以后,有人可能会注意到界面已被更改。
通过此测试,即使看起来好像没有人使用它,您的测试套件也会失败。测试的自我记录性质告诉您ShouldReturnGameIsRunning()
,如果IGame
应该真正公开IsRunning
获取者,那么至少应该产生对话。
答案 1 :(得分:5)
测试无效。 Moq是用于“模拟”被测方法使用的对象的框架。如果您正在测试IsRunning
,则可以使用Mock为IsRunning
依赖的那些方法提供某种实现,例如,使某些执行路径执行。
人们可以整天告诉你,先测试更好;你不会意识到它实际上直到你自己开始这样做并意识到你首先编写测试的代码有更少的bug,这将节省你和你的同事的时间,并可能使你的代码质量更高。
答案 2 :(得分:3)
可能是测试已经编写(之前)代码,这是一种很好的实践。
同样可能是这是一个由工具创建的毫无意义的测试。
答案 3 :(得分:1)
另一种可能性是代码是由当时不了解如何使用特定模拟框架的人编写的 - 并编写了一个或多个简单的测试来学习。 Kent Beck在他最初的TDD书中谈到了那种“学习测试”。
答案 4 :(得分:0)
这个测试过去可能有一点。它本可以测试一个具体的类。它本来可以测试一个抽象的 - 因为有时候模拟一个你想要测试的抽象类是有意义的。我可以看到一个(不太了解情况(如我自己))TDD做事方式的追随者如何留下这样的小混乱。清除死代码和死测试代码,并不真正适合红色,绿色,重构的自然工作流程(因为它不会破坏任何测试!)。 然而,历史并不是一种测试的理由,这种测试只会让读者感到困惑。所以,做一个好的boyscout并删除它。
答案 5 :(得分:0)
我认为这只是垃圾,只能证明moq按预期工作