コンテンツにスキップ

Pants Test の Coverage 対象のファイルを filter する

背景

Pants のテストでカバレッジの対象を変更ファイルのあるディレクトリに絞る方法を紹介します。--coverage-py-filterの指定例と、GitHub Actions で変更のあったファイルのディレクトリを取得し、自動設定する手順を示します。

Pants Test の Coverage は、対象ファイルが推移的に依存するファイルまでカバレッジ対象に含めてしまいます。

テストコードが推移的な依存ファイルの一部のクラスや関数だけを使う場合、テストのカバレッジは低くなってしまいます。推移的な依存ファイルをなるべく除外し、変更したソースファイルを含むディレクトリに対象を絞れば、変更箇所に近い範囲のカバレッジを把握しやすいと考えました。

解決策

Pants Test では、Coverage 対象のファイルを--coverage-py-filterオプションで絞り込めます。

filter sample
pants test --coverage-py-filter='["foo_dir", "foo_dir/bar_dir"]'

上記の場合、カバレッジの対象はfoo_dirとfoo_dir/bar_dir内のファイルです。ディレクトリ単位の指定なので、同じディレクトリ内の未変更ファイルも含まれます。変更ファイルだけを厳密に選ぶ方法とは範囲が異なります。

GitHub Actions と連携した filter の自動設定

変更ファイルを含むディレクトリを filter に指定し、その外にある依存ファイルをカバレッジ対象から外します。GitHub Actions 上では、次の手順で filter を設定します。

  1. 変更があったファイルのディレクトリのみを取得する(dirnameを使うのは、filter にはディレクトリを指定する必要があるため)
  2. 取得したディレクトリを${{ env.PANTS_COVERAGE_PY_FILTER }}に設定する
  3. pants testの実行時に、${{ env.PANTS_COVERAGE_PY_FILTER }}を filter として指定する
filter
1
2
3
4
# coverageの対象となる変更のあったソースファイルを指定する。
filter=$(pants --changed-since=origin/main --changed-dependents=transitive --filter-target-type=python_source peek | jq '.[].sources[]' | xargs dirname | sed ':a;N;$!ba;s/\n/","/g' | sed 's/^/"/;s/$/"/')
echo "PANTS_COVERAGE_PY_FILTER='[${filter}]'" >> $GITHUB_ENV
PANTS_COVERAGE_PY_FILTER=${{ env.PANTS_COVERAGE_PY_FILTER }} pants --changed-since=origin/main --changed-dependents=transitive test

シェル展開から環境変数への切り替え

pants testの実行時に filter を指定する方法として、最初は shell の${filter}で直接展開する方法を試しましたが、動きませんでした。そこで、GitHub Actionsの環境変数を設定する仕組みを使い、GITHUB_ENVが指すファイルへ値を書き込む方法に切り替えています。