测试GUI代码:我应该使用模拟库吗?

测试GUI代码:我应该使用模拟库吗?

问题描述:

最近,我一直在用Python开发一个GUI应用程序的同时尝试使用TDD。我发现验证我的代码功能的测试非常令人放心,但遵循TDD的一些推荐做法非常棘手。也就是说,首先写测试很困难。我发现很难让我的测试可读(由于大量使用模拟库)。测试GUI代码:我应该使用模拟库吗?

我选择了一个名为mocker的嘲讽库。我使用它很多,因为我测试的很多代码都会调用(a)依赖系统状态的应用程序中的其他方法或(b)没有事件循环等情况下不能存在的ObjC/Cocoa对象等。

不管怎样,我已经得到了很多的测试,如下所示:

def test_current_window_controller(): 
    def test(config): 
     ac = AppController() 
     m = Mocker() 
     ac.iter_window_controllers = iwc = m.replace(ac.iter_window_controllers) 
     expect(iwc()).result(iter(config)) 
     with m: 
      result = ac.current_window_controller() 
      assert result == (config[0] if config else None) 
    yield test, [] 
    yield test, [0] 
    yield test, [1, 0] 

注意,这实际上是三个测试;全部使用相同的参数化测试功能。下面是正在测试的代码:

def current_window_controller(self): 
    try: 
     # iter_window_controllers() iterates in z-order starting 
     # with the controller of the top-most window 
     # assumption: the top-most window is the "current" one 
     wc = self.iter_window_controllers().next() 
    except StopIteration: 
     return None 
    return wc 

一个我用嘲笑者注意到的事情是,它更容易第二首写的应用程序代码,然后回去写测试,因为大多数的我嘲笑了许多方法调用,编写模拟调用的语法比应用程序代码更冗长(因此写得更难)。编写应用程序代码更容易,然后将测试代码模型化。

我发现使用这种测试方法(以及一些学科),我可以轻松编写100%测试覆盖率的代码。

我想知道这些测试是否是好的测试?当我终于发现编写好的测试的秘密时,我会后悔这样做吗?

我是否违反了TDD的核心原则,以至于我的测试徒劳无功?

单元测试在重构代码时非常有用(即完全重写或移动模块)。只要你在进行大的改变之前进行单元测试,你就会有信心在你完成时没有忘记移动或包含某些东西。

如果您在编写代码并使其通过之后编写测试,那么您没有执行TDD(您也没有从Test-First或Test-Driven开发中获得任何好处..请查看SO对TDD权威书籍)

的事情之一,问题我已经与 用嘲弄的是,它更容易 先写的应用程序代码和 然后回去写测试 第二,因为大多数注意到我是 嘲笑许多方法调用和 s yntax编写的模拟调用比应用程序代码更加详细(因此难以写入 ) 。这是 更容易编写应用程序代码,然后 模拟测试代码。

当然,它更容易,因为你只是在用特定类型的笔刷绘制橙色后测试天空是橙色的。 这是加装测试(用于自我保证)。嘲笑是好的,但你应该知道如何以及何时使用它们 - 正如俗话所说'当你有一把锤子时,一切看起来都像钉子一样'编写一整本不可读的,不太可能的帮助文档也很容易 - 测试。花费时间了解测试的内容是可以用来修复损坏的时间。

而且一点是:

  • 阅读Mocks aren't stubs - Martin Fowler如果您还没有。谷歌出了一些记录良好ModelViewPresenter图案化的图形用户界面(假的/模拟出的UI如果需要的)实例。
  • 研究你的选择,并明智地选择。我会用白色的左肩上的光环扮演那个说'不要这样做'的人。阅读这个问题关于my reasons - 圣贾斯汀在你的右肩上。我相信他也有话要说:)

请记住,TDD不是一个万能的。这很难,它应该很难,“提前”写嘲笑测试特别困难。

所以我会说 - 做什么适合你。即使它不是“认证的TDD”。我基本上做同样的事情。

您可能希望为GUI提供您自己的API,该API位于控制器代码和GUI库代码之间。这可能更容易模拟,或者你甚至可以添加一些测试钩子。

最后但并非最不重要的是,您的代码对我来说看起来不太难理解。使用mocks的代码通常很难理解。幸运的是,Python嘲笑比其他语言更容易和更清晰。