升级至 Jasmine 4.0

概述

重点说明:更新至 3.99 并修复所有弃用警告,然后才能更新至 4.0。

我们认为,大多数用户都可以轻松升级至 Jasmine 4.0。但是,其包含一些重大更改,因此部分用户需要更改其代码才能升级。按照本指南中的步骤操作,能够最大程度顺畅地升级。

Jasmine 4.0 中的重大更改包括更改 Jasmine 配置的方式、自定义匹配器和不对称相等性测试器、更好地检测常见错误,以及更改系统要求。您可以在 jasmine-corejasmine 的发行说明中找到重大更改的完整列表。

内容

  1. 系统要求
  2. 使用 Jasmine 3.99 来检测兼容性问题
  3. 针对 Ruby 和 Python 用户的迁移路径
  4. jasmine 包公开接口
  5. ES 模块支持
  6. 退出代码更改
  7. 更改处理 beforeAll 和 beforeEach 失败的方式
  8. 报告器界面更改
  9. 解决特定弃用警告的提示

系统要求

不再支持以下以前受支持的环境

尽管 Jasmine 4.0 可能仍然可以在某些环境中运行,但我们不再针对这些环境进行测试,并且不会尝试在未来的 4.x 版本中保持与这些环境的兼容性。奇数版本的 Node(13.x、15.x、17.x)不受支持,可能无法运行。特别是,某些 13.x 版本对 ES/CommonJS 模块互操作的支持不完整,无法运行 Jasmine 4.0。

使用 Jasmine 3.99 来检测兼容性问题

对于大多数使用已在 4.0 中以不兼容方式移除或更改的 API 的代码,Jasmine 3.99 会发出弃用警告。我们建议先升级至 3.99,修复所有弃用警告,再升级至 4.0。您应该像往常一样,直接升级所依赖的 Jasmine 包。如果您将 jasmine NPM 包、jasmine Rubygem 或 jasmine Python 包升级至 3.99,您将同时获得版本 3.99 的 jasmine-core。

如果您正在使用 jasmine-browser-runner,只需将 jasmine-core 3.99 添加至您的依赖项即可。

针对 Ruby 和 Python 用户的迁移路径

3.99 是 Ruby 和 Python 中 Jasmine 的最终版本。我们建议大多数用户迁移到 jasmine-browser-runner NPM 包,它是 jasmine Ruby gem 和 Python 包的直接替代品。它在浏览器中运行您的规范,包括无头 Chrome 和 Saucelabs。它适用于 Rails 应用程序,包括那些使用 Webpacker 的应用程序,后者从未得到 jasmine gem 的支持。

如果 jasmine-browser-runner 无法满足您的需要,以下内容之一可能满足

jasmine 包公开接口

jasmine-core 包不同的是,jasmine 包在版本 3.8 之前没有公开的已记录接口。从 4.0 开始,任何不属于已记录公共接口一部分的内容都将被视为私有 API,并且可能随时更改。如果您以编程方式使用 jasmine 包(即,您有执行 require('jasmine') 或 import('jasmine') 的代码),请使用 API 文档 检查您的代码。

ES 模块支持

从版本 4 开始,jasmine 包默认使用动态 import() 加载规范和其他文件。这允许在没有任何配置的情况下使用带有 .js 扩展名的 ES 模块。版本 4.0.1 修复了加载具有 .jsx.coffee 等非标准扩展名的文件的问题,因此如果您有此类文件,请务必至少安装该版本。

退出代码更改

在版本 4 之前,jasmine 命令几乎在所有非完全成功的情况下都以状态 1 退出。版本 4 为不同类型的故障使用不同的退出代码。除非您的构建或 CI 系统专门检查退出代码 1(这是非常罕见的),否则您无需更改任何内容。任何将 0 视为成功并将其他任何内容视为失败内容都仍然可以正常工作。

更改了 beforeAllbeforeEach 故障的处理方式

Jasmine 4 以不同的方式处理 beforeAllbeforeEach 故障。该更改可能会导致某些不寻常的设置和终止模式出现问题。只要您在设置资源的同一套件中终止资源,您就不需要进行任何更改。

beforeAll 函数并非因预期的失败而失败时,Jasmine 4 将跳过除 any afterAll 函数(定义在 beforeAll 函数所在的相同套件中)之外的整个套件。同理,当 beforeEach 失败时,也并非因预期的失败而失败,会导致任何随后出现的 beforeEach 函数、待处理的说明和任何 afterEach(定义在嵌套套件中)函数被跳过。

// Unsafe. Test pollution can result because the afterEach won't always run.
describe('Outer suite', function() {
  beforeEach(function() {
    setSomeGlobalState();
    possiblyFail();
  });

  describe('inner suite', function() {
    it('does something', function() { /*...*/ });

    // This afterEach function should be moved up to the outer suite.
    afterEach(function() {
      cleanUpTheGlobalState();
    });
  });
});

报告器界面更改

Jasmine 4.0 为 传递给报告程序的 specDone 方法的对象 添加了 debugLogs 字段。如果说明调用了 jasmine.debugLog,并且还失败了,此字段将被定义。大部分报告程序在字段存在时会显示它。

Jasmine 4.0 比前一个版本更有可能在 jasmineDone 事件中报告错误。不显示这些错误是自定义报告程序中常见的错误。您可以通过在顶层创建一个 afterAll 函数(即不在 describe 中)来检查您自己,该函数引发异常,并确保您的报告程序显示它。

解决特定弃用警告的提示

与比较器中的自定义相等检验程序相关的弃用

在 3.6 之前,想要支持 自定义相等检验程序自定义比较器 必须接受自定义相等检验程序数组作为比较器工厂的第二个参数,并将其传递给类似于 MatchersUtil#equalsMatchersUtil#contains 的方法。自 3.6 以来,传递给比较器工厂的 MatchersUtil 实例已预先配置为当前的自定义相等检验程序集,并且比较器无需提供它们。自 Jasmine 4.0 起,自定义相等检验程序既不传递至比较器工厂,也不接受为 MatchersUtil 方法的参数。要将您的自定义比较器更新为新样式,只需从比较器工厂移除额外的参数,并停止将其传递至 MatchersUtil 方法即可。

之前

jasmine.addMatchers({
  toContain42: function(matchersUtil, customEqualityTesters) {
    return {
      compare: function(actual, expected) {
        return {
          pass: matchersUtil.contains(actual, 42, customEqualityTesters)
        };
      }
    };
  }
});

之后

jasmine.addMatchers({
  toContain42: function(matchersUtil) {
    return {
      compare: function(actual, expected) {
        return {
          pass: matchersUtil.contains(actual, 42)
        };
      }
    };
  }
});

致函库作者

上面更新的形式仅与 Jasmine 3.6 及更高版本兼容。如果您想保持与旧版 Jasmine 的兼容性,您可以通过声明匹配器工厂来接受单个参数并随后使用 arguments 对象或 rest 参数语法 访问自定义相等性测试人员的数组来避免弃用警告。然后在传递它之前检查数组上的 deprecated 属性,该属性将在 Jasmine 3.6 及更高版本中存在

jasmine.addMatchers({
  toContain42: function(matchersUtil, ...extraArgs) {
    const customEqualityTesters = 
      extraArgs[0] && !extraArgs[0].deprecated ? extraArgs[0] : undefined;
    
    return {
      compare: function(actual, expected) {
        return {
          pass: matchersUtil.contains(actual, 42, customEqualityTesters)
        };
      }
    };
  }
});

"asymmetricMatch 的第二个参数现在是 MatchersUtil。将其用作自定义相等性测试人员的数组已被弃用,并且在将来的版本中将停止工作。"

在 3.6 之前,希望支持 自定义相等性测试人员自定义非对称相等性测试人员 必须接受自定义相等性测试人员的数组作为 asymmetricMatch 的第二个参数并将其传递给 MatchersUtil#equalsMatchersUtil#contains 这样的方法。从 3.6 到 3.99,第二个参数既是自定义相等性测试人员的数组,又是一个预先配置了它们的 MatchersUtil 实例。在 4.0 及更高版本中,它只是一个正确配置的 MatchersUtil。要解决弃用警告,请直接使用提供的 MatchersUtil

之前

function somethingContaining42() {
  return {
    asymmetricMatch: function(other, customEqualityTesters) {
      return jasmine.matchersUtil.contains(other, 42, customEqualityTesters);
    }
  };
}

之后

function somethingContaining42() {
  return {
    asymmetricMatch: function(other, matchersUtil) {
      return matchersUtil.contains(other, 42);
    }
  };
}

致函库作者

上面更新的形式仅与 Jasmine 3.6 及更高版本兼容。如果您想保持与旧版 Jasmine 的兼容性,您可以通过检查第二个参数是否为 MatchersUtil(例如,通过检查 equals 方法)并在其不是 MatchersUtil 时退回到上述旧形式来避免弃用警告。

与不再全局可用的匹配器实用程序相关的弃用

在 Jasmine 4.0 之前,有一个静态 MatchersUtil 实例可用作 jasmine.matchersUtil,并且有一个静态漂亮打印机可用作 jasmine.pp。因为这两个现在都承载了特定于当前规范的配置,所以不再有静态实例是有道理的。代替使用 jasmine.matchersUtil,可以通过以下方式之一访问当前 MatchersUtil

不要使用 class="language-plaintext highlighter-rouge">jasmine.pp,而是以上任意一种方式访问 class="language-plaintext highlighter-rouge">matchersUtil,然后使用其 pp 方法

另外,如果对象具有 class="language-plaintext highlighter-rouge">jasmineToString 方法,则会将 class="language-plaintext highlighter-rouge">pp 作为第一个参数传递。

致函库作者

自 2.0 以后的所有版本都给匹配器工厂提供了 class="language-plaintext highlighter-rouge">matchersUtil,自 2.6 以后的所有版本都给非对称相等测试程序提供了 class="language-plaintext highlighter-rouge">matchersUtilclass="language-plaintext highlighter-rouge">matchersUtil#pp 是在 3.6 中引入的,这也是向 class="language-plaintext highlighter-rouge">jasmineToString 传递漂亮打印程序的第一个版本。如果您需要以与低于 3.6 版本的 Jasmine 兼容的方式实现漂亮打印,那么可以在 class="language-plaintext highlighter-rouge">matchersUtil 实例或传递给 class="language-plaintext highlighter-rouge">jasmineToString 的参数上检查是否存在 class="language-plaintext highlighter-rouge">pp 方法,如果不存在,则回退到 class="language-plaintext highlighter-rouge">jasmine.pp

与混合使用两种形式的异步相关的弃用

Jasmine 从不支持将多种形式的异步相结合的函数,并且它们的行为从未一致或明确。如果检测到此类函数,Jasmine 4.0 将发出规范失败。 常见问题解答对此更改的原因以及如何更新规范进行了讨论

由于多次调用 class="language-plaintext highlighter-rouge">done 而导致的弃用

Jasmine 在历史上可以接受多个 done 调用,但这样做所掩盖的错误被证明是造成混淆的常见来源。每当异步函数调用 done 多次时,Jasmine 4 都会报告错误。常见问题讨论了进行此更改的原因以及如何更新规范

不再推荐使用 jasmine.clock().tick() 重入调用

在 4.0 之前,在 setTimeoutsetInterval 处理程序中调用 jasmine.clock().tick() 可能导致由 Date 公开的当前时间向后推移。从 4.0 开始,即使在对 tick() 进行重入调用时,当前时间也不会减少。这可能会影响规范的行为,这些规范从计时器处理程序内部调用 tick(),也关心当前时间。

如果受影响的规范不关心当前时间,或者您计划在升级到 4.0 后检查它们,则可以忽略此警告。但是,我们建议修改受影响的规范,使其不从计时器处理程序内部调用 tick()

之前

it('makes a reentrant call to tick()', function() {
  const foo = jasmine.createSpy('foo');
  const bar = jasmine.createSpy('bar');

  setTimeout(function() {
    foo();
    jasmine.clock().tick(9);
  }, 1);

  setTimeout(function() {
    bar();
  }, 10);

  jasmine.clock().tick(1);
  expect(foo).toHaveBeenCalled();
  expect(bar).toHaveBeenCalled();
});

之后

it('does not make a reentrant call to tick()', function() {
  const foo = jasmine.createSpy('foo');
  const bar = jasmine.createSpy('bar');

  setTimeout(function() {
    foo();
  }, 1);

  setTimeout(function() {
    bar();
  }, 10);

  jasmine.clock().tick(1);
  expect(foo).toHaveBeenCalled();
  jasmine.clock().tick(9);
  expect(bar).toHaveBeenCalled();
});