測試 Rspack

Rspack 的測試案例包括以下內容

  • Rspack 核心測試案例儲存在 packages/rspack-test-tools/tests 資料夾中,將透過模擬建置過程來執行測試案例。一般而言,應在此資料夾中新增測試案例。
  • 其他 Rspack 套件的測試案例儲存在 packages/{name}/tests 資料夾中,只有在修改該套件時才應新增或修改。

執行測試

您可以透過以下方式執行這些測試案例

  • 從根目錄執行 ./x test unitpnpm run test:unit
  • 或從 packages/rspack-test-tools 目錄執行 npm run test
  • 若要更新快照,請從 packages/rspack-test-tools 目錄執行 npm run test -- -u
  • 若要傳遞特定的 jest cli 引數,請從 packages/rspack-test-tools 目錄執行 npm run test -- {args}
  • 若要篩選特定的測試案例,請從 packages/rspack-test-tools 目錄執行 npm run test -- -t path-of-spec
    • 例如 npm run test -- -t config/asset 只會執行 packages/rspack-test-tools/configCases/asset 資料夾中的測試案例(config 會自動對應到 configCases,其他資料夾的工作方式類似)。

目錄結構

packages/rspack-test-tools/tests 資料夾的結構如下

.
├── js # Used to store build artifacts and temporary files
├── __snapshots__ # Used to store test snapshots
├── {Name}.test.js # Entry for normal testing
├── {Name}.hottest.js # Entry for hot snapshot testing
├── {Name}.difftest.js # Entry for diff testing
├── {name}Cases # Directory to store test cases
└── fixtures # General test files

{Name}.test.js 是測試的進入點檔案,它會走訪 {name}Cases 資料夾並執行其中的案例。因此,當您需要新增或修改測試案例時,請根據測試類型將它們新增至相關的 {name}Cases 資料夾。

測試類型

現有的測試類型為

  • Normal:用於測試沒有組態變更的核心建置過程。當測試不需要新增 rspack.config.js 時,會使用此類型。
  • Config:用於測試建置組態選項。如果您的測試需要透過 rspack.config.js 新增特定的組態才能執行,並且不符合其他情境,請使用此測試類型。
  • Hot:用於測試熱模組替換 (HMR) 是否正確執行。此類型包含具有固定 target=async-node 的 HotNode、具有固定 target=web 的 HotWeb 和具有固定 target=webworker 的 HotWorker。
  • HotSnapshot:用於測試 HMR 是否可以產生正確的中間成品。此測試類型與 Hot 類型共用測試案例,並為每個 HMR 的增量成品產生快照。
  • Watch:用於測試在 Watch 模式下修改檔案後的增量編譯。
  • StatsOutput:用於測試建置結束後的控制台輸出記錄。
  • StatsAPI:用於測試建置結束後產生的 Stats 物件。
  • Diagnostic:用於測試建置過程中產生的警告/錯誤的格式化輸出資訊。
  • Hash:用於測試雜湊產生是否正確運作。
  • Compiler:用於測試 Compiler/Compilation 物件 API。
  • Defaults:用於測試組態選項之間的互動。
  • Error:用於測試 compilation.errorscompilation.warnings 之間的互動。
  • Hook:用於測試各種 hook 功能。
  • TreeShaking:用於測試與 Tree Shaking 相關的功能。
  • Builtin:用於測試具有內建原生實作的插件。

請優先在上述測試類型中新增測試案例。

Normal

測試進入點 tests/Normal.test.js
案例目錄 tests/normalCases
輸出目錄 tests/js/normal
預設組態 NormalProcessor
執行輸出

案例的撰寫方式與常規 rspack 專案相同,但不包含 rspack.config.js 檔案,並且會使用提供的組態進行建置。

Config

測試進入點 tests/Config.test.js
案例目錄 tests/configCases
輸出目錄 tests/js/config
預設組態 ConfigProcessor
執行輸出

此測試案例與常規 rspack 專案類似。您可以透過新增 rspack.config.js 來指定建置組態,並透過新增 test.config.js 來控制測試期間的各種行為。test.config.js 檔案的結構如下

test.config.js
1type TConfigCaseConfig = {
2  noTest?: boolean; // Do not run the test output and end the test
3  beforeExecute?: () => void; // Callback before running the output
4  afterExecute?: () => void; // Callback after running the output
5  moduleScope?: (ms: IBasicModuleScope) => IBasicModuleScope; // Module context variables when running the output
6  findBundle?: (
7    // Function for obtaining output when running the output, can control the output at a finer granularity
8    index: number, // Compiler index in multi-compiler scenario
9    options: TCompilerOptions<T>, // Build configuration object
10  ) => string | string[];
11  bundlePath?: string[]; // Output file name when running the output (prior to findBundle)
12  nonEsmThis?: (p: string | string[]) => Object; // this object during CJS output runtime, defaults to current module's module.exports if not specified
13  modules?: Record<string, Object>; // Pre-added modules when running the output, will be prioritized when required
14  timeout?: number; // Timeout for the test case
15};
16
17/** @type {import("../../../..").TConfigCaseConfig} */
18module.exports = {
19  // ...
20};

Hot

測試進入點 Hot{Target}.test.js
案例目錄 tests/hotCases
輸出目錄 tests/js/hot-{target}
預設組態 HotProcessor
執行輸出

此測試案例與常規 rspack 專案類似。您可以透過新增 rspack.config.js 來指定建置組態。

此外,在已變更的檔案中,使用 --- 來分隔變更前和變更後的程式碼

file.js
module.exports = 1; // Initial build
---
module.exports = 2; // First hot update
---
module.exports = 3; // Second hot update

在測試案例程式碼中,使用 NEXT 方法來控制檔案變更的時機,並在其中新增測試程式碼

index.js
import value from './file';

it('should hot update', done => {
  expect(value).toBe(1);
  // Use packages/rspack-test-tools/tests/hotCases/update.js to trigger update
  NEXT(
    require('../../update')(done, true, () => {
      expect(value).toBe(2);
      NEXT(
        require('../../update')(done, true, () => {
          expect(value).toBe(3);
          done();
        }),
      );
    }),
  );
});

module.hot.accept('./file');

HotSnapshot

測試進入點 HotSnapshot.hottest.js
案例目錄 tests/hotCases
輸出目錄 tests/js/hot-snapshot
預設組態 Hot 相同
執行輸出

使用與 Hot{Target} 相同的測試案例,並在案例資料夾中產生 __snapshots__/{target}/{step}.snap.txt 檔案,以對每個 HMR 的增量成品執行快照測試。

快照結構如下

  • 已變更的檔案:觸發此 HMR 建置的原始程式碼檔案
  • 資產檔案:此 HMR 建置的成品檔案
  • 資訊清單:此 HMR 建置的 hot-update.json 中繼資料檔案的內容,其中
    • "c":此 HMR 中要更新的區塊的 ID
    • "r":此 HMR 中要移除的區塊的 ID
    • "m":此 HMR 中要移除的模組的 ID
  • 更新:關於此 HMR 建構的 hot-update.js 補丁檔案的資訊,包括
    • 變更的模組:包含在補丁中的模組列表
    • 變更的執行階段模組:包含在補丁中的執行階段模組列表
    • 變更的內容:補丁程式碼的快照

監看

入口檔案 Watch.test.js
案例目錄 tests/watchCases
輸出目錄 tests/js/watch
預設組態 WatchProcessor
執行輸出

由於監看建構需要分多個步驟執行,您可以透過加入 rspack.config.js 來指定建構設定。其案例的目錄結構較為特殊,將使用遞增的數字來表示變更批次

.
├── 0 # WATCH_STEP=0, initial code for the case
├── 1 # WATCH_STEP=1, diff files for the first change
├── 2 # WATCH_STEP=2, diff files for the second change
└── rspack.config.js

在測試程式碼中,您可以使用 WATCH_STEP 變數來取得當前變更的批次號碼。

StatsOutput

測試進入點 StatsOutput.test.js
案例目錄 tests/statsOutputCases
輸出目錄 tests/js/statsOutput
預設組態 StatsProcessor
執行輸出

案例的寫法與一般的 rspack 專案相同。執行後,主控台的輸出資訊將會被擷取成快照,並儲存在 rspack-test-tools/tests/__snapshots__/StatsOutput.test.js.snap 中。

提示

由於某些 StatsOutput 測試案例包含雜湊值,當您修改輸出程式碼時,請使用 -u 參數來更新這些案例的快照。

Stats API

入口檔案 StatsAPI.test.js
案例目錄 tests/statsAPICases
輸出目錄
預設組態
執行輸出

此測試使用 rspack-test-tools/tests/fixtures 作為建構的原始碼,因此測試案例會寫成單一檔案。其結構如下

{case}.js
1type TStatsAPICaseConfig = {
2  description: string, // Case description
3  options?: (context: ITestContext) => TCompilerOptions<T>, // Case build configuration
4  build?: (context: ITestContext, compiler: TCompiler<T>) => Promise<void>, // Case build method
5  check?: (stats: TCompilerStats<T>, compiler: TCompiler<T>) => Promise<void>, // Function to check the stats for the case
6};
7
8/** @type {import('../..').TStatsAPICaseConfig} */
9module.exports = {
10  // ...
11};

診斷

入口檔案 Diagnostics.test.js
案例目錄 tests/diagnosticsCases
輸出目錄 tests/js/diagnostics
預設組態 DiagnosticProcessor
執行輸出

此測試案例與典型的 rspack 專案類似,可以透過加入 rspack.config.js 來指定建構設定。此外,它會在案例目錄中新增一個 stats.err 檔案,以儲存警告/錯誤的快照。若要重新整理,請使用 -u 參數。

雜湊

入口檔案 Hash.test.js
案例目錄 tests/hashCases
輸出目錄
預設組態 HashProcessor
執行輸出

此測試案例與典型的 rspack 專案類似,但它會在案例目錄中新增一個 test.config.js 檔案,並指定一個 validate() 方法,以在建構完成後檢查 stats 物件中的雜湊資訊

test.config.js
1type THashCaseConfig = {
2  validate?: (stats: TCompilerStats<T>) => void,
3};
4
5/** @type {import('../..').THashCaseConfig} */
6module.exports = {
7  // ...
8};

編譯器

入口檔案 Compiler.test.js
案例目錄 tests/compilerCases
輸出目錄
預設組態
執行輸出

此測試使用 rspack-test-tools/tests/fixtures 作為建構的原始碼,因此測試案例會寫成單一檔案。其結構如下

{case.js}
1interface TCompilerCaseConfig {
2  description: string; // Description of the test case
3  options?: (context: ITestContext) => TCompilerOptions<T>; // Test case build configuration
4  compiler?: (context: ITestContext, compiler: TCompiler<T>) => Promise<void>; // How the compiler is created for the test case
5  build?: (context: ITestContext, compiler: TCompiler<T>) => Promise<void>; // Build method for the test case
6  check?: (
7    context: ITestContext,
8    compiler: TCompiler<T>,
9    stats: TCompilerStats<T>,
10  ) => Promise<void>; // Check function for the test case
11}
12
13/** @type {import('../..').TCompilerCaseConfig} */
14module.exports = {
15  // ...
16};

預設值

入口檔案 Defaults.test.js
案例目錄 tests/defaultCases
輸出目錄
預設組態
執行輸出

此測試不會執行實際的建構;它只會產生建構設定並觀察與預設設定的差異。基本的預設設定將被快照並儲存在 rspack-test-tools/tests/__snapshots__/Defaults.test.js.snap 中。

此測試使用 rspack-test-tools/tests/fixtures 作為建構的原始碼,因此測試案例會寫成單一檔案。其結構如下

{case}.js
1interface TDefaultsCaseConfig {
2  description: string; // Description of the test case
3  cwd?: string; // process.cwd for generating the build configuration of the test case, default is the `rspack-test-tools` directory
4  options?: (context: ITestContext) => TCompilerOptions<ECompilerType.Rspack>; // Test case build configuration
5  diff: (
6    diff: jest.JestMatchers<Diff>,
7    defaults: jest.JestMatchers<TCompilerOptions<ECompilerType.Rspack>>,
8  ) => Promise<void>; // Differences from the default configuration
9}
10
11/** @type {import('../..').TDefaultsCaseConfig} */
12module.exports = {
13  // ...
14};

錯誤測試的詳細資訊如下

錯誤

入口檔案 Error.test.js
案例目錄 tests/errorCases
輸出目錄
預設組態 ErrorProcessor
執行輸出

此測試使用 rspack-test-tools/tests/fixtures 作為建構的原始碼,因此測試案例會寫成單一檔案。其結構如下

{case}.js
1interface TErrorCaseConfig {
2  description: string; // Description of the test case
3  options?: (
4    options: TCompilerOptions<T>,
5    context: ITestContext,
6  ) => TCompilerOptions<T>; // Test case configuration
7  build?: (context: ITestContext, compiler: TCompiler<T>) => Promise<void>; // Test case build method
8  check?: (stats: TStatsDiagnostics) => Promise<void>; // Function to check the test case
9}
10
11/** @type {import('../..').TErrorCaseConfig} */
12module.exports = {
13  // ...
14};

Hook

入口檔案 Hook.test.js
案例目錄 tests/hookCases
輸出目錄
預設組態 HookProcessor
執行輸出

此測試記錄 hook 的輸入和輸出,並將其儲存在快照 hooks.snap.txt 中。最終產品程式碼的快照儲存在 output.snap.txt 中。

此測試使用 rspack-test-tools/tests/fixtures 作為建構的原始碼,因此測試案例會寫成單一檔案。其結構如下

{case}/test.js
1interface THookCaseConfig {
2  description: string; // Description of the test case
3  options?: (
4    options: TCompilerOptions<T>,
5    context: ITestContext,
6  ) => TCompilerOptions<T>; // Test case configuration
7  compiler?: (context: ITestContext, compiler: TCompiler<T>) => Promise<void>; // Callback after creating the compiler instance
8  check?: (context: ITestContext) => Promise<void>; // Callback after the build is completed
9}
10
11/** @type {import("../../../..").THookCaseConfig} */
12module.exports = {
13  // ...
14};

TreeShaking

入口檔案 TreeShaking.test.js
案例目錄 tests/treeShakingCases
輸出目錄 tests/js/treeShaking
預設組態 TreeShakingProcessor
執行輸出

在此測試案例中,設定與一般的 rspack 專案類似。您可以透過加入 rspack.config.js 來指定建構設定,但最終產品會被快照並儲存在 __snapshots__/treeshaking.snap.txt 中。

內建

入口檔案 Builtin.test.js
案例目錄 tests/builtinCases
輸出目錄 tests/js/builtin
預設組態 BuiltinProcessor
執行輸出

此測試案例與一般的 rspack 專案類似,您可以透過加入 rspack.config.js 來指定建構設定。然而,根據目錄的不同,會產生不同的產品快照,並儲存在 __snapshots__/output.snap.txt

  • plugin-css:具有 .css 副檔名的檔案快照
  • plugin-css-modules:具有 .css.js 副檔名的檔案快照
  • plugin-html:具有 .html 副檔名的檔案快照
  • 其他:具有 .js 副檔名的檔案快照