TDD:添加测试状态的方法

时间:2009-09-08 03:50:01

标签: unit-testing tdd

所以,我开始为一个简单的程序(旁边的玩具游戏)写一些逻辑。您有一艘特定的船(称为设置),它是一艘船+模块。您从基于船舶的空设置开始,然后将模块添加到该设置。船舶也有一组编号的模块位置。

var setup = new Setup(ship); // ship is a stub (IShip) defined someplace else
var module = new Mock<IModule>().Object;
setup.AddModule(module, 1); // 1 = which position

所以,这是我测试方法中的代码。我现在需要断言这段代码。好吧,我需要一个getter方法吗?

Assert.AreEqual(module, setup.GetModule(1));

这可能听起来真的很愚蠢,我一点也不担心,但出于某些愚蠢的原因,我担心添加一个方法只是为了断言测试通过了。

这是否正常,实际上是TDD推出的设计过程的一部分?例如,我知道我需要一个AddModule方法,因为我想测试它,而这需要一个GetModule方法进行测试,这只是我的设计通过TDD的演变。

或者是这种气味,因为我甚至不知道我的代码中是否真的需要GetModule而且它只会用于测试?

例如,添加模块最终将影响设置的不同属性(装甲,盾牌,火力等)。问题是复杂的,我想从一个简单的测试开始。但最终,这些是我关心的公共属性 - 设置由其统计数据定义,而不是由模块列表定义。

3 个答案:

答案 0 :(得分:2)

有趣的问题。我很高兴听到你先写下测试。

如果您让设计通过测试表现出来,那么您更有可能只构建您需要的部分。但这是最好的设计吗?也许不是,但不要让你气馁 - 你的添加方法有效!

现在判断您以后是否需要GetModule方法可能为时尚早。现在,建立你需要的功能并变为绿色,然后慢慢重构它(再次从红色变为绿色)以获得你想要的设计。

答案 1 :(得分:1)

开发设计的一部分是从婴儿步骤开始,就像一个简单的方法,然后在足够支持它的时候成长为复杂的统计数据(最终放弃这个方法并改变测试)。在进行TDD时,不要指望您编写的第一个测试是针对理想的接口。随着设计的发展,可能会出现一些混乱现象。

话虽如此,如果您没有看到该方法的公共目的,请尽量将其可见性限制为对测试代码合理。虽然这样做最终会消失,因为你可以构建系统的其余部分并且有一些真实的测试作为set方法的副作用。

答案 2 :(得分:0)

我会谨慎地在我的班级中引入一个仅用于测试的公共方法。

有多种方法可以测试这个:

反思:GetModule方法是您班级中的私有方法(如果您的“统计信息”是私有的,这也可以使用),您可以通过反射在测试方法中访问它。这样可以很好地工作,唯一的麻烦是如果你改变私有方法的名称或添加/删除一些变量你不会得到任何编译器错误(但是,当然,你的测试会失败,你会很早就知道)

继承:GetModule方法可以受到保护(只有继承可见),并且您的测试类可以从主类继承。通过这种方式,您的测试类可以访问此方法,但这并未真正暴露给外部世界。

断言副作用:这是您真正考虑将模块添加到系统意味着什么的地方。如果它会影响某些“统计数据”,你可以编写测试,断言统计数据被适当修改。