4
2

More than 1 year has passed since last update.

GitHub Actionsでpytestしてカバレッジを出す

Last updated at Posted at 2023-04-20

個人的備忘録。

やること

  • Github Actionsでpytestを動かして単体テストする。
    • 動作タイミングはpull requestのopen時と、pull requestがopenされたブランチへのpush時
    • 外部APIを叩くテストケースはスキップすることにした
  • pytest-covでカバレッジを出して、pull requestのコメントとして投稿する。

Github Actionsの設定

pytest.yaml
name: Pytest

on:
  pull_request:
    types: [opened, reopened, synchronize]
  
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - uses: actions/setup-python@v4
        with:
          python-version: '3.10' 
          cache: 'pip'

      - name: Install dependencies
        run: pip install -r devel-requirements.txt
      
      - name: run pytest
        run: |
          set -o pipefail
          python -m pytest --junitxml=pytest.xml --cov-report=term-missing --cov=src tests/ | tee pytest-coverage.txt

      - name: Pytest coverage comment
        uses: MishaKav/pytest-coverage-comment@v1.1.47
        with:
          pytest-coverage-path: ./pytest-coverage.txt
          junitxml-path: ./pytest.xml

以下に補足していきます。

pull requestのopen時と更新時に動作させる

on:
  pull_request:
    types: [opened, reopened, synchronize]

pull requestがopenされているブランチへのpushイベントで動かしたい時は、synchronizeを指定します。

カバレッジを取得する

      - name: run pytest
        run: |
          set -o pipefail
          python -m pytest --junitxml=pytest.xml --cov-report=term-missing --cov=src tests/ | tee pytest-coverage.txt

pytest-coverage-commentの公式例とほぼ同じですが、パイプを使う場合、pipefailの設定をしないとパイプ後半の戻り値で成功・失敗を判断することになるので、単体テストが失敗していてもCIが通ってしまいます。
そこで、set -o pipefailを設定しています。

pull requestのコメントとして投稿する

      - name: Pytest coverage comment
        uses: MishaKav/pytest-coverage-comment@v1.1.47
        with:
          pytest-coverage-path: ./pytest-coverage.txt
          junitxml-path: ./pytest.xml

このような感じでコメントしてくれます。
pytest-cov-comment.png

--cov-reportterm-missingを指定するとテストされていない行を表示してくれます。

GitHub Actionsでの実行時にはskipするテストケースを設定する

GITHUB_ACTION環境変数が設定されるのを利用して、GitHub Actionsでの実行時にskipします。

@pytest.mark.skipif('GITHUB_ACTION' in os.environ, reason="skip external api call during CI")
def test_foobar():
    # GitHub Actionsではskipされるテストケース
    pass

参考:

ハマりどころ

srcのサブディレクトリにある.pyファイルに関して、テストはされるのですがcoverage reportに入らないというトラブルがありました。

調べてみると、pytest-covはサブディレクトリに__init__.pyがないとそこで探索をやめてしまうという動作になっているようでした。

そこで、srcのサブディレクトリにそれぞれ空の__init__.pyを作成したところ、うまく動作しました。

TODO

READMEにカバレッジのバッジをつけたい。

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2