テストが実行される場所

自動テストは通常、手動でスクリプトを実行するか、テスト フレームワーク(テストランナーとも呼ばれる)のヘルパーを使用してテストを見つけて実行することで実行できます。ただし、スクリプトを手動で実行する必要がない場合もあります。テストを実行する方法はいくつかあり、開発ライフサイクルのさまざまな時点でフィードバックと自信を得ることができます。

前提条件のスクリプト

通常、ウェブ プロジェクトには構成ファイル(package.json ファイル)があります。このファイルは、npm、pnpm、Bun などによって設定されます。この構成ファイルには、プロジェクトの依存関係やその他の情報、ヘルパー スクリプトが含まれています。これらのヘルパー スクリプトには、プロジェクトをビルド、実行、テストする方法が含まれている場合があります。

package.json 内に、テストの実行方法を記述する test というスクリプトを追加する必要があります。npm などのツールを使用する場合、「test」スクリプトには特別な意味があるため、これは重要です。このスクリプトでは、例外をスローする 1 つのファイル(node tests.js など)のみを指定できますが、確立済みのテストランナーを指定することをおすすめします。

テストランナーとして Vitest を使用している場合、package.json ファイルは次のようになります。

{
  "name": "example-project",
  "scripts": {
    "start": "node server.js",
    "test": "vitest --run"
  }
}

このファイルを使用して npm test を実行すると、Vitest のデフォルトのテストセットが 1 回実行されます。Vitest のデフォルトでは、末尾が「.test.js」または類似のファイルをすべて検索して実行します。選択したテストランナーによって、コマンドが若干異なる場合があります。

このコースでは、例として、人気が高まっているテスト フレームワークである Vitest を使用しています。この決定について詳しくは、テストランナーとしての Vitest をご覧ください。ただし、テスト フレームワークとテストランナーは、言語が違っても、共通の用語を持つ傾向があることにご注意ください。

手動テスト呼び出し

コードベースに積極的に取り組んでいる間は、自動テストを手動でトリガーする方法(上記の例の npm test を使用するなど)が実用的です。機能の開発中に機能のテストを作成すると、その機能の動作を理解するのに役立ちます。テストドリブン開発(TDD)のコンセプトに触れています。

テストランナーには通常、テストの一部またはすべてを実行するために呼び出す短いコマンドと、場合によってはテストを保存すると再実行するウォッチャー モードがあります。これらはすべて、新機能を開発する際に役立つオプションであり、新しい機能とそのテスト、またはその両方を迅速なフィードバックで簡単に記述できるように設計されています。たとえば、Vitest はデフォルトでウォッチャー モードで動作します。つまり、vitest コマンドは変更を監視し、検出したテストを再実行します。テストの作成中は、このウィンドウを別のウィンドウで開いたままにしておくことをおすすめします。これにより、テストを開発する際に迅速にフィードバックを得ることができます。

一部のランナーでは、コード内でテストを only としてマークすることもできます。コードに only テストが含まれている場合は、テストの実行時にこれらのテストのみがトリガーされるため、テスト開発を迅速かつ簡単にトラブルシューティングできます。すべてのテストが短時間で完了する場合でも、only を使用するとオーバーヘッドが削減され、作業中の機能やテストとは無関係なテストを実行する手間が省けます。

小規模なプロジェクト、特に開発者が 1 人しかいないプロジェクトでは、コードベースのテストスイート全体を定期的に実行する習慣を身に付けることもおすすめします。これは、テストが小規模で迅速に(すべてのテストで数秒以内に)完了する場合に特に役立ちます。これにより、次に進む前にすべてが正常に機能していることを確認できます。

presubmit または review の一環としてテストを実行する

多くのプロジェクトでは、コードを main ブランチにマージし直す際に、コードベースが正しく機能していることを確認しています。テストを初めて行う人でも、過去にオープンソース プロジェクトに貢献したことがある場合は、pull リクエスト(PR)プロセスの一部で、プロジェクトのすべてのテストに合格したことが確認されます。つまり、新しく貢献したことが既存のプロジェクトに悪影響を及ぼさなかったことがわかるでしょう。

テストをローカルで実行する場合、プロジェクトのオンライン リポジトリ(GitHub や別のコード ホスティング サービスなど)は、テストに合格したことを認識しないため、テストを presubmit タスクとして実行すると、すべてが機能していることがすべてのコントリビューターに明確になります。

たとえば GitHub では、これらを「ステータス チェック」と呼んでいます。ステータス チェックは、GitHub Actions で追加できます。GitHub Actions は基本的に一種のテストです。各ステップが成功する(失敗しない、または Error をスローしない)必要があります。アクションはプロジェクトのすべての PR に適用できます。プロジェクトでは、コードを投稿する前にアクションが渡すことを要求できます。GitHub のデフォルトの Node.js アクションは、ステップの 1 つとして npm test を実行します。

GitHub Actions テストプロセスのスクリーンショット。
GitHub Actions テストプロセスのスクリーンショット。

このテスト手法では、テストを正常に実行できないコードを受け入れないことにより、コードベースが常に「緑色」になるようにします。

継続的インテグレーションの一環としてテストを実行する

Green PR が承認されると、ほとんどのコードベースは以前の PR ではなく、プロジェクトの main ブランチに基づいてテストを再度実行します。これは直ちに発生する場合もあれば、定期的に(毎晩、毎晩など)行われる場合もあります。多くの場合、これらの結果は、プロジェクト全体の健全性を示す継続的インテグレーション(CI)ダッシュボードの一部として表示されます。

この CI のステップは、特にコードベースが小さいプロジェクトでは冗長に思えるかもしれません。つまり、テストはレビューで合格するため、変更が適用されると合格するはずです。ただし、常にそうなるとは限りません。緑色の結果が正常に返された後でも、テストが突然失敗することがあります。これには次のような理由があります。

  • 複数の変更が「一度に」承認されました。これは競合状態とも呼ばれます。これらの変更は微妙にテストされていない方法で相互に影響し合います。
  • テストを再現できないか、「不安定」なコードをテストします。コードを変更しなくても、合格と不合格の両方になる可能性があります。
    • これは、コードベースの外部のシステムに依存している場合に発生することがあります。プロキシの場合、Math.random() > 0.05 の場合のテストを想像してください。これは、5% の確率でランダムに失敗します。
  • エンドツーエンド テスト(これについては自動テストの種類で詳しく説明します)など、すべての PR で実行するにはコストがかかりすぎるテストもあります。このようなテストは、時間の経過とともに、常にアラートを発生させることなく中断する可能性があります。

これらの問題を克服することは不可能ではありませんが、テストやソフトウェア開発全般は、決して正しい科学とは言えません。

ロールバックの合間曲

継続的インテグレーションの一環としてテストを実行した場合、ステータス チェックの一環としてテストを実行した場合でも、ビルドが「赤」状態、つまりテストの失敗を示す別の状態になる可能性があります。前述のように、これはテスト送信の競合状態や不安定なテストなど、さまざまな理由で発生する可能性があります。

小規模なプロジェクトでは、危機として扱いたいと思うかもしれません。すべてを停止し、不適切な変更をロールバックまたは元に戻して、既知の正常な状態に戻します。有効なアプローチになり得ますが、テスト(そしてソフトウェア全般)は目的への手段であり、それ自体は目的ではないことを覚えておいてください。目標は、すべてのテストに合格することではなく、ソフトウェアを作成することです。代わりに、失敗したテストを修正する別の変更で互換性を破る変更をフォローアップすることで、ロール フォワードできます。

一方、永続的に機能しない状態で存在する大規模なプロジェクトを見たり、取り組んだりしたことがあるかもしれません。さらに悪いことに、大規模なプロジェクトではテストが不安定で、デベロッパーのアラーム疲れを引き起こすほど頻繁に中断します。これは多くの場合、リーダーが解決すべき存続に関わる問題です。このようなテストは、「開発の妨げになる」と見なされて、無効になることもあります。

これに対する簡単な修正はありませんが、テストの作成に自信を持てるようになり(スキルアップ)、テストの範囲を縮小(簡素化)してエラーを特定しやすくなります。コンポーネント テスト統合テスト(種類は自動テストの種類を参照)の数を増やせば、メンテナンスが難しく、一度にあらゆることを試行する 1 つの巨大なエンドツーエンド テストよりも信頼性が高まります。

リソース

理解度をチェックする

npm や同様のプログラムがテスト中に検索する特別なスクリプトの名前は何ですか?

テスト
presubmit
verify