Meck和测试驱动开发工作流程?

时间:2012-08-23 06:14:07

标签: unit-testing testing erlang mocking tdd

据我所知,TDD的典型工作流程(W1)如下:

  1. 开发功能测试;
  2. 运行测试并观察它失败;
  3. 开发功能;
  4. 再次运行测试并观察它通过;
  5. 重复1次。
  6. 但是对于Meck和其他模拟框架,工作流程(W2)可能如下:

    1. 为所有功能编写测试并观察它们是否失败;
    2. 借助模拟对象开发完整的系统原型(所有函数及其交互);
    3. 再次运行测试并观察它们通过;
    4. 逐步将每个模拟功能逐步更改为真实功能。
    5. 我倾向于认为W2比W1有一些优势:

      • 写得快;
      • 更容易集成,因为所有测试(单元测试和集成测试)都将提前编写;他们也会从一开始就过去;

      所以,问题是:

      W2真的具有上述优势吗?如果不是,我如何将Meck纳入我的日常开发中作为既定的例程,即使用它的工作流程是什么?或者我应该在没有任何指导的情况下随机使用Meck?

2 个答案:

答案 0 :(得分:3)

您无法独家使用模拟来使测试通过。如果可能,那么你的测试不值得他们的名字,或者你不需要用“真实”代码替换模拟,因为模拟已经按照你想要的代码做了。

模拟通常用于隔离被测系统(SUT),即您要测试的类,来自其依赖项。依赖项被模拟,SUT不是。

答案 1 :(得分:1)

W2假设您在开始之前已经完成了系统的正确设计 - 我很少进入一个位置。您必须预先进行大型设计; IME意味着您已经移动了开发过程的昂贵部分而不是消除它。如果你的初始设计恰好有缺陷(而且会是这样),那么恢复将是昂贵的。

通过by开头的测试是一个错误,而不是一个功能。编写特定的失败测试是至关重要的一步 - 您如何证明您编写的代码实际上有效?

我不能特别谈到Meck,但我可以谈谈一般的TDD工作流程,它自然地融合了各种各样的模拟对象。存在模拟对象以使单元测试通过,而不管系统的其余部分是否工作。它们还为您接下来需要做的事情提供了自然的路标。为了使单元测试A通过,你必须模拟一个B类。显然,接下来要做的是实现一个B类,其行为与它的模拟描述它的方式。

你的W1省略了几个关键步骤,包含这些步骤可能会澄清模拟对象在TDD中扮演的角色。插图为伪Perl,TDD看起来更像是这样:

while (not $project->is_feature_complete()) {
  my $feature_test = write_feature_test();
  die "You screwed up" if $feature_test->does_pass();
  $feature_test_suite->add($feature_test);
  while (not $feature_test_suite->does_pass()) {
    my $test = write_unit_test();
    die "You screwed up" if $test->does_pass();
    $unit_test_suite->add($test);
    while (not $unit_test_suite->does_pass()) {
      write_exactly_enough_code_to_pass_unit_test();
      while ($project->has_duplication()) {
        $project->eliminate_duplication();
      }
    }
  }
}

与W1的主要区别在于:

  • 围绕单元测试的循环是另一个特征测试循环。
  • 功能测试可能会暂时失败;在完成所有依赖项的集成之前,它无法通过。
  • 我们编写的代码通过单元测试非常简约。而且由于模拟对象比真正的工作类更容易编写,因此暗示我们在尝试时会模拟出我们发现的每个依赖项。
  • 消除重复是至关重要的,也是我们经常用实际实现替换模拟对象的步骤。

最后一点可能需要更多放大(最好不要重复 { 1整个 {{3}}。发生的事情是,进行第二次测试的最短方法通常是使用模拟对象的副本,该副本使第一次测试通过一些参数调整。在“消除重复”步骤中,我们将这两个模拟对象组合成一个参数化对象。一旦我们重复了几次循环,我们构建的模拟对象几乎与我们需要的真实对象完全相同,因此我们可以使用它的代码来开始实现它迄今为止隐藏的依赖。

在所有这些中,模拟对象的作用几乎总是相同的:允许您通过单元测试而不必立即实现整个系统。在我看来,使用它们来预先实现整个系统似乎浪费了大部分功能,同时也让您面临通常的大前期设计风险。我认为你不会得到你认为会有的好处;充其量,你改变会计,以减少“编码”所花费的时间。