メインコンテンツへスキップ

Jest 26: Tick-Tock モデルの開始

· 1分で読める
非公式ベータ版翻訳

このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →

Jestの再構築を開始した5年前、私たちの目標は「バッテリー内蔵」のゼロ設定テストランナーを提供することでした。初心者にも親しみやすく、ほぼすべてのテストユースケースで拡張可能で、大規模プロジェクトにも対応できるものにするためです。重要なリリースとなったJest 15は、すべてを統合し優れたデフォルト設定を提供したため、多くのユーザーが設定なしでJestを実行できるようになりました。しかしこのアプローチには大きな欠点があり、Jestがプロジェクトに不要な依存関係を多数インストールしてしまうことでした。

私たちはこの欠点に対処し始め、Jestのインストールサイズを縮小しながらも親しみやすさと拡張性を維持しています。Jest 26では以下の破壊的変更を実施しました:

  • [expect, jest-mock, pretty-format] ES5ビルドファイルを削除し、ES2015(Node 8)を新たな最小サポート環境に(ブラウザビルド専用)(#9945)

    移行手順: この変更により、対象パッケージのバンドル責任をユーザーに移管します。ユーザーが対象環境を最も理解しているためです。元の機能が必要な場合、別パッケージとして提供する可能性があります。プルリクエスト歓迎!

  • [jest-config, jest-resolve] browserフィールドのサポートを削除 (#9943)

    移行手順: browser-resolveモジュールをインストールし、以下の設定を追加:

    {
    "jest": {
    "resolver": "<rootDir>/resolver.js"
    }
    }
    // resolver.js
    const browserResolve = require('browser-resolve');

    module.exports = browserResolve.sync;
  • TypeScript定義ファイルの使用にTypeScript v3.8以上が必要に (#9823)

上記の変更により、Jest 26はJest 25.5.4より4MiB縮小しました(53 → 49MiB)。Babelのような多くの依存関係はプロジェクトに既に存在する可能性がある点にご留意ください。Jest本体のサイズは1.2MiB縮小しています(4.3 → 3.1MiB)。

これは良いスタートですが、Jestを大幅に軽量化するには不十分です。Jest本体と依存ツリーのサイズを最大70%削減する計画を進めており、デフォルト設定を縮小する変更のほとんどは小規模な破壊的変更となる予定です。コミュニティと共に進化させるため、「Tick-Tock」リリースプロセスに沿ってJest 27と28で以下の変更を実施します:

  • Jest 27では新テストランナー"jest-circus"とNode.js環境がデフォルトになります。jest-jasmine2jest-environment-jsdomは引き続き同梱され、設定ファイルの1行を変更するだけで使用可能です。

  • Jest 28ではjest-jasmine2jest-environment-jsdomをデフォルト配布から削除します。これらパッケージはJestプロジェクトの一部としてメンテナンスされ続け、別途公開されます。使用するにはユーザーがインストールする必要があります。

メジャーリリースへのアップグレード時には、Jestが必要な変更をガイドします。先行して新しいデフォルトに移行したい場合(かつDOM環境が不要なプロジェクトの場合)、Jest 26にアップグレードし以下の設定オプションを追加できます:

{
"jest": {
"testEnvironment": "node",
"testRunner": "jest-circus/runner"
}
}

Jestはデフォルトで有効なbabel-jestを引き続き同梱します。現在、babel-jestは最新のNode.jsやブラウザが理解できる形式への現代的なJavaScript構文のコンパイルだけでなく、JestのコードカバレッジやESモジュールのモック機能も支えています。Jestは現在、実験的なV8カバレッジとES Modulesのネイティブサポートを提供しています(詳細は後述!)。仕様上、コードを変換せずに静的なESモジュールをモックすることは不可能なため、現在Babelを使った変換なしで動作するパターンを推奨していきます。V8カバレッジとネイティブESMサポートがJestで安定化したら、デフォルトからbabel-jestを削除できますが、メンテナンスは継続します。

新しいフェイクタイマー

Jest 26では@sinonjs/fake-timersに基づいた新しいフェイクタイマーを導入します。この実現を数年待ち望んでおり、Jestの既存のフェイクタイマー使用ケースをすべてサポートできる段階まで進んだことを嬉しく思います。

新しい実装ではDatequeueMicrotaskのモックなど追加機能が利用可能です(詳細はREADME参照)。jest.runAllTimers()などの既存タイマーAPIと透過的に連携します - 詳細は公式ドキュメントをご覧ください。

本実装は本番環境で使用可能と確信していますが、新旧実装の微妙な差異に依存するテストの強制書き換えは避けたいと考えています。Jest 26では、jest.useFakeTimers('modern')を呼び出すか、設定でtimersオプションにmodernを指定することで新実装をオプトイン方式で有効化できます(既に全テストでフェイクタイマーを使用している場合)。

Jest 27ではデフォルトを新しい「modern」実装に切り替えますが、jest.useFakeTimers('legacy')でレガシー実装も引き続きサポートします。Jest 27リリースまでに全テストを移行できるか不安な場合は、今すぐテストにこの設定を追加して従来の動作を維持できます。

本機能実現に尽力してくださった@sinonjs/fake-timersのメンテナー、Carl-Erik Kopseng氏、Benjamin Gruenbaum氏をはじめとする皆様のご協力と忍耐に感謝します! ワクワクしますね

Jestの新しい利用法 - @jest/globals

JestはこれまでJasmineテストフレームワーク由来のdescribeittestexpectといったグローバル変数に依存してきました。このパターンは広く使われていますが、テスト関連関数をインポートする形式を好む声も多くあります。この要望に応え、テスト関数をインポート可能にする新パッケージ@jest/globalsを追加しました:import {expect, jest, test} from '@jest/globals';

注意点:

  • 現時点ではグローバル変数は残りますが、将来無効化するモードを導入予定です。同様に、jest変数がグローバルなためconst jest = require('@jest/globals')は宣言エラーになります

  • 現時点ではこの形式でグローバルを使用する場合、TypeScript定義へカスタムマッチャーを追加する方法がありません

  • グローバル変数なしでテストを実行できますが、現時点ではJestのテストランナーなしでの実行はサポートされていません

ネイティブESMサポート

Jest 25 のブログ記事で述べたように、私たちは ECMAScript Modules のネイティブサポートに取り組んできました。まだ安定版ではありませんが、テスト可能な状態です。皆さんのフィードバックやバグ報告をお待ちしています!現在の状況の概要については、この issue をご覧いただくか、ES Modules ラベルが付いたすべての issue を参照してください。

Jest 26 のその他の破壊的変更

  • Node 8 のサポートを終了しました (#9423)

  • [jest-environment-jsdom] jsdom を v16 にアップグレードしました (#9606)

  • [jest-runtime] 長らく非推奨となっていた require.requireActual および require.requireMock メソッドを削除しました (#9854)

  • [jest-haste-map] providesModuleNodeModules を削除しました (#8535)

  • [jest-circus] テストが done コールバックを受け取り、かつ戻り値がある場合、テストを失敗させます (#9129)

  • [jest-circus] テストやフックが非同期で定義された場合、適切なエラーをスローします (#8096)

安全にお過ごしください

私たちは今、前例のない不確実な時代を経験しています。経済的に苦境にある場合、Jest の Open Collective 基金を活用して、新規および既存のコントリビューターを支援したいと考えています。私たちは特定の issue にバウンティを設定しており、現在オープン中の issue に対してバウンティを提供することも可能です - issue 内でバウンティ設定を提案するか、Twitter で @cpojer にダイレクトメッセージでご連絡ください。

どうか安全にお過ごしください。