【问题标题】:Unittesting dependant tests单元测试依赖测试
【发布时间】:2013-10-06 14:56:52
【问题描述】:

我已经搜索了该网站和一些文献,但无法得到明确的答案。我正在尝试学习单元测试,同时构建一个简单地用作白板的新网页,您可以在其中添加便利贴。

我有一个代表白板的 Canvas 对象和一个代表便利贴的票证对象。我有(目前)全局函数来检索唯一的画布,我像这样测试它:

this.testRetrieveCanvas = function()
{
    var canvas = getCanvas();

    this.assertTrue( canvas != null );
}

this.testCanvasType = function()
{
    var canvas = getCanvas();

    this.assertTrue( canvas instanceof Canvas );    
}

this.testIfCanvasIsReused = function()
{
    var canvas = getCanvas();

    this.assertEquals( canvas, getCanvas() );       
}

所以,我测试了三件事:

  1. 该方法是否返回画布?
  2. 它是真实的画布吗?
  3. 该方法是否总是给我相同的画布?

目前没有问题。但稍后,我正在测试“将票添加到画布”:

    this.testAddTicketToCanvas = function()
{
    var ticket = factory.createTicket("yellow");
    var canvas = getCanvas();

    canvas.addTicket( ticket );     

    this.assertTrue( canvas.contains( ticket ) );   
};

如您所见,我在测试中使用了 getCanvas() 函数。现在这是一个依赖测试吗?我的意思是,如果我希望这个测试能够毫无疑问地运行,前三个测试必须通过。如果它是依赖的,我将如何解决这个问题?

【问题讨论】:

  • 没有其他代码我帮不上什么忙,但你应该看看chaijs.com/api/bdd (chai)、sinonjs.org (sinon) 或 gofreerange.com/mocha/docs (mocha)介绍 javascript 中的模拟。
  • 我不确定您需要什么额外的代码来回答我的问题。也许我会改写:我是否违反了单元测试规则,使我的第四个单元测试依赖于前三个?
  • @DavidMaes 需要更多信息。你用的是什么测试框架?即您是否编写了“assertTrue”方法(如果是的话,您可以包含源代码吗?)或者您是从库中使用它吗?你也可以请包括“getCanvas()”的代码,因为这也是回答你的问题所需要的。
  • 我不同意,我已经提供了您需要的所有信息。该框架是无关紧要的,因为我在问一个一般的单元测试问题。我将再次改写:“你可以在单元测试中使用你在其他单元测试中测试过的功能吗?这是一个依赖项吗?”和“如果它是依赖项,你为什么以及如何规避这些类型的情况”?

标签: javascript unit-testing testing tdd


【解决方案1】:

严格来说,您应该重写 getCanvas() 以返回一个预先构造的(即不调用原始构造函数)画布的部分模拟。话虽如此,如果 canvas 的构造函数是一个空函数并且 getCanvas 方法不涉及业务逻辑,那么您应该没有问题。

我会更加警惕最后两个语句一起使用。 canvas.addTicket( ticket ); 没问题,因为它是正在测试的功能。但是随后您断言您已使用来自同一对象的方法添加了票证。如果这个方法还没有实现,或者返回 false,或者更糟的是 true,该怎么办?如果您的 addTicket 方法具有可以使其将票添加到列表但更改使 contains() 抛出异常或返回 false 或 true 的标志的次要效果怎么办?如果 contains 具有某些业务逻辑,它会为您发送它的票证返回 false,但对于生产环境中的同一票证返回 true(即您的测试票证尚未正确初始化、缺少状态、已标记为已排除)从环境的业务流程中),如果它现在没有逻辑,但是在项目进行两个月后,逻辑发生了变化,因此您的测试失败但其他一切正常(添加了一个新状态,并且没有此状态的对象被视为不存在,客户 a、b 和 c) 除外。我可以继续。

我的意思是,如果没有代码,我们无法具体回答您的问题,只能像上面那样为您提供指示和一般性答案。如果您真的不想发布代码,请考虑所有这些场景以及您能想到的所有其他场景,如果在这些场景下以这种方式测试您的代码不会破坏代码,也不会立即测试可预见的未来,那你就没事。

【讨论】:

  • 我确实可以制作一个新的 Canvas 而不是使用 getCanvas 方法。正如你所注意到的,我正在寻找一个普遍的答案。我非常愿意提供更多代码,但这违背了目的:)。对于 addTicket / contains 方法,我已经阅读了很多关于这个问题的文章。我无法测试 addTicket 方法,因为保存我所有票证的列表都是私有的。我认为我在这里有几个选择:-我公开门票(对我来说这不是一个好的设计决定,因为画布必须能够跟踪所有门票。-我将它作为一个组合进行测试。感谢您长期以来回应
【解决方案2】:

您的问题的简短回答是,不。 如果您的代码不违反任何单元测试 原则只要你遵守这些rules

通常,对于这些问题,会有大量关于模拟测试的某些部分的讨论,例如你的 getCanvas() 函数。我同意这个讨论背后是有原因的,如果你想继续进行测试或 TDD,你应该更深入地研究这个话题。 (请参考 Martin Fowler 的这个出色的article)。

但是,对于这是否是有效的单元测试的问题,我认为只要您遵守单元测试规则,它就无关紧要。

【讨论】:

  • 感谢您的回复。我确实渴望更深入地研究这个主题。但是,它有几个部分,我不完全理解。 1) 测试什么/不测试什么 2) 异步功能(例如加载文件并调度两个事件(成功和失败)的方法)我将很快深入研究 Martin Fowler 的文章。谢谢。我希望我能标记你两者都是很好的答案。
  • 确定。我很高兴能帮上忙
猜你喜欢
  • 2021-06-19
  • 2012-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-27
相关资源
最近更新 更多