当所需代码几乎没有逻辑时,是否仍然使用TDD编写测试? 为什么?

TDD应该具有100%的代码覆盖率。 这是否意味着应该为属性getter和setter编写测试,以及其他不包含实际逻辑的方法,例如处理外部APIfunction?

例1:

下面是一个示例方法(这也恰好是另一个SO问题的例子,它解决了如何最好地测试它,如果我们要测试它)。 这种方法做得不多。 它是停止服务的System.ServiceProcess.ServiceControllerfunction的外观。 目前这个代码不是使用TDD编写的,但如果是,那么它应该是一个应该测试的东西吗? 这里的逻辑非常少。 测试本身并没有那么有用。

仅供参考:如果您想回答如何最好地测试它(IoC&Adapter Pattern vs. Detouring),请参阅其他问题 。

 Public Function StopService(ByVal serviceName As String, ByVal timeoutMilliseconds As Double) As Boolean Implements IWindowsServicesService.StopService Try Dim service As New ServiceController(serviceName) Dim timeout As TimeSpan = TimeSpan.FromMilliseconds(timeoutMilliseconds) service.[Stop]() If timeoutMilliseconds <= 0 Then service.WaitForStatus(ServiceControllerStatus.Stopped) Else service.WaitForStatus(ServiceControllerStatus.Stopped, timeout) End If Return service.Status = ServiceControllerStatus.Stopped Catch ex As Win32Exception Return False Catch ex As TimeoutException Return False End Try End Function 

例2:

如果有人认为代码仍然有一些逻辑,因此在进行TDD时需要进行测试,那么下面的代码没有逻辑:

 Public Function GetProcess(ByVal serviceName As String) As Process Dim managementObject As New ManagementObject(String.Format("Win32_service.Name='{0}'", serviceName)) Dim processID As Integer = CType(managementObject.GetPropertyValue("ProcessID"), Integer) Dim process As Process = process.GetProcessById(processID) Return process End Function 

TDD 应该具有100%的代码覆盖率。 与其他方法相比,TDD 往往具有非常高的代码覆盖率。 如果你没有在没有失败的测试的情况下编写一行代码,如果你严格遵循,那么是的,你将获得100%的覆盖率。 但是我们大多数人并没有严格遵守这一规定,完美的代码覆盖率并不是TDD的目标 。 高代码覆盖率是测试驱动开发的一个很好的副作用 ,但它不是重点。

我们大多数人都没有专门测试简单的getter和setter作为TDD过程的一部分。 但是,在我们需要它之前,我们不会创建需要getter和setter的字段 – 其中“need”被定义为失败测试。 因此,getter和setter将作为理所当然的测试,因为它们是根据我们测试驾驶的方法创建的。

你的两个例子都有足够的逻辑值得测试; 我会测试它们两个。

为了充分披露: 我不是TDD的专家(我实际上并没有使用它,也从未有过),但我认为我可以在这种情况下对TDD倡导者的无知进行辩论。

想象一下,你有一个简单的“零逻辑”属性/function,如例2。 假设您实现了自己的GetProcessById版本,其function略有不同,但可以与Process对象互换。 你决定不为这个函数编写一个测试,并说“啊,我只是把它委托给经过良好测试的库,我不可能搞砸了。” 这是你的第一个错误。 “我不可能搞砸了”是程序员经常告诉自己的最糟糕的谎言。

假设从现在起六个月后你意识到你需要用一些额外的东西来扩展Process 。 您委派所有正确的方法并覆盖GetProcessById 。 您现在正式必须测试这种“零逻辑”方法。 那就是麻烦。 多态性和编程语言的许多其他特性(甚至不是严格面向对象的特性)导致代码不能完全按照您的想象去做。

所以,话虽如此,如果您遵循严格的TDD方法,并且您正在努力实现100%的测试覆盖率,那么您将需要测试“零逻辑”方法,就像这两种方法一样。

我能想象的唯一例外是.NET特有的,它是自动实现的属性,测试中Getter和Setter没有任何意义,因为即使它们没有,你也无能为力。 测试包含在属性中的对象,而不是属性本身。

TDD人员,这样做总结得很好吗?

完全披露: 我不使用正式的TDD而且永远不会

您的代码示例封装了第三方复杂API以完成某些任务。 错误来自哪里?

大多数错误都是由API的意外,可能是未记录的行为引起的。 在任何情况下(Windows版本/区域设置/网络设置等)都可能很难让这些事情正确行事。您只需记录人们使用Win32 API所犯的错误和误解,就可以成为世界着名的博主 。

  • 最重要的测试是针对真实API的测试。 您需要一些设置和拆卸代码来创建流程或服务。
  • 模拟/ IoC不是很有价值。 您只是certificate您正在按特定顺序进行特定的API调用。 在现实世界中遇到的所有情况中,您需要certificate您的代码正在实现您想要的目标。
  • 我真的认为你不能在这里对模拟进行测试优先开发。 想象一下,你在第三方API中发现了一个错误 ( 它发生了 )。 你需要解决这个bug。 您甚至可能需要完全改变您的方法,可能是PInvoke到Win32 API或某些COM对象。 在那种情况下,模拟测试只是浪费时间。
    1. 首先,您必须编写一个实际上与真实API相关的解决方法。
    2. 然后,您必须编辑模拟测试以匹配变通方法。
    3. 您无法首先编辑模拟测试,因为您必须尝试解决方法以了解它是否真的有效。

我的世界是垂直市场桌面软件。 我们有一个像你这样的例程库,我们对它们进行了真实的测试。 有时我们会在特定的Windows版本/区域设置/任何内容中发现错误。 然后我们扩展测试以重现错误并validation修复,并确保在我们的测试环境集上重新运行它们。 读者注意:如果您的代码只需要在一台服务器上运行 ,那么您的世界可能就不同了 ,您也不需要这样做。