通常,在谈论编码标准时,我们指的是程序本身的代码,但是单元测试呢?是否存在某些单元测试独有的某些编码标准准则?这些是什么?
通常,在谈论编码标准时,我们指的是程序本身的代码,但是单元测试呢?是否存在某些单元测试独有的某些编码标准准则?这些是什么?
Answers:
我不禁想到了测试代码的三种编码风格差异。
在命名测试方法时,我遵循的模式shouldDoSomethingWhenSomeConditionHolds
。
在测试中,通常遵循以下间距模式:
@Test
shouldReturnAccountBalenceWhenGetBalenceIsCalled() {
// Some lines
// of setup code
// go here.
// The action being tested happens after a blank line.
// An assertion follows another blank line.
}
有些人坚持每个测试仅一个断言,但这远非普遍。
测试代码中的DRY(不要重复自己)比生产代码中的考虑要少。虽然应该将某些重复的代码放置在setUp方法或testUtils类中,但是在测试代码中争取零重复将导致紧密耦合且不灵活的测试,从而不利于重构。
Roy Osherove建议使用以下模式来命名测试:
NameOfMethodUnderTest_StateUnderTest_ExpectedBehavior()
参见http://weblogs.asp.net/rosherove/archive/2005/04/03/TestNamingStandards.aspx
NameOfMethodUnderTestStateUnderTestExpectedBehavior()
;但它可以提高可读性;)
最主要的是要记住单元测试本质上是微型规范。这意味着重点必须始终放在可读性上。
首先,这意味着名称必须明确传达正在测试的内容和主张的内容。
其次,尽管有时被遗忘的是,作为规范,它们应该这样做-指定行为。也就是说,单元测试不应包含逻辑-否则它们有可能陷入重复程序功能而不是对其进行测试的陷阱。
有时测试涉及的对象设置起来很复杂,您应该使用对象母体或测试数据构建器之类的方法,努力使此设置逻辑与测试分开。
我将以一些书建议作为结尾:
xUnit测试模式:重构测试代码:很棒的书,有人说这有点干,但是我不这么认为。详细介绍了组织测试的多种不同方式以及如何使其保持可维护性。如果您使用的是类似NUnit之类的东西,则相关。
单元测试的技巧:.Net中的示例:有关编写和维护测试的精髓的最佳书籍。尽管真的很新,但我发现模拟部分已经过时了,因为AAA语法现在已经很标准了,而不仅仅是另一种实现方式。
在测试的指导下,不断发展的面向对象软件:这本书真是太神奇了!迄今为止,最好的单元测试书和唯一的高级手册将单元测试视为设计过程中的头等公民。在公开测试版中正在阅读此书,此后一直在推荐。整本书中都使用了出色的真实示例。但是建议您先阅读罗伊的书。
不要在单元测试中添加逻辑。例如,假设您正在测试一个add方法,则可能会有类似以下内容:
void MyTest_SaysHello()
{
string name = "Bob";
string expected = string.Format("Hello, {0}", name);
IMyObjectType myObject = new MyObjectType();
string actual = myObject.SayHello(name);
Assert.AreEqual(expected, actual);
}
在这种情况下,您可能会重复与测试中相同的逻辑,因此实际上是在测试“ 1 + 1 == 1 + 1”,而不是“ 1 + 1 == 2”,即“真实”测试。因此,您真正想要的测试代码是:
void MyTest_SaysHello()
{
string expected = "Hello, Bob";
IMyObjectType myObject = new MyObjectType();
string actual = myObject.SayHello("Bob");
Assert.AreEqual(expected, actual);
}
描述性的长方法名称。 请记住,永远不会从代码中调用测试方法(它们是通过单元反射运行程序通过反射来发现和调用它们的),因此,发疯并使用50-80个字符长的方法名称是可以的。特定的命名约定(驼峰式,下划线,“应该”,“必须”,“何时”,“给出”等)并不重要,只要名称能回答以下三个问题即可:
测试方法应简短。
测试方法应具有简单的线性结构。没有if或loop构造。
测试方法应遵循“排列-作用-断言”模式。
每个测试应测试一件事。这通常意味着每个测试一个声明。像这样的测试{ Do A; Assert B; Assert C; }
应重构为两个:{ Do A; Assert B; }
和{ Do A; Assert C; }
避免使用随机数据或类似“ DateTime.Now”的内容
确保在测试结束时所有测试夹具成员都恢复到原始状态(例如,使用拆解)
即使您无情地删除了生产代码中的重复项,测试夹具中的代码重复项也没有那么重要。
类似于Farmboy已经提到的方法名称格式
<MethodName>Should<actionPerformed>When<Condition>
例如
GetBalanceShouldReturnAccountBalance() {