English 中文(简体)
当所需的代码几乎没有逻辑时,是否仍然使用TDD编写测试?为什么?
原标题:Does one still write tests with TDD when the desired code has little to no logic? Why?

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

Example 1:

下面是一个示例方法(恰好也是另一个SO问题,如果我们要测试它,它涉及如何最好地测试它)。这个方法没有多大作用。它是停止服务的System.ServiceProcess.ServiceController功能的一个门面。目前,这个代码不是用TDD编写的,但如果是,它会是应该测试的吗?这里几乎没有逻辑这本身不会有那么大帮助。

仅供参考:如果您想回答如何最好地测试它(IoC&;适配器模式与Detouring),请参阅另一个SO问题

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

Example 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的字段——其中“需要”被定义为失败的测试。所以吸气剂&;setter当然会被测试,因为它们是根据我们正在测试的方法的需要重新创建的。

你的两个例子都有足够的逻辑,值得检验;我会试驾他们两个。

问题回答

为了充分披露:我不是TDD方面的专家(我实际上没有使用过,也从来没有使用过),但我认为我可以从我的无知中为TDD倡导者辩护

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

假设六个月后您意识到需要用一些额外的东西来扩展Process。您委托了所有正确的方法并覆盖GetProcessById。您现在正式必须测试这个“零逻辑”方法。这就是问题所在。编程语言的多态性和许多其他特性(即使不是严格面向对象的)导致代码不能像你想象的那样完成

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

我能想到的唯一例外是.NET和它自动实现的属性,在那里测试Getter和Setter是否正常工作是没有意义的,因为即使它们没有正常工作,你也无能为力。测试封装在属性中的对象,而不是属性本身。

TDD的人,这总结得很好吗?

全面披露:我不使用正式的TDD,也从来没有

您的代码示例封装了一个第三方复杂的API来完成一些工作。虫子从哪里来?

大多数错误都是由API中意外的、可能未记录的行为引起的。在各种情况下(Windows版本/区域设置/网络设置等),要让这些事情正确运行可能非常困难。您实际上可以成为世界著名的博主只是通过记录人们使用Win32 API所犯的错误和误解。

  • The most important tests are tests against the real API. You need some setup and teardown code to create processes or services.
  • Mocking/IoC aren t very valuable. You re just proving that you are making particular API calls in a particular order. You need to prove that your code is achieving what you want, in all the situations it will encounter in the real world.
  • I really think you can t do test-first development against mocks here. Imagine you find a bug in the third-party API (it happens). You ll need to work round the bug. You might even need to totally change your approach, maybe PInvoke to the Win32 API or some COM object. In that situation, mocked tests would just be a waste of time.
    1. First you d have to code up a workaround that actually works against the real API.
    2. Then you d have to edit the mocked tests to match the workaround.
    3. You couldn t edit the mocked tests first, because you have to try the workaround out to know whether it actually works.

我的world是垂直市场的桌面软件。我们有一个像你这样的例程库,我们对它们进行了现实的测试。偶尔我们会在特定的Windows版本/区域设置/其他什么上发现错误。然后我们扩展测试以复制错误并验证修复,并确保在我们的一组测试环境中重新运行它们。请读者注意:如果你的代码只需要在一台服务器上工作,也许您的世界是不同的,您不需要这样做





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...