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サービスの開発エンジニアを募集しています!
社員・フリーランスに関わらず、参画後に安心してご活躍できることを目指し、応募された方の特性・ご希望にマッチしたチームをご紹介します。
ちょっと話を聞いてみたい、ぜひ応募したい、など、当社にご興味を持っていただけましたら、お気軽にエントリーください!!