Mari Jadikan Jest Berlari Lebih Pantas

Patricia Arquette
Lepaskan: 2024-10-31 12:23:54
asal
530 orang telah melayarinya

Let’s Make Jest Run Much Faster

Tetapi pertama-tama, kita perlu faham mengapa ia begitu perlahan.

Contoh Praktikal

Pertimbangkan komponen React yang mudah.

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>
  );
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Komponen apl hanya bergantung pada satu fungsi utiliti - deepClone. Fail utils kelihatan seperti ini.

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;
Salin selepas log masuk
Salin selepas log masuk

Ia mengeksport tiga fungsi pembantu satu baris. Itu sahaja.
Sekarang, inilah soalan besar: Pada pendapat anda, berapa lama masa yang diperlukan untuk melaksanakan ujian ini?

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 />);
});
Salin selepas log masuk
Salin selepas log masuk

Jawapannya? Keabadian!

 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
Salin selepas log masuk

Ia mengambil masa 5 saat pada mesin saya, untuk melaksanakan kes ujian satu pelapik bagi komponen React satu pelapik.

Menganalisis Prestasi

Untuk menganalisis perkara yang berlaku di sebalik tabir, kita boleh menggunakan sama ada pemprofil Chrome - Saya syorkan menonton video bernas ini oleh Kent C. Dodds.
Sebagai alternatif, anda boleh menggunakan perpustakaan jest-neat-runner, yang memudahkan proses pemprofilan. Tetapkan pilihan NEAT_REPORT_MODULE_LOAD_ABOVE_MS kepada 150 dan dayakan NEAT_REPORT_TRANSFORM. Konfigurasi ini akan mencetak modul yang mengambil masa lebih daripada 150ms untuk dimuatkan dan memberikan maklumat tentang tempoh masa yang diambil untuk memproses (membuka dan mentranspile) fail.

Jom gunakan yang kedua. Ini adalah outputnya.

> 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
Salin selepas log masuk

Kami memuatkan perpustakaan "@mui/material" selama hampir 2 saat tanpa menggunakannya!

Punca Punca Dalam Banyak Projek?

Ketergantungan yang tidak kemas

Menurut pengalaman saya, masalah prestasi dengan gurauan terutamanya berpunca daripada bilangan besar kebergantungan transitif yang tidak digunakan pada masa jalanan. Seperti yang ditunjukkan dalam contoh kami di atas, jika anda tidak memberi perhatian yang cukup kepada fail yang anda import ke dalam aplikasi anda, anda mungkin akan mengalami situasi yang sama seperti saya.

Dalam kes saya, komponen App hanya bergantung pada fungsi utiliti deepClone. Walau bagaimanapun, memandangkan deepClone dieksport daripada fail utils, semua kebergantungan dalam fail utils turut dimuatkan bersamanya.

Fail yang mengandungi banyak fungsi berkaitan yang longgar dan kebergantungan berat mungkin melambatkan aplikasi dan ujian anda dengan ketara.

Fail Tong

Jest bukan rakan dengan modul ESM, yang membawanya kepada sandaran kepada CommonJS. Akibatnya, goncangan pokok tidak berfungsi dengan betul. Ini amat bermasalah apabila bergantung pada modul yang diimport daripada fail tong (fail indeks).
Contohnya, apabila anda mengimport komponen atau fungsi kecil daripada fail tong, Jest akan memuatkan semua yang lain juga - yang jelas menyebabkan overhed yang tidak perlu.

Apa Sekarang?

Melaraskan Strategi Import Secara Manual

Selain daripada mengalih keluar fail tong dan memfaktorkan semula keseluruhan pangkalan kod dengan memecahkan fail dengan banyak kebergantungan kepada modul yang lebih kecil dan lebih fokus. Kami boleh mengenal pasti modul yang mengambil masa yang lama untuk dimuatkan dan mencari modul alternatif yang lebih kecil atau menyemak sama ada modul yang diimport mengeksport bahagian individu secara berasingan (iaitu, import dinamakan) dan bukannya menggunakan fail tong.
Maksudnya, bukannya

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>
  );
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

buat

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;
Salin selepas log masuk
Salin selepas log masuk

Jika kami tidak menggunakan modul itu sama sekali, kami boleh mengejeknya melalui jest.mock untuk mengelakkan memuatkannya sepenuhnya.
Walau bagaimanapun, pelarasan ini boleh memakan masa yang agak lama.

Pendekatan Cache Masa Jalan

Kaedah yang lebih berkesan melibatkan penggunaan perpustakaan jest-neat-runner dengan pilihan NEAT_RUNTIME_CACHE. Apabila pilihan ini dihidupkan, pustaka menjejaki penggunaan masa jalan sebenar semua modul (setiap fail ujian) dan menyimpan kebergantungan yang kami tidak perlukan untuk ujian berikutnya dijalankan ke dalam cache. Biar saya tunjukkan fungsinya pada contoh di atas

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 />);
});
Salin selepas log masuk
Salin selepas log masuk

Kami mengurangkan masa pelaksanaan daripada lima saat kepada dua dengan melangkau memuatkan 26 perpustakaan yang tidak diperlukan, termasuk perpustakaan MUI.
Berhati-hati - terdapat beberapa kaveat apabila menggunakan NEAT_RUNTIME_CACHE, jadi pastikan anda membaca README sebelum menggunakannya.

Teknik Pengoptimuman Lain

Pengoptimuman transpilasi: Periksa bilangan fail yang perlu ditranpilkan dan gunakan transpiler yang paling berkesan (seperti SWC atau esbuild). Jika anda ingin menjimatkan masa, pilihan NEAT_REPORT_TRANSFORM dalam jest-neat-runner akan memberikan maklumat terperinci tentang berapa banyak masa dan berapa banyak modul yang diperlukan untuk transpile.

Caching Modul dalam Memori: Secara lalai, Jest tidak cache modul dalam memori, bermakna setiap ujian dijalankan mesti membuka, menghuraikan dan memuatkan modul ke dalam memori. Jika anda mempunyai rangkaian ujian yang luas dan ingatan yang mencukupi, pertimbangkan untuk menggunakan pilihan NEAT_TRANSFORM_CACHE untuk mempercepatkan perkara.

Bagaimana dengan Talian Paip CI?

Larian Selari: CircleCI dan Tindakan GitHub menyokong larian selari. Ini bermakna anda boleh memutarkan lebih banyak mesin dan membahagikan beban menggunakan parameter shard dalam Jest.
Menyimpan Cache Jest dan Rapi: Ini penting untuk memanfaatkan Jest dan jest-neat-runner dalam CI. Pastikan anda menetapkan pilihan cacheDirectory dalam Jest. Kemudian, simpan direktori selepas ujian dijalankan dan pulihkan cache sebelum menjalankan ujian. Kaveat: Jika anda menggunakan selari, pastikan anda menyimpan cache unik untuk setiap nod. Sebagai contoh, CircleCI mendedahkan pembolehubah persekitaran CIRCLE_NODE_INDEX, yang boleh anda manfaatkan apabila menyimpan cache. Beginilah rupanya dalam 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>
  );
}
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dengan mengikut garis panduan ini, anda boleh meningkatkan prestasi Jest dengan ketara dalam projek anda.

Atas ialah kandungan terperinci Mari Jadikan Jest Berlari Lebih Pantas. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan