フロントエンドのテスト用に Webサーバ を起動するときには PM2 を使うのもあり

PM2 とは

  • PM2 is a daemon process manager
    • Process Manager

pm2.keymetrics.io

理由

  • メジャーな OSS であり、信頼でき、メンテも続くだろう
    • Webサーバ の起動、停止、削除というだけに限らず、汎用的なので、応用範囲が広い
  • 同期的な処理にできるので、サーバが起動しない前にテストが走って落ちてしまうということがない
    • Cypress 公式では start-server-and-test が紹介されていたり、Vue Test Utils でもなにか紹介されていた*1と思うが、これらは非同期でサーバを起動する*2ので、サーバ起動よりも早くテストが実行されることがある
      • ローカルの超早マシンだと落ち、CI だと通る、みたいな Flaky な悩みどころを生んでしまい、体験的に良くない
  • ローカルでも CI でも同じコマンド(の流れ)で使える

    • CI だとサーバ起動しっぱなしでもいいが、ローカルだと起動したままテストが落ちる場合なども考慮する必要がある
      • pm2 なら自分で命名した名前に対して冪等に kill できるので、ローカルでも CI でも同じコマンドで "scripts" に定義できる
  • SSG ならば http-server を Webサーバ として用い、PM2 で管理するといい

具体例

Next.js で SSG を採用する場合の E2Eテスト を Cypress で行う場合、次のようにして ローカル実行 と CI (GitHub Actions) での実行で共通化できています*3

{
  "scripts": {
    "test:e2e": "npx --yes pm2 delete my_product_e2e_test 2> /dev/null & yarn build && npx pm2 start 'npx --yes http-server out/ -p 3000' --name my_product_e2e_test && yarn cypress:run && npx --yes pm2 delete my_product_e2e_test",
  }
}

最初にも $ pm2 delete している理由は、ローカルのテスト実行で落ちたときにサーバが起動しっぱなしになっていることを考慮しているからです。最初に $ pm2 delete するように書いておけば冪等にできます。

なお、もしサーバが起動していないにも関わらず $ pm2 delete するとエラーになる*4 ので、その対策として 2> /dev/null したり、コマンドの連結を & で行ったりしています。

*1:忘れてしまった

*2:はず

*3:少々書き方がくどいですが、分割しなくていいぎりぎりの線だと思います

*4:exit 1 になる

Powered by はてなブログ