升級到 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 偵測相容性問題

Jasmine 3.99 對大多數使用在 4.0 中已移除或以不相容方式變更的 API 的程式碼,發布不建議使用的警告。我們建議升級到 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-browser-runner NPM 套件,它是 jasmine Ruby gem 和 Python 套件的直接替換品。它可以在瀏覽器(包含無頭瀏覽器 Chrome 和 Saucelabs)中執行您的規格。它支援 Rails 應用程式,包括使用 Webpacker 的 Rails 應用程式,而這項功能從未受到 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 會略過整個區套,但會執行與失敗的 beforeAll 定義在同一個區套中的任何 afterAll 函數。類似地,除了預測失敗以外的 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 事件中回報錯誤。未顯示這些錯誤在自訂回報器中是一項常見的臭蟲。你可以透過於頂層 (也就是非 describe) 建立 afterAll 函式來檢查你的程式碼,它會引發例外狀況並確保你的回報器會顯示它。

解決特定不建議使用警告的秘訣

比對器中與自訂等號測試器相關的不建議事項

於 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,而一個靜態的 pretty 列印程式可用於 jasmine.pp。由於這兩個目前都附帶特定於當前規格的設定,因此不再需要靜態實例。請勿使用 jasmine.matchersUtil,請透過下列方式之一存取目前的 MatchersUtil

請勿使用 jasmine.pp,請透過上述任一種方式存取 matchersUtil,然後使用它的 pp 方法

另請注意,如果一個物件有 jasmineToString 方法,pp 會被傳遞為第一個參數。

提供給函式庫作者的注意事項

matchersUtil 在 2.0 以後的版本傳遞給比對器工具工廠,在 2.6 以後的版本傳遞給非對稱相等性測試器。 matchersUtil#pp 在 3.6 引入,這也是第一個將 pretty 列印程式傳遞給 jasmineToString 的版本。如果您需要以與 3.6 之前的 Jasmine 版本相容的方式進行 pretty 列印,您可以檢查 MatchersUtil 實例或傳遞給 jasmineToString 的參數是否具有 pp 方法,然後在它不存在時退回到 jasmine.pp

混合使用兩種非同步形式的不建議使用通知

Jasmine 從未支援過將多種非同步樣式合併的函式,它們也從來沒有過一致或明確的行為定義。只要在執行期間發現那樣的函式,Jasmine 4.0 便會發布規格失敗訊息。常見問答說明了解為何會做此變更,以及如何更新你的規格

多次呼叫 done 導致的廢棄項目

Jasmine 先前容許多次呼叫 done,但它掩蓋的錯誤已證明是常見的混淆來源。Jasmine 4 將在非同步函式呼叫 done 超過一次時回報錯誤。常見問答說明了解為何會做此變更,以及如何更新你的規格

因重新呼叫 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();
});