我很难理解为什么在我看到的大多数专业TDD代码中每个功能只有一个测试.当我最初接触TDD时,如果它们相关,我倾向于对每个功能进行4-5次测试,但我认为这似乎不是标准.我知道每个函数只进行一次测试更具描述性,因为你可以更容易地缩小问题的范围,但我发现自己很难想出功能名来区分不同的测试,因为许多测试非常相似.
所以我的问题是:在一个函数中放置多个测试真的是一个不好的做法,如果是这样,为什么呢?那里有共识吗?谢谢
编辑:哇哇大的答案.我相信.你需要把它们全部分开.我经历了最近的一些测试,并将它们全部分开,并且看起来更容易阅读并帮助我更好地理解我正在测试的内容.同样通过给测试他们自己冗长的冗长名称,它给了我一些想法,比如"哦等我没有测试这个其他的东西",所以我认为这是我要走的路.
很棒的答案.要赢得冠军很难
jus*_*ody 12
看起来你问"为什么在我看过的大多数专业TDD代码中每次测试只有一个断言 ".这可能会增加测试隔离度,以及出现故障时的测试覆盖率.这就是我用这种方式创建TDD库(用于PHP)的原因.说你有
function testFoo()
{
$this->assertEquals(1, foo(10));
$this->assertEquals(2, foo(20));
$this->assertEquals(3, foo(30));
}
Run Code Online (Sandbox Code Playgroud)
如果第一个断言失败,你就不会看到其他两个断言会发生什么.这并不完全有助于查明问题:这是输入特有的,还是系统性的?
是的,您应该在TDD中测试每个功能的一个行为.这就是原因.
而且,最后一个问题-为什么不能有每个功能的一个测试?有什么好处?我不认为对功能声明征税.
建议进行高粒度的测试,不仅仅是为了便于识别问题,而且因为函数内部的排序测试可能会意外地隐藏问题.假设例如foo带有参数的调用方法bar应该返回23- 但是由于对象初始化其状态的方式中的错误,42如果它被调用为新构造对象的第一个方法(之后,它会返回)正确切换到返回23).如果您的测试foo在对象创建后没有出现,那么您将会错过这个问题; 如果你一次测试5个,那么你只有20%的几率意外地做到了.每个功能进行一次测试(以及每次都干净地重置和重建所有内容的设置/拆卸安排),您将立即修复该错误.现在这只是一个人为简单的问题,仅仅是出于讨论的原因,但是一般的问题 - 测试不应该相互影响,但往往除非它们每个都被设置和拆除功能所包围 - 确实很大.
是的,将事情命名(包括测试)并不是一个小问题,但不能以此为借口来避免适当的粒度.一个有用的命名提示:每个测试都会检查给定的特定行为 - 例如,"2008年的复活节是在3月23日" - 而不是通用的"功能",例如"正确计算复活节日期".
我很难理解为什么在我看到的大多数专业TDD代码中每个功能只有一个测试
当你说'测试'时,我假设你的意思是'断言'.通常,测试应该只测试函数的单个"用例"."用例"是指:代码可以通过控制流语句流经的路径(不要忘记处理的异常等).基本上,您正在测试该功能的所有"要求".例如,假设你有一个如下功能:
Public Function DoSomething(ByVal foo as Boolean) As Integer
Dim result as integer = 0
If(foo) then
result = MakeRequestToWebServiceA()
Else
result = MakeRequestToWebServiceB()
End If
return result
End Function
Run Code Online (Sandbox Code Playgroud)
在这种情况下,函数可以使用2个"用例"或控制流.此功能至少应有2次测试.一个接受foo为true并将if(true)代码分支的一个,以及一个接受foo为false并向下移动到第二个分支的代码.如果你有更多的if语句或流程代码可以通过,那么它将需要更多的测试.这有几个原因 - 对我来说最重要的是没有它,测试会太复杂,难以阅读.还有其他原因,例如在上述函数的情况下,控制流程基于输入参数 - 这意味着您必须调用该函数两次以测试所有代码路径.一旦您在测试IMO中进行测试,就不应该再调用该函数.
但我发现自己很难想出功能名称来区分不同的测试,因为许多测试非常相似
也许你过度思考了?不要害怕为你的测试功能编写疯狂的,过于冗长的名字.无论测试做什么,用英文写,使用下划线,并为名称提出一套标准,以便其他人查看代码(包括你自己6个月后)可以轻松地弄清楚它的作用.记住,你实际上不必自己调用这个函数(至少在大多数测试框架中),所以谁在乎它的名字是100个字符.疯了.在上面的例子中,我的2个测试将命名为:
DoSomethingTest_TestWhenFooIsTrue_RequestIsMadeToWebServiceA()
DoSomethingTest_TestWhenFooIsFalse_RequestIsMadeToWebServiceB()
Run Code Online (Sandbox Code Playgroud)
此外 - 这只是一般指导原则.肯定会出现在同一单元测试中有多个断言的情况.当您测试相同的控制流时会发生这种情况,但是在编写断言语句时需要检查多个字段.以此为例 - 对函数进行测试,该函数将CSV文件解析为具有Header,Body和Footer字段的业务对象:
Public Sub ParseFileTest_TestFileIsParsedCorrectly()
Dim target as new FileParser()
Dim actual as SomeBusinessObject = target.ParseFile(TestHelper.GetTestData("ParseFileTest.csv")))
Assert.Equals(actual.Header,"EXPECTED HEADER FROM TEST DATA FILE")
Assert.Equals(actual.Footer,"EXPECTED FOOTER FROM TEST DATA FILE")
Assert.Equals(actual.Body,"TEST DATA BODY")
End Sub
Run Code Online (Sandbox Code Playgroud)
在这里,我们确实测试了相同的用例,但我们需要多个断言来检查所有数据并确保我们的代码实际工作.
-DREW