QUnit 2.0 升级指南

本指南将帮助您从 QUnit 1 升级到 QUnit 2。

概述

QUnit 2 版本只删除了旧方法。 “QUnit 2” 方法是在 QUnit 1.x 版本中引入的。如果您使用的是 QUnit 1.23,您可以在升级之前逐步迁移。

旧方法在 QUnit 2.0 中被删除,并被替换为抛出描述性错误的占位符方法,以简化迁移("Global 'test()' method is removed, use 'QUnit.test() instead")。QUnit 2.1 删除了这一层,而是会抛出像 "ReferenceError: test is not defined" 这样的原生错误。

QUnit 1.x QUnit 2.x
module() QUnit.module()
test() QUnit.test()
asyncTest() QUnit.test() with assert.async()
stop()/start() assert.async()
expect() assert.expect()
ok(), equal(), deepEqual(), … assert
setup/teardown options beforeEach and afterEach hooks

对于插件和其他集成

QUnit 1.x QUnit 2.x
QUnit.log = …
QUnit.begin = …
QUnit.log(…),
QUnit.begin(…),
QUnit.push() assert.pushResult()
QUnit.jsDump.parse() QUnit.dump.parse()

更改

The qunit-migrate tool can automate the transition to QUnit 2.

删除全局函数

QUnit 2 不再使用全局函数。主要方法现在是 QUnit 接口的一部分,断言方法通过绑定到每个测试的新 assert 对象公开。

之前

module('example');

test('add', function () {
  equal(add(2, 3), 5);
});

之后

QUnit.module('example');

QUnit.test('add', assert => {
  assert.equal(add(2, 3), 5);
});

引入 assert.async()

使用 assert.async() 而不是 stop()start() 函数。调用 assert.async() 返回一个 done 函数,该函数应在异步操作完成后调用。

类似地,如果您使用的是 asyncTest(),请使用带有 assert.async() 的常规 QUnit.test()

之前

QUnit.test('navigates to new page', function () {
  stop();
  router.navigate(function (newPage) {
    equal(newPage.id, 1);
    start();
  });
});

// Or

asyncTest('navigates to new page', function () {
  router.navigate(function (newPage) {
    equal(newPage.id, 1);
    start();
  });
});

之后

QUnit.test('navigates to new page', assert => {
  const done = assert.async();
  router.navigate(newPage => {
    assert.equal(newPage.id, 1);
    done();
  });
});

重命名模块钩子

模块钩子 setupteardown 已重命名为 beforeEachafterEach。新名称首次出现在 QUnit 1.16 中,并在 QUnit 2.0 中删除。

之前

QUnit.module('router', {
  setup: function () {
    this.router = new Router();
  },
  teardown: function () {
    this.router.destroy();
  }
});

之后

QUnit.module('router', {
  beforeEach: () => {
    this.router = new Router();
  },
  afterEach: () => {
    this.router.destroy();
  }
});

从 QUnit 1.20 开始,您还可以使用 嵌套范围,这使得更轻松地共享变量并将测试与模块关联起来。

示例

QUnit.module('router', hooks => {
  let router;

  hooks.beforeEach(() => {
    router = new Router();
  });
  hooks.afterEach(() => {
    router.destroy();
  });

  QUnit.test('add', assert => {
    assert.true(router.add('/about'));
  });
});

删除旧的回调属性

QUnit 0.x 的早期 alpha 版本需要属性赋值来注册回调事件。在 QUnit 1.0 中,这些被弃用,转而使用更现代的事件注册方法。在 QUnit 2.0 中,使用赋值作为注册回调的方式被删除。

另请参阅 QUnit.on(),它从 QUnit 2.2 开始实现 js-reporters 规范

之前

QUnit.log = function (results) {
  console.log(results);
};

之后

QUnit.log(function (results) {
  console.log(results);
});

这适用于所有报告回调,特别是:begindonelogmoduleDonemoduleStarttestDonetestStart

QUnit.push() 替换为 assert.pushResult()

要实现自定义断言,请将函数分配给 QUnit.assert,并在内部使用 this.pushResult() 而不是 QUnit.push。这允许断言直接与其测试上下文相关联,防止异步测试泄漏到其他测试中。

之前

QUnit.assert.mod2 = function (value, expected, message) {
  const actual = value % 2;
  QUnit.push(actual === expected, actual, expected, message);
};

之后

QUnit.assert.mod2 = function (value, expected, message) {
  const actual = value % 2;
  this.pushResult({ result: actual === expected, actual, expected, message });
};

删除 QUnit.init,没有替换

此方法用于重新初始化测试运行器。它不应该公开为公共方法,现在已移除,没有替代方案。如果您构建了需要使用 QUnit.init 的集成或运行器框架,请在我们的 聊天室 中联系我们,或在 问题跟踪器 中联系我们,以帮助找到替代方案。

删除 QUnit.reset

此方法访问了 QUnit 的内部夹具重置。现在已移除,没有替代方案。如果您的代码正在使用它,您可能需要将受影响的测试拆分为单独的测试。

之前

QUnit.test('currentPage', assert => {
  router.refresh();
  assert.equal(router.currentPage.id, 1);

  QUnit.reset();

  history.replaceState('/about');
  router.refresh();
  assert.equal(router.currentPage.id, 42);
});

之后

QUnit.test('currentPage default', assert => {
  router.refresh();
  assert.equal(router.currentPage.id, 1);
});

QUnit.test('currentPage after replaceState', assert => {
  history.replaceState('/about');
  router.refresh();
  assert.equal(router.currentPage.id, 42);
});

QUnit.jsDump 重命名为 QUnit.dump

最初 jsDump 是一个独立的库,导入到 QUnit 中。它后来在库中进一步发展。为了反映这一点,该属性已重命名为 QUnit.dump.parse。这只会影响自定义报告程序代码,不会影响常规测试套件。

之前

QUnit.log(obj => {
  const actual = QUnit.jsDump.parse(obj.actual);
  const expected = QUnit.jsDump.parse(obj.expected);
  sendMessage(obj.result, actual, expected);
});

之后

QUnit.log(obj => {
  const actual = QUnit.dump.parse(obj.actual);
  const expected = QUnit.dump.parse(obj.expected);
  sendMessage(obj.result, actual, expected);
});

QUnit.testexpected 数字参数替换掉

用于指定预期断言数量的 QUnit.test 的可选 expected 参数已移除。请改用 assert.expect()

之前

QUnit.test('addition', 1, assert => {
  assert.equal(add(2, 3), 5);
});

之后

QUnit.test('addition', assert => {
  assert.expect(1);
  assert.equal(add(2, 3), 5);
});

替换 assert.throws(Function, string, message) 签名

接受错误字符串作为第二个参数的 assert.throws() 的签名已移除。这避免了与断言消息的歧义,因为两个参数都是可选的。

建议使用正则表达式或错误对象作为预期值。

例如,要测试以下代码

function add (a, b) {
  if (a === undefined) {
    throw new Error('This is an error');
  }
}

之前

QUnit.test('add', assert => {
  assert.throws(() => {
    add();
  }, 'This is an error', 'Fail if A is undefined');
});

之后

QUnit.test('add', assert => {
  assert.throws(() => {
    add();
  }, /This is an error/, 'Fail if A is undefined');
});

// Or

QUnit.test('add', assert => {
  assert.throws(() => {
    add();
  }, new Error('This is an error'), 'Fail if A is undefined');
});

有关支持签名的概述,请参阅 assert.throws()

请注意,在两个参数签名 assert.throws(Function, string) 中,始终被解释为断言任何内容被抛出,字符串参数是断言消息。这将继续得到支持。