TypeScript 在 Cypress 測試中的所有內容#frontend@twiliosendgrid

已發表: 2020-11-14

在 Twilio SendGrid,我們現在使用 TypeScript 和 React 編寫大部分前端 Web 應用程序,尤其是新頁面和新功能,以實現更好的類型檢查、可維護性和代碼庫文檔。 兩年前我們第一次開始編寫 Cypress 測試時,我們的大多數頁面對象、幫助程序和規範文件仍然用 JavaScript 實現,而且我們主要使用 Cypress 版本 3.xx 更多最近的測試已經用 TypeScript 編寫,但我們仍然有大量文件要轉換和遷移到 TypeScript。

我們希望從完全輸入我們的組件、單元測試和賽普拉斯 E2E 測試中獲益 自 Cypress 4.4.0 起,遷移到較新版本的 Cypress 以利用 TypeScript 的開箱即用支持使該過程變得更容易

如果您想退後一步,更一般地了解如何考慮編寫 E2E 測試,請隨時查看此博客文章。 如果您還想查看我們在不同環境中編寫賽普拉斯測試時使用或完成的最常見事情的一千英尺概覽,您可以在開始將 TypeScript 添加到賽普拉斯測試之前參考這篇博文。 這篇博文假設您熟悉 Cypress 測試並且之前使用過他們的 API。

如果您準備好了解我們是如何輸入內容的,那麼讓我們先看看一些初始更改,例如如果您來自舊版本,則向 Cypress 添加 TypeScript 支持。

從 Cypress 3.x 遷移到 >= 4.4.0

對於那些已經在 Cypress 版本 3.xx 到 4.4.3 中配置了 Cypress 基礎設施以使用 TypeScript 的人,您很可能在plugins/index.js中設置正確的 Webpack 預處理器配置時經歷了一些試驗和錯誤。 對於 Twilio SendGrid 團隊來說,存在一些問題,其中某些文件需要是pluginssupport文件夾中的 JavaScript 文件,並且難以調試的 Cypress 錯誤會浮出水面。 一旦你得到一些工作,它應該看起來像這樣。


從早期版本的 3.xx 升級後,我們能夠刪除 Webpack 預處理器配置,用index.ts文件替換我們的plugins/index.js文件,稍微修改一下 Cypress 文件夾的tsconfig.json ,最後,使用 Cypress 文件夾中的 TS 文件(如some_page.spec.tsindex.d.tspage_object.ts )——不再需要 Webpack 預處理器配置,它就可以工作了! 我們很高興不用管理您自己的 Webpack 預處理器配置並且對我們的文件有更好的 TypeScript 覆蓋率,它變得更加簡潔和好,如下所示。

在涵蓋了 TypeScript 支持之後,我們查看了 Cypress 團隊的示例真實世界應用程序 cypress-real-world-app 存儲庫,以了解更多關於如何更好地鍵入內容的信息。 我們發現瞭如何在更新文件時鍵入cy.task(“pluginName”, { … })Cypress.env(“someEnvVar”)函數調用以更好地鏈接和鍵入智能感知支持。 我們還翻閱了他們隨附的 TypeScript 文檔。 這教會了我們如何鍵入諸如cy.login()自定義命令之類的內容,以及如何設置tsconfig.json配置文件。 示例應用程序還有一個tsconfig.json供您參考,它可以為您提供一個很好的基礎 TypeScript 配置,供您根據自己的喜好進行自定義。 我們建議您及時了解最新的賽普拉斯版本,深入了解賽普拉斯官方資源,並嘗試使用您的類型定義文件。

鍵入自定義命令

我們創建了一些全局自定義命令,例如cy.login()來通過 API 處理登錄,因此它可以在我們所有的規範文件中重用。 這是一個示例,說明如何在給定用戶憑據的情況下鍵入自己的登錄自定義命令並返回身份驗證令牌。

鍵入環境變量

為了處理多個測試環境,例如 dev 和 staging,我們利用了配置環境變量的優勢,例如:“testEnv”來保存我們當前正在測試的環境,例如 staging,“apiHost”來保存後端 API 主機,以及其他變量。 您可以輸入Cypress.env()調用,以更好地輸入依賴於使用這些環境變量值的函數和其他對象,例如。

打字插件

我們創建了許多cy.task()插件函數來處理 API 調用、輪詢服務以及檢查測試電子郵件收件箱中的匹配電子郵件。 以前,當鏈接任何這些函數調用(如cy.task().then((data) => {})時,鏈接的數據主體將被鍵入為anyunknown ,這對我們的 TypeScript 文件來說不是很好。 我們通過 Cypress 示例發現瞭如何根據插件名稱和函數調用中傳遞的參數更好地鍵入插件。 這允許我們的 TypeScript 文件檢測鏈接的數據類型是什麼。

我們遇到的一個微妙問題是插件名稱和參數必須與您輸入的方式完全匹配。我們發現在編輯器中將鼠標懸停在鏈接的 .then( .then()類型和cy.task()參數對像上以加倍很重要檢查類型是否正確匹配。 有時,如果您使用來自另一個賽普拉斯函數的鏈接主題,例如cy.getCookie(“auth_token”).its(“value”).then((token) => { })cy.wrap(data).then((data) => {}) ,在將其作為cy.task(..., { token, data })函數參數傳遞之前,您還需要鍵入這些鏈接的數據參數,否則您仍然會看到cy.task(...).then((data) => { })數據部分類型為anyunknown 。 最好在許多鍊式 Cypress 函數類型中更加明確,例如.its(“value”).then((token: string) => {})cy.wrap(data).then((data: DataType) => {})在將它們作為cy.task()參數對象的一部分傳遞之前,以確保類型再次正常工作。

我們創建了單獨的插件 Typescript 文件,這些文件將導出函數以在我們的plugins/index.ts中使用。 隨著插件數量的增加,我們建議您按頁面或功能組織這些插件功能實現,以保持您的plugins/index.ts文件較小。 在plugins/index.ts文件中定義所有cy.task(...)函數時,您應該一目了然。 您最終可以通過以下方式在index.d.ts中輸入這些任務功能:

將它們放在一個類型聲明文件中

我們將自定義命令、環境變量和插件的所有類型放在support文件夾中的index.d.ts文件中。 我們建議您將所有 Cypress 類型也放在一個主要的 TypeScript 定義文件中,以使事情井井有條。 為了繞過 Cypress 測試代碼中使用的外部依賴項中缺少的類型,您還可以定義諸如“some-lib.d.ts”之類的模塊文件,其中包括declare module 'some-lib' ,以解決庫的 TypeScript 警告。 您甚至可以使用 TypeScript 的導入類型功能來引入在其他插件/實用程序文件中定義的類型/接口,以避免在多個文件中重複您的類型定義。 您可以在賽普拉斯命名空間中添加這些類型,並按以下方式組織它們:

鍵入測試夾具對象、頁面對象和規範文件

當我們想為測試環境加載不同的用戶和元數據時,我們之前說明瞭如何將諸如“testEnv”之類的環境變量與“testing”或“staging”的值結合起來,以提取“testing”或“暫存”來自整個測試夾具對象的對象。 您可以使用泛型鍵入這些測試夾具環境對象,以獲得所有規範共享的一致結構。 對於每個測試環境,您可以使用通用類型為測試添加相同的用戶憑據和元字段,以便根據需要添加任意數量的屬性。 請參見下面的示例。

輸入頁面對象和輸入相應的規範文件取決於您使用的賽普拉斯命令、插件和其他實用程序。 在大多數情況下,輸入頁面對像或規範文件不需要對其 JavaScript 對應項進行太多更改(假設您已經輸入了插件和環境變量調用)。 有時,您定義的頁面對象輔助函數可能需要輸入一些參數,或者可能需要輸入從cy.request()調用返回的響應as response.body as SomeType 。 總體而言,您的編輯器(例如 VSCode)可以自動檢測cy.task()cy.customCommand()調用的鏈接類型,而無需在規範文件中添加更多類型來補償任何 TypeScript 警告。

這是一個頁面對象的部分示例,其中包含一些幫助函數和一個使用頁面對象、登錄自定義命令和插件任務的規範文件。

結論

在 Cypress 測試中添加 TypeScript 有助於我們避免錯誤並改善我們在編寫 Cypress 測試時的開發人員體驗。 使用cy.task()Cypress.env()cy.customCommand()函數調用時,我們可以更好地對函數參數和輸出進行類型檢查,並利用我們的 IDE(例如 VSCode)中的代碼完成。

關鍵是創建您自己的類型聲明文件,例如index.d.ts文件,您可以在其中根據您的自定義命令、環境變量和任務插件函數覆蓋或擴展“Cypress”和“Chainable”接口使用。 在您的頁面對象和規範 TypeScript 文件中,您可以利用這些 Cypress 函數並將鼠標懸停在或遵循預期輸入和輸出類型的定義。

此外,請嘗試將 TypeScript 與 Cypress 一起使用,因為它在最新版本中對 TypeScript 提供了開箱即用的支持。 測試它是否可以幫助您更清楚地記錄功能並避免錯誤的 API 使用。 您的 TypeScript 測試可能仍然與您的 JavaScript Cypress 測試相似,因此您可以一次穩定地轉換一些測試以比較和對比這些方法。

如果您對更多與我們從賽普拉斯測試中學到的知識相關的帖子感興趣,請查看以下文章:

  • 編寫 E2E 測試時要考慮什麼
  • 編寫柏樹測試的 1,000 英尺概述
  • 在 Cypress 測試中處理電子郵件流
  • 配置、組織和整合賽普拉斯測試的想法
  • 將 Cypress 測試與 Docker、Buildkite 和 CICD 集成