8

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

我选择了一个名为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

我在使用 mocker 时注意到的一件事是,首先编写应用程序代码然后再返回编写测试更容易,因为大多数时候我都在模拟许多方法调用和编写模拟的语法调用比应用程序代码更冗长(因此更难编写)。编写应用程序代码并以此为基础对测试代码进行建模会更容易。

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

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

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

4

3 回答 3

8

如果您在编写代码并使其通过之后再编写测试,那么您并没有进行 TDD(您也没有从测试优先或测试驱动开发中获得任何好处。查看 SO questions 以获取有关 TDD 的权威书籍)

我在使用 mocker 时注意到的一件事是,首先编写应用程序代码然后再返回编写测试更容易,因为大多数时候我都在模拟许多方法调用和编写模拟的语法调用比应用程序代码更冗长(因此更难编写)。编写应用程序代码并以此为基础对测试代码进行建模会更容易。

当然,它更容易,因为您只是在通过使用特定类型的画笔将天空涂成橙色后测试天空是否为橙色。这是改造测试(为了自信)。模拟很好,但你应该知道如何以及何时使用它们 - 就像谚语所说的“当你有一把锤子时,一切看起来都像钉子” 写一大堆不可读和没有帮助的东西也很容易- 是测试。花在了解测试内容上的时间是浪费的时间,可用于修复损坏的测试。

重点是:

  • 阅读Mocks are not stubs -如果您还没有的话,请阅读 Martin Fowler。谷歌出一些好的ModelViewPresenter模式 GUI 的文档实例(如有必要,假/模拟 UI)。
  • 研究您的选择并明智地选择。我会扮演那个在你左肩上戴着白色光环的人说“不要这样做”。阅读这个问题,了解我的原因- 圣贾斯汀在你的右肩上。相信他也有话要说:)
于 2008-09-17T04:33:46.390 回答
-2

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

于 2008-09-17T03:30:19.070 回答
-3

请记住,TDD 不是灵丹妙药。这很难,应该很难,而且“提前”编写模拟测试尤其困难。

所以我会说——做对你有用的事。即使它不是“经过认证的 TDD”。我基本上做同样的事情。

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

最后但并非最不重要的一点是,您的代码对我来说看起来并不太难读。使用模拟的代码通常更难理解。幸运的是,Python 中的模拟比其他语言更容易、更干净。

于 2008-09-17T11:08:17.270 回答