Open4

分散システムの E2E テストを並列化して CI を高速化して実行時間を 1/7 にした

voluntasvoluntas

概要

自社製品の E2E テストは Python (pytest) を利用しているが、実行にかなりの時間がかかっており、E2E テストを流している間に他の事をやっていた。

しかし、最近 GitHub Enterprise を契約してことで、GitHub Actions のプランに含まれる時間が 3000 分から 50000 分に増えたため、せっかくだし力業でなんとかすることにした。

つまり、お金で解決した。

voluntasvoluntas

前提

  • 設定方法は GitHub Copilot Chat が全て教えてくれた
    • ドキュメントも読んでない
  • 自社製品はパッケージ製品かつ分散システムである
  • 製品は Erlang/OTP で書かれている
  • 音声や映像をリアルタイムに扱う製品である
  • 今は pytest を利用して test_*.py というファイルを順々にテストしている
    • グルーピングはしていない
  • 分散システムを起動しての E2E テストなので、同一環境で並列テストはかなりめんどくさい
    • あまりそこは頑張りたくなかった
  • E2E テストはタイムアウトなども含まれるため遅くなりがち

pytest 並列化

  • 1 コンテナ 1 テストが理想なので strategymatrix を利用して無理矢理並列化することにした
  • まず test_*.py 一覧を取得して matrix に突っ込む
  • matrix を使って pytest を実行する

以下は色々省略した GitHub Actions の YAML

jobs:
  prepare_e2e_test_files:
    runs-on: ubuntu-latest
    outputs:
      e2e_test_files: ${{ steps.set-e2e-test-files.outputs.e2e_test_files }}
    steps:
      - uses: actions/checkout@v4
      - id: set-e2e-test-files
        # test-e2e 以下の test_*.py ファイルを取得して matrix にセットする
        run: |
          E2E_TEST_FILES=$(find . -name "test_*.py" | jq -R -s -c 'split("\n")[:-1]')
          echo "e2e_test_files=${E2E_TEST_FILES}" >> $GITHUB_OUTPUT
  e2e_test:
    needs: [prepare_e2e_test_files]
    runs-on: ubuntu-latest
    strategy:
      matrix:
        e2e_test: ${{fromJson(needs.prepare_e2e_test_files.outputs.e2e_test_files)}}
      - run: rye run pytest ${{ matrix.e2e_test }}
      - uses: eifinger/setup-rye@v3
        with:
          version: 'latest'
      - run: rye sync
      - run: rye run pytest ${{ matrix.e2e_test }}
voluntasvoluntas

まとめ

CI 実行時間が短いのは素晴らしい

  • E2E テストの実行時間が 1/7 になった
    • この並列化以外にも頑張ってるがそこは割愛
  • ユニットテストとほぼ変わらない速度になった
  • 今後どれだけ E2E テストを追加しても、その E2E テスト自体が遅く無い限りは実行時間が増えなくなった
  • 恐ろしい速度で GitHub Acitons の利用時間が減っていく
    • 50000 分過ぎても、この速度はお金を払ってでも維持するべきだと思えるくらいのメリット

おまけ

  • プロパティテストも並列化したら快適になった