首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Meck和测试驱动的开发工作流?

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

Stack Overflow用户
提问于 2012-08-23 06:14:07
回答 2查看 218关注 0票数 2

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

  1. 为一个函数开发一个测试;
  2. 运行测试,并看着它失败;
  3. 发挥功能;
  4. 再做一次测试,看着它通过;
  5. 重复1次。

但是,对于Meck和其他模拟框架,工作流(W2)可以是:

  1. 编写所有函数的测试,并观察它们的失败;
  2. 在模拟对象的帮助下,开发一个完整的系统原型(所有功能及其交互);
  3. 再做一次测试,看着它们通过;
  4. 逐步将每个模拟函数转变为一个真正的函数,一步一步。

我倾向于认为W2比W1有一些优势:

  • 写得更快;
  • 更容易的集成,因为所有的测试(包括单元测试和集成测试)都是预先编写的,而且它们从一开始就会通过;

因此,问题是:

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

EN

回答 2

Stack Overflow用户

发布于 2012-08-23 06:15:33

不能单独使用模拟来使测试通过。如果这是可能的,那么要么您的测试不值得使用它们的名称,要么您不需要用“真正的”代码替换模拟,因为模拟已经完成了您希望代码做的事情。

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

票数 3
EN

Stack Overflow用户

发布于 2012-08-24 00:44:52

W2假设您在启动系统之前已经完成了正确的系统设计--例如,我很少进入这个职位。您必须预先进行大型设计;IME意味着您已经移动了开发过程中昂贵的部分,而不是取消它。而且,如果您的初始设计碰巧有缺陷(而且它会有缺陷),那么恢复成本就会很高。

从一开始就通过的测试是一个bug,而不是一个特性。编写特别失败的测试是关键的一步--否则您将如何证明您编写的代码实际工作?

我不能具体地与Meck交谈,但我可以讨论一般的TDD工作流,它自然地结合了各种类型的模拟对象。无论系统的其余部分是否工作,都存在允许单元测试通过的模拟对象。它们也为你接下来需要做的事情提供了自然的路标。为了使单元测试A通过,您必须模拟一个B类,很明显,接下来要做的是实现一个B类,它的模拟描述它的方式。

您的W1遗漏了一些关键步骤,包括这些步骤可能会澄清模拟对象在TDD中所扮演的角色。如伪Perl所示,TDD看起来更像这样:

代码语言:javascript
复制
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)。发生的情况是,进行第二次测试的最短方法通常是使用模拟对象的副本,该对象在经过一些参数调整后进行第一次测试传递。在“消除重复”步骤中,我们将这两个模拟对象组合成一个参数化对象。一旦我们重复这个循环几次,我们构建的模拟对象与我们需要的实际对象几乎是完全相同的,因此我们可以使用它的代码来实现它迄今为止隐藏的依赖关系。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12085746

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档