搜尋
首頁web前端js教程讓 Jest 運行得更快

Let’s Make Jest Run Much Faster

但首先,我們要了解為什麼它這麼慢。

實際例子

考慮一個簡單的 React 元件。

import React from "react";
import { deepClone } from "./utils";

export function App() {
  const obj = { foo: 'bar' };

  return (
    <div>
      <p>Object looks like this: {JSON.stringify(deepClone(obj))}</p>
    </div>
  );
}

應用程式元件僅依賴一個實用函數 - deepClone。 utils 檔案如下所示。

import _ from 'lodash';
import moment from 'moment';
import * as mui from '@mui/material';

export const deepClone = (obj) => _.cloneDeep(obj);
export const getFormattedDate = (date) => moment(date).format('YYYY-MM-DD');

export const isButton = (instance) => instance === mui.Button;

它會導出三個單行輔助函數。就是這樣。
現在,有一個大問題:您認為執行此測試需要多長時間?

import React from "react";
import { render, screen } from "@testing-library/react";
import { App } from "./app";
import "@testing-library/jest-dom";

test("renders the app", () => {
  render(<app></app>);
});

答案是?永恆!

 PASS  src/tests/react-app/react-app.test.js
  √ renders the date and sum correctly (25 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        5.045 s

在我的機器上花了 5 秒鐘來為單行 React 元件執行單行測試案例。

分析績效

要分析幕後發生的事情,我們可以使用 Chrome 的分析器 - 我建議觀看 Kent C. Dodds 的這段富有洞察力的影片。
或者,您可以使用 jest-neat-runner 函式庫,它可以簡化分析流程。將 NEAT_REPORT_MODULE_LOAD_ABOVE_MS 選項設為 150 並啟用 NEAT_REPORT_TRANSFORM。此配置將列印出載入時間超過 150 毫秒的模組,並提供有關處理(開啟和轉譯)檔案所需時間的資訊。

我們使用後者。這是輸出。

> jest src/tests/react-app/

From src\tests\react-app\utils.js -> @mui/material in 1759ms
From node_modules\@mui\material\node\styles\adaptV4Theme.js -> @mui/system in 509ms
From src\tests\react-app\react-app.test.js -> @testing-library/react in 317ms
From node_modules\@testing-library\react\dist\pure.js -> @testing-library/dom in 266ms
From node_modules\@mui\system\ThemeProvider\ThemeProvider.js -> @mui/private-theming in 166ms
From node_modules\@testing-library\dom\dist\role-helpers.js -> aria-query in 161ms

我們載入「@mui/material」函式庫花了近 2 秒,甚至沒有使用它!

許多項目的根本原因是什麼?

凌亂的依賴關係

根據我的經驗,jest 的效能問題主要源自於大量甚至在運行時都沒有使用的傳遞依賴項。正如上面的範例所示,如果您沒有足夠注意導入到應用程式中的文件,您最終可能會遇到與我相同的情況。

就我而言,App 元件只依賴 deepClone 實用函數。但是,由於 deepClone 是從 utils 檔案匯出的,因此 utils 檔案中的所有依賴項也會隨之載入。

包含大量鬆散相關函數和嚴重依賴項的檔案可能會顯著減慢您的應用程式和測試速度。

桶銼

Jest 不適合 ESM 模組,這導致它回退到 CommonJS。因此,tree-shaking 無法正常運作。當依賴從桶文件(索引檔案)導入的模組時,這尤其成問題。
例如,當您從桶檔案匯入一個小元件或函數時,Jest 也會載入其他所有內容 - 這顯然會導致不必要的開銷。

現在怎麼辦?

手動調整導入策略

除了刪除桶檔案並透過將具有大量依賴項的檔案分解為更小、更集中的模組來重構整個程式碼庫之外。我們可以識別需要長時間加載的模組並尋找較小的替代模組,或者檢查導入的模組是否單獨導出各個部分(即命名導入)而不是使用桶文件。
意思是,而不是

import React from "react";
import { deepClone } from "./utils";

export function App() {
  const obj = { foo: 'bar' };

  return (
    <div>
      <p>Object looks like this: {JSON.stringify(deepClone(obj))}</p>
    </div>
  );
}


import _ from 'lodash';
import moment from 'moment';
import * as mui from '@mui/material';

export const deepClone = (obj) => _.cloneDeep(obj);
export const getFormattedDate = (date) => moment(date).format('YYYY-MM-DD');

export const isButton = (instance) => instance === mui.Button;

如果我們根本不使用該模組,我們可以透過 jest.mock 來模擬它,以避免完全載入它。
然而,這些調整可能相當耗時。

運行時快取方法

更有效的方法是將 jest-neat-runner 函式庫與 NEAT_RUNTIME_CACHE 選項一起使用。當此選項開啟時,程式庫會追蹤所有模組(每個測試檔案)的實際執行情況,並將後續測試運行不需要的依賴項儲存到快取中。讓我在上面的範例中展示它的作用

import React from "react";
import { render, screen } from "@testing-library/react";
import { App } from "./app";
import "@testing-library/jest-dom";

test("renders the app", () => {
  render(<app></app>);
});

我們透過跳過 26 個不必要的庫(包括 MUI 庫)的加載,將執行時間從 5 秒減少到 2 秒。
請小心 - 使用 NEAT_RUNTIME_CACHE 時有一些注意事項,因此請務必在使用前閱讀 README。

其他優化技術

轉譯最佳化:檢查需要轉譯的檔案數量並使用最有效的轉譯器(例如 SWC 或 esbuild)。如果您想節省時間,jest-neat-runner 中的 NEAT_REPORT_TRANSFORM 選項將提供有關轉譯所需時間和模組數量的詳細資訊。

在記憶體中快取模組:預設情況下,Jest 不會在記憶體中快取模組,這表示每次測試運行都必須開啟、解析並將模組載入記憶體。如果您有大量測試和足夠的內存,請考慮使用 NEAT_TRANSFORM_CACHE 選項來加快速度。

CI 管道怎麼樣?

並行運作:CircleCI 和 GitHub Actions 支援並行運作。這意味著您可以啟動更多機器並使用 Jest 中的分片參數劃分負載。
儲存 Jest 和 Neat 快取:這對於在 CI 中利用 Jest 和 jest-neat-runner 至關重要。請務必在 Jest 中設定 cacheDirectory 選項。然後,在測試運行後儲存目錄,並在運行測試之前恢復快取。注意:如果您使用並行性,請確保為每個節點儲存唯一的快取。例如,CircleCI 公開了 CIRCLE_NODE_INDEX 環境變量,您可以在儲存快取時利用該變數。這就是它在 CircleCI 的樣子。

import React from "react";
import { deepClone } from "./utils";

export function App() {
  const obj = { foo: 'bar' };

  return (
    <div>
      <p>Object looks like this: {JSON.stringify(deepClone(obj))}</p>
    </div>
  );
}

透過遵循這些準則,您可以顯著提高 Jest 在專案中的表現。

以上是讓 Jest 運行得更快的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript數據類型:瀏覽器和nodejs之間是否有區別?JavaScript數據類型:瀏覽器和nodejs之間是否有區別?May 14, 2025 am 12:15 AM

JavaScript核心數據類型在瀏覽器和Node.js中一致,但處理方式和額外類型有所不同。 1)全局對像在瀏覽器中為window,在Node.js中為global。 2)Node.js獨有Buffer對象,用於處理二進制數據。 3)性能和時間處理在兩者間也有差異,需根據環境調整代碼。

JavaScript評論:使用//和 / * * / * / * /JavaScript評論:使用//和 / * * / * / * /May 13, 2025 pm 03:49 PM

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python vs. JavaScript:開發人員的比較分析Python vs. JavaScript:開發人員的比較分析May 09, 2025 am 12:22 AM

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

Python vs. JavaScript:選擇合適的工具Python vs. JavaScript:選擇合適的工具May 08, 2025 am 12:10 AM

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript:了解每個的優勢Python和JavaScript:了解每個的優勢May 06, 2025 am 12:15 AM

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

JavaScript的核心:它是在C還是C上構建的?JavaScript的核心:它是在C還是C上構建的?May 05, 2025 am 12:07 AM

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript應用程序:從前端到後端JavaScript應用程序:從前端到後端May 04, 2025 am 12:12 AM

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

Python vs. JavaScript:您應該學到哪種語言?Python vs. JavaScript:您應該學到哪種語言?May 03, 2025 am 12:10 AM

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!