javascript - 有人可以解释在使用 QUnit 进行单元测试时使用 qunit-fixture 吗?

标签 javascript unit-testing qunit

我刚刚开始使用 QUnit 进行 ui 测试,所以我确定我缺少 qunit-fixture 的一些基本用例。我认为它对测试 DOM 操作很有用,但后来我意识到我的 DOM 操作函数都不知道任何关于 qunit-fixture 的信息(他们也不应该?)。

例子:

<div id="container">
    <form id="my-form">
        <input type="hidden" name="field1" id="field1">
        <input type="hidden" name="field2" id="field2">
    </form>
</div>
<div id="qunit-fixture"></div>

我将 URL 参数传递给函数以填充此表单。如果这些参数不存在,我希望删除该字段,以便 JQuery.serialize() 不会捆绑空字段。

function populate(params){
    if( params.field1 ){
        $("#field1").val(params.field1);
    } else {
        $("#field1").remove();
    }
    if( params.field2 ){
        $("#field2").val(params.field2);
    } else {
        $("#field2").remove();
    }
}

我最初的想法是“哦,太棒了。我可以使用 qunit-fixture 来重复模拟我的表单!”像这样:

QUnit.test("populate - field1=text", function(assert){
    $("#qunit-fixture").html($("#container").html());
    populate( {field1: "text"} );

    assert.deepEqual($("#field1").val(), "text");
    assert.deepEqual($("#field2").val(), undefined);
});

QUnit.test("populate - field1="text", function(assert){
    $("#qunit-fixture").html($("#container").html());
    populate( {field1: "text", field2: "text"} );

    assert.deepEqual($("#field1").val(), "text");
    assert.deepEqual($("#field2").val(), "text");
});

这当然会失败,因为第一个测试对 populate() 的调用改变了 DOM 并从页面的主表单中删除了 #field2 以及原来的副本放入 qunit-fixture(非唯一 ID.. 哎呀)。

那我错过了什么?我真的很喜欢使用 QUnit 测试逻辑模块的能力,并且终于开始看到更多测试驱动开发风格的优点。我也希望能够测试我的 DOM 操作。

注意:这是一个简化的示例。我项目中的实际 DOM 操作要复杂得多,因此希望对其进行测试。

最佳答案

qunit-fixture 元素是一些 HTML 的容器,您的测试可以针对这些 HTML 进行断言。每次测试后,QUnit 都会将其重置为测试开始前的状态,以便下一次测试可以运行,而不必担心之前的测试添加或删除了什么。

当然,如果您的测试开始对 qunit-fixture 之外的元素进行修改,那么您将开始看到影响其他测试的测试,因此请尽量不要这样做。

在您的例子中,您正在创建一个空的 qunit-fixture div 并从另一个 div 复制内容。更好的方法是使用 qunit-fixture 元素来包含您要测试的 HTML,例如:

<div id="qunit-fixture">
    <div id="container">
        <form id="my-form">
            <input type="hidden" name="field1" id="field1">
            <input type="hidden" name="field2" id="field2">
        </form>
    </div>
</div>

(我不知道你是否需要容器div。我在上面的例子中保留了它,但如果不需要,请随意去掉它。)

因为您不再需要将 HTML 从容器 div 复制到 qunit-fixture div,您可以从测试中删除这些行:

    $("#qunit-fixture").html($("#container").html());

您也不再遇到重复 ID 的问题,并且由于 QUnit 会在每次测试后重置 qunit-fixture,因此您不应该遇到一个测试影响另一个测试的问题。

QUnit 的目的是让您从专门为测试目的而创建的页面运行它。此页面应如下所示:

<html>
<head>
  <!-- load various JS and CSS files -->
</head>
<body>
  <div id="qunit"></div>
  <div id="qunit-fixture">
    <!-- sample markup for testing against -->
  </div>
</body>

由于 qunit-fixture 之外没有任何标记,除了 QUnit 将用于测试结果的 qunit div 之外,没有“页面部分 qunit-fixture”,如您在评论中所写,也没有任何重复的 ID。

关于javascript - 有人可以解释在使用 QUnit 进行单元测试时使用 qunit-fixture 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33681172/

相关文章:

javascript - 如何使用 Dart 在 Angular 2 中创建动态组件?

c# - JavaScript 代码可以使网络浏览器上的文本闪烁一次

javascript - 使用 Mocha/Chai 测试异步函数时,无法满足期望总是会导致超时

javascript - QUnit with Ajax,QUnit 通过了失败的测试

JavaScript 待办事项列表 - 删除按钮仅出现在最近添加的元素上

javascript - 我来自 Node 的数据没有绑定(bind)到模板变量

java - Junit - AssertArrayEquals 不适用于用户定义的对象(非原始数据类型)

java - 如何为 BigDecimal 编写 Junit 测试用例

phantomjs - QUnit + PhantomJS : asyncTest never returns

javascript - 我应该如何衡量 JS 的单元测试覆盖率?我不能满足于 jscoverage