見出し画像

GitHub Actions で Python アプリの自動テストを設定する

こんにちは。株式会社レスキューナウで基幹システムの開発を担当している衣笠です。今回は、Pythonアプリのプルリクエスト時に「GitHub Actions でユニットテスト (pytest) を実行させ、テスト結果をコメントする」までを自動で行う方法をご紹介します。
現在ローカル環境で pytest を手動実行している方や、CI (継続的インテグレーション) ツールを Jenkins から GitHub Actions へ移行させたいと検討している方の参考になれば幸いです。

ワークフローの設定

すでに pytest のテストコードやテストツールを準備されているのであれば、GitHub Actions にワークフローを作成するだけで、簡単に自動テストを設定することができます。

早速ですが、以下の設定ファイルをご覧ください。この例では実行トリガーを pull_request にして、プルリクエスト時に自動テストが走るようにしていますが、トリガーをプッシュにしたり、特定のブランチに対してだけに制限することも可能です。

name: Pytest

on:
  - pull_request

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      # リポジトリをチェックアウト
      - uses: actions/checkout@v2 

      # データベース起動
      - name: Start mongoDB
        run: docker-compose -f ./docker/githubactions/docker-compose.yml up -d --build

      # Pythonセットアップ
      - name: Set up Python 3.6.8
        uses: actions/setup-python@v2
        with:
          python-version: "3.6.8"
          
      # ライブラリインストール
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
      
      # mongoDBにコレクションインポート
      - name: Import collections
        run: docker container exec mongodb /initdata/import_collections.sh

      # ユニットテスト実行
      - name: Run tests
        env:
          PROJECT_HOME: /home/runner/work/repository_name/repository_name
          PYTHONPATH: /home/runner/work/repository_name/repository_name/app
        run: |
          pytest test --cov=app --cov-report=term-missing --junitxml=pytest.xml | tee pytest-coverage.txt
        continue-on-error: true
  
      # テスト結果をプルリクにコメントする
      - name: Pytest coverage comment
        uses: MishaKav/pytest-coverage-comment@main
        with:
          pytest-coverage-path: ./pytest-coverage.txt
          junitxml-path: ./pytest.xml

各ステップの解説

リポジトリのチェックアウト
特に指定しなければ、/home/runner/work/{repository名}/{repository名} にチェックアウトされます。

データベース起動
アプリケーションがデータベースに接続する場合は、ワークフロー内でデータベースの Docker コンテナを起動させることで、問題なくテストができます。Docker で構築できるデータベースであれば何でも利用可能ですが、MongoDB を使用される場合は、以前の記事を参考にしていただければと思います。

データベースの起動には時間が掛かるため、リポジトリのチェックアウト後すぐに実行するようにしています。このとき、docker-compose up に "-d" を付けてバックグラウンドで実行するようにしないと、ワークフローが次のステップに進まないのでご注意ください。

Pythonセットアップ
Pythonのバージョンを指定します。

ライブラリインストール
アプリケーションに必要なライブラリに加えて、ユニットテストに必要なライブラリもインストールします。テスト内容にもよりますが、pytest、pytest-cov、pytest-freezegun、mockあたりが必要になります。

起動したMongoDBにコレクションをインポート
いよいよ次のステップでテストを実行するので、データベースのセットアップを完了させます。今回の例では、起動させたMongoDBにコレクションをインポートするため、コマンドを記述したスクリプトを実行しています。スクリプトの内容は、以前の記事内の import_collections.sh の解説をご覧ください。

ユニットテスト実行
まずは環境変数を設定します。PROJECT_HOME にはリポジトリのパスを、PYTHONPATH にはテスト対象のディレクトリのパスを設定します。pytest 実行コマンドには、以下のようなオプションを付けています。

pytest test --cov=app --cov-report=term-missing --junitxml=pytest.xml | tee pytest-coverage.txt

オプションの内容は、
・カバレッジを計算する対象をappディレクトリに指定する
・カバレッジレポートの内容は、網羅されなかった行番号にする
・テスト結果を JUnit XML形式で pytest.xml に出力する
・カバレッジレポートを pytest-coverage.txt に出力する

テスト結果をプルリクにコメントする
pytest の結果を表示するアクションを GitHub の Marketplace で検索するといくつか出てきますが、その中でも設定方法が簡単で結果の確認がしやすいと感じた "Pytest Coverage Comment" を利用させていただいています。こちらのアクションを利用すれば、テスト結果がプルリクエストの Conversation にコメントとして表示されます。

pytest コマンド実行時に設定したカバレッジレポートファイルのパスを pytest-coverage-path に、JUnit XMLファイルのパスを junitxml-path に設定します。

実際に試してみる

ワークフローの設定は以上になります。実際にプルリクエストを出してみるとすぐにワークフローが走りだし、実行状況は GitHub のPull requests の Checks で確認することができます。

ワークフローが正常に終了した後、Conversation を確認すると、以下のようなコメントが追加されています。

実行したテスト数とエラーの数、カバレッジ率などが一目で確認できます。テスト結果の詳細を見たい場合は、Coverage Report をクリックすると、ファイル名と網羅されていない行番号が一覧表示されます。

テスト結果がコメントに表示されると、レビュワーにとっても結果の確認がしやすく、便利だと思います。ワークフローの設定は簡単なので是非一度お試しいただけたらと思います。(※無料枠を使い切っている場合、ワークフローの実行時間に応じて課金されますのでご注意ください。)
最後までご覧いただき、ありがとうございました。

最後に

現在、レスキューナウでは、災害情報の提供、災害情報を活用した安否確認サービスなどのWebサービスの開発エンジニアを募集しています!
社員・フリーランスに関わらず、参画後に安心してご活躍できることを目指し、応募された方の特性・ご希望にマッチしたチームをご紹介します。
ちょっと話を聞いてみたい、ぜひ応募したい、など、当社にご興味を持っていただけましたら、お気軽にエントリーください!!