【ITニュース解説】Is Playwright's sharding slowing you down? Meet "Pawdist"
2025年09月11日に「Dev.to」が公開したITニュース「Is Playwright's sharding slowing you down? Meet "Pawdist"」について初心者にもわかりやすく解説しています。
ITニュース概要
Playwrightのテストを複数に分けて同時実行する際、静的な分割だと各テストの時間差で遅い部分が全体の完了を遅らせ、資源も無駄になる。これを解決するため、テストを動的に割り振るツール「Pawdist」が登場。テスト実行時間を短縮し、資源を効率良く使えるようになる。
ITニュース解説
ソフトウェア開発において、作ったプログラムが意図通りに動くか確認する「テスト」は非常に重要だ。特に大規模なシステムや頻繁に更新されるサービスでは、テストの数が膨大になり、手作業での確認は現実的ではない。そこで、「テスト自動化」という技術が広く使われている。Playwrightは、ウェブサイトやウェブアプリケーションの動作を自動でテストするための強力なツールの一つであり、多くの開発現場で利用されている。
Playwrightのような自動テストツールでは、テストの数が増えると、実行にかかる時間も長くなってしまう。この問題を解決するために、「複数のテストを同時に、異なるコンピュータで並行して実行する」という方法が取られる。Playwrightには「シャード(shard)」と呼ばれる機能があり、--shardというオプションを使って、この並行実行を実現できる。これは、テストをいくつかのグループに分け、それぞれ別のコンピュータ(「CIランナー」と呼ばれる、テスト実行用のサーバーや仮想環境のこと)に割り当てて同時に実行することで、全体のテスト時間を短縮しようとするものだ。例えば、テストが100個あれば、4つのCIランナーに25個ずつ割り当てて同時に実行するイメージである。
しかし、このPlaywrightのシャード機能には大きな問題がある。それは、その仕組みが「静的」であるという点だ。静的シャードとは、テストが始まる前に、どのCIランナーがどのテストを実行するかを事前に決めてしまう方法を指す。例えば、4つのCIランナーを使う場合、最初のCIランナーにはテスト全体の最初の4分の1を、次のCIランナーには次の4分の1を、というように、テストのファイルを順番に均等に分割して割り振る。もしすべてのテストがぴったり同じ時間で終わるのであれば、この方法は非常に効率的である。しかし、現実世界では、テストにかかる時間は常に変動する。ログイン処理だけを確認するような短いテストもあれば、複雑なユーザー操作をシミュレートするような非常に長いテストも存在する。
このような状況で静的シャードを使うと、負荷の不均衡という問題が発生する。あるCIランナーには偶然にも短いテストばかりが集中し、すぐにテストを終えてアイドル状態になる一方で、別のCIランナーには長いテストばかりが集中し、なかなかテストが終わらないという状況が生まれるのだ。結果として、全体のテスト実行時間は、最も時間がかかったCIランナーの完了を待つことになるため、期待したほどの時間短縮効果が得られない。早く終わったCIランナーは、残りの時間をただ待っているだけなので、その間、リソースが無駄になってしまう。
具体的な例として、あるシステムで53個のテストを4つのCIランナーにPlaywrightの静的シャードで分散させた場合が挙げられる。それぞれのCIランナーの実行時間は、46秒、1分45秒、41秒、1分1秒とばらつきが生じた。この場合、全体のテストが完了したと見なされるのは、最も遅いCIランナーである1分45秒が経過した後となる。しかし、最も速いCIランナーはわずか41秒でテストを終えていたため、残りの1分4秒もの間、何もせずに他のCIランナーが終わるのを待っていたことになる。これはCI/CD(継続的インテグレーション・継続的デリバリー)の環境におけるリソースの無駄であり、開発者がテスト結果を受け取るまでの時間(フィードバックサイクル)を長くしてしまう要因となる。
この静的シャードの問題を解決するために開発されたのが「Pawdist」というツールだ。PawdistはRustというプログラミング言語で開発され、「動的テスト分散」というアプローチを取る。動的分散とは、テストの割り振りを事前に固定するのではなく、テストが進行する中で、空いているCIランナーに次に実行すべきテストをリアルタイムで割り当てていく方法だ。
Pawdistは「マネージャー・ワーカー」というアーキテクチャで動作する。
- マネージャー: すべてのテストをスキャンし、まだ実行されていないテストのリスト(これを「作業キュー」と呼ぶ)を作成し、一元管理する。
- ワーカー: 実際にテストを実行するCIランナーやプロセスを指す。ワーカーはマネージャーに接続し、「次に実行するテストをください」と要求する。テストが完了すると、その結果をマネージャーに報告し、すぐに次のテストを要求する。
この仕組みにより、あるワーカーが短いテストを素早く終えた場合でも、すぐに次のテストに取り掛かれるため、CIランナーがアイドル状態になることなく、常に効率的に作業し続けることが可能となる。結果として、すべてのリソースが最後まで最大限に活用され、全体のテスト実行時間の短縮に貢献する。
Pawdistの実際の効果を検証するため、100個のテストを持つサンプルプロジェクトが用意された。このプロジェクトでは、意図的にテストの長さにばらつきが持たされている。具体的には、最初の50個のテストはそれぞれ15〜25秒かかる「長いテスト」であり、残りの50個のテストは1〜15秒で終わる「短いテスト」である。このテストスイートを3つの異なる方法で実行し、パフォーマンスを比較した。
- ベースライン(シャードなし): まず、すべての100個のテストを1台のコンピュータで、4つのテストを並行して実行した場合の時間が測定された。これは、環境が最適に設定された場合の理想的な実行時間となる。結果は6分3秒であった。
- Playwrightの静的シャード: 次に、テストを2つのCIランナーに分割し、それぞれで2つのテストを並行実行するPlaywrightの静的シャードを適用した。Playwrightはテストファイルを順番に分割するため、最初のCIランナー(シャード1/2)には、長いテストであるテスト1〜50がすべて割り振られた。このため、このCIランナーは8分36秒かかった。もう一方のCIランナー(シャード2/2)には、短いテストであるテスト51〜100がすべて割り振られたため、わずか3分32秒で終了した。しかし、全体のテストが完了と見なされるのは、最も遅いシャードが完了した時点であるため、結果的に8分36秒もの時間がかかってしまった。
- Pawdistによる動的分散: 最後に、2つのワーカー(各ワーカーで2つのテストを並行実行)にPawdistを適用してテストを実行した。Pawdistはマネージャーが管理する単一の作業キューからテストを動的に割り当てるため、特定のワーカーが長いテストを実行している間にも、他のワーカーは短いテストを次々と処理し、負荷をリアルタイムで分散する。その結果、全体のテストは6分5秒で完了した。これはベースラインの6分3秒とほぼ同じ時間であり、Playwrightの静的シャードで発生した大幅な時間延長を完全に解消している。
この比較結果は、Pawdistがもたらす効果を明確に示している。Pawdistの動的分散モデルに切り替えることで、次のような大きなメリットが得られる。テストスイート全体の実行時間が大幅に短縮され、最終的な完了時間は最も遅いシャードに左右されるのではなく、すべてのテストが効率的に完了する時間となる。CIランナーのリソースが最適な形で活用され、早くテストを終えたCIランナーが他のCIランナーの完了を待ってアイドル状態になることがなくなる。そして、テストの負荷がリアルタイムで均等に分散されるため、常に最大の効率でテストを実行できる。これにより、開発者はより迅速にテスト結果を受け取ることができ、開発サイクル全体のスピードアップに貢献するだろう。Pawdistは、Playwrightを使った大規模なテストスイートの実行時間を最適化し、CI/CD環境におけるリソースの利用効率を最大化するための強力なソリューションだと言える。