PythonでLambdaを書いているとき、pytestを利用してUnit TestやAPIに対するE2Eテストを実施しています。 Lambdaが多くなるほど、実施するテストも増えます。 実施するテストが増えると、1回あたりのCI/CDの稼働時間も増えます。
このCI/CDの稼働時間を減らすために、差分があるLambdaのテストだけを実施する仕組みを考えてみました。 (ALLのテストはデイリーで実施する想定です。)
おすすめの方
- pytestでgit diffの差分があるファイルだけをテストしてみたい方
前提
次のフォルダ構成とします。「handlers/xxx」とペアになるe2eテストファイルがあります。
├── src
│ └── handlers
│ ├── xxx
│ │ └── app.py
│ └── yyy
│ └── app.py
└── tests
└── e2e
├── test_xxx.py
└── test_yyy.py
まずは、普通にE2E Testを実行する
Pythonコード(src)
用意はしますが、ダミーです。
src/handlers/xxx/app.py
src/handlers/xxx/app.py
def message():
return "this is xxx/app.py"
src/handlers/yyy/app.py
src/handlers/yyy/app.py
def message():
return "this is yyy/app.py"
Pythonコード(e2e test)
実際はデプロイしたAPIのエンドポイントなどを叩く想定ですが、ここでは「assert True」としておきます。
tests/e2e/test_xxx.py
tests/e2e/test_xxx.py
def test_message():
assert True
tests/e2e/test_yyy.py
tests/e2e/test_yyy.py
def test_message():
assert True
E2E Testを実行する
次のコマンドで実行すると、2つのE2E Testが実行されます。(結果は一部抜粋しています)
pytest tests/e2e
collected 2 items
tests/e2e/test_xxx.py . [ 50%]
tests/e2e/test_yyy.py . [100%]
============================== 2 passed in 0.01s ===============================
git diffで差分のあるファイルだけテストする
テスト用のスクリプト
git diffで「src/handlers配下」と「tests/e2e配下」の差分ファイル名を取得し、テストファイルを特定し、重複を削除して、pytestを実行します。 スクリプト力が高くないので散らかってますが……。
unit-test-diff.sh
#!/bin/bash
git diff main --name-only
echo ---
# src/handlers配下の差分ファイル名を取得する
src_files=$(git diff main --name-only | grep "^src/handlers/.*\.py$")
# 対応するテストファイル名を取得する
src_test_files=$(for file in $src_files; do echo $file | sed -E 's|src/handlers/([^/]+)/([^/]+\.py)$|tests/e2e/test_\1.py|'; done)
# tests/e2e配下の差分ファイル名を取得する
e2e_test_files=$(git diff main --name-only | grep "^tests/e2e/.*\.py$")
# 重複を削除する
target_files=$((echo $src_test_files; echo $e2e_test_files) | tr ' ' '\n' | sort -u)
# テストファイルがない場合は終了する
if [ -z "$target_files" ]; then
echo "No test files"
exit 0
fi
pytest $target_files
テストを実行する
diffなし
- src/handlers/xxx/app.py: 差分なし
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分なし
- tests/e2e/test_yyy.py: 差分なし
No test files
diffあり(src配下)
- src/handlers/xxx/app.py: 差分あり
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分なし
- tests/e2e/test_yyy.py: 差分なし
collected 1 item
tests/e2e/test_xxx.py . [100%]
diffあり(src配下)
- src/handlers/xxx/app.py: 差分なし
- src/handlers/yyy/app.py: 差分あり
- tests/e2e/test_xxx.py: 差分なし
- tests/e2e/test_yyy.py: 差分なし
collected 1 item
tests/e2e/test_yyy.py . [100%]
diffあり(src配下)
- src/handlers/xxx/app.py: 差分あり
- src/handlers/yyy/app.py: 差分あり
- tests/e2e/test_xxx.py: 差分なし
- tests/e2e/test_yyy.py: 差分なし
collected 2 items
tests/e2e/test_xxx.py . [ 50%]
tests/e2e/test_yyy.py . [100%]
diffあり(tests配下)
- src/handlers/xxx/app.py: 差分なし
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分あり
- tests/e2e/test_yyy.py: 差分なし
collected 1 item
tests/e2e/test_xxx.py . [100%]
diffあり(tests配下)
- src/handlers/xxx/app.py: 差分なし
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分なし
- tests/e2e/test_yyy.py: 差分あり
collected 1 item
tests/e2e/test_yyy.py . [100%]
diffあり(tests配下)
- src/handlers/xxx/app.py: 差分なし
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分あり
- tests/e2e/test_yyy.py: 差分あり
collected 2 items
tests/e2e/test_xxx.py . [ 50%]
tests/e2e/test_yyy.py . [100%]
diffあり(src&tests配下)
- src/handlers/xxx/app.py: 差分あり
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分あり
- tests/e2e/test_yyy.py: 差分なし
collected 1 item
tests/e2e/test_xxx.py . [100%]
diffあり(src&tests配下)
- src/handlers/xxx/app.py: 差分あり
- src/handlers/yyy/app.py: 差分なし
- tests/e2e/test_xxx.py: 差分なし
- tests/e2e/test_yyy.py: 差分あり
collected 2 items
tests/e2e/test_xxx.py . [ 50%]
tests/e2e/test_yyy.py . [100%]
diffあり(src&tests配下)
- src/handlers/xxx/app.py: 差分あり
- src/handlers/yyy/app.py: 差分あり
- tests/e2e/test_xxx.py: 差分あり
- tests/e2e/test_yyy.py: 差分あり
collected 2 items
tests/e2e/test_xxx.py . [ 50%]
tests/e2e/test_yyy.py . [100%]
さいごに
git diffコマンドで差分があるファイルのテストを実行してみました。 命名の前提があったりで小回りは効きませんが、ここからカスタマイズしてみるのも良いですね。