サイトアイコン 協栄情報ブログ

GitHub Actions での テスト実施 CI/CD ハンズオン

0.はじめに

前回GitHub Actions と Cloud Run で実現する CI/CD ハンズオンで、GitHubにマージすることで、自動的にCloudRunにデプロイされる仕組みを構築しました。

今回は、そちらに新しく テスト を組み込んで、マージしたらテストが実行され、問題ない場合は自動的にCloudRunにデプロイされる仕組みを構築したいと思います。

1.基本的な用語

1.1.テストについて

ソフトウェア開発における「テスト」とは、作成したコードが意図した通りに動作するかを確認する作業のことです。

自動化されたテストは、手作業に比べて高速かつ繰り返し正確に実行できるため、開発効率を高め、品質を均一に保つ上で非常に有効です。
そしてCI/CDパイプラインにおいては、この自動テストが重要な役割を果たします。

1.2.テストの種類

今回はテストの中でも 単体テスト(Unit Test)部分について実施をしていきます。

項番 テスト内容 テスト詳細
1 単体テスト(Unit Test) プログラムの最小単位(関数やメソッドなど)が正しく動作するかを確認するテスト
2 統合テスト(Integration Test) 複数のモジュールやコンポーネントを組み合わせたときに、正しく連携して動作するかを確認するテスト
3 システムテスト システム全体が仕様通りに機能するかを確認するテスト。すべてのコンポーネントを組み合わせた状態でテストする
4 運用テスト(Operation Test) 実際の運用環境に近い状態で、システム全体の動作やパフォーマンスを確認するテスト

1.3.利用ツール(pytest)について

Pythonで広く使われているテストフレームワークで、シンプルにテストを書くことが可能です。
特別な定型コードが少なく、Pythonの標準的な機能を使ってテスト関数を定義できます

2.ハンズオン

2.0.前提条件

2.1.ローカルでテスト実施

テスト対象のコードmain.py
Web画面を標示した際「Hello World!!!」が表示されることを正しいとする

# main.pyの内容
import functions_framework

@functions_framework.http
def hello_http(request):
    return "Hello World!!!"

# requirements.txtの内容
functions-framework==3.*

2.1.1.テストファイル作成

# Pythonアプリのテストファイルを作成
# test_main.py
cat > test_main.py << EOF
# テスト対象のファイルをインポート
import main

def test_hello_http():
    """
    hello_http関数が'Hello World!!!'を返すことを確認するテスト。
    このテストはAPIのグリーティングメッセージが正しいことを検証します。
    """
    # 引数をNone(無し)で hello_http関数を実際に呼び出し
    response = main.hello_http(None)
    # 関数の戻り値が"Hello World!!!"と等しい
    assert response == "Hello World!!!"
EOF

2.1.2.ライブラリインストール

# requirements-testファイルを作成
cat > requirements-test.txt << 'EOF'
pytest==7.*
EOF

# テスト用ライブラリインストール
pip install -r requirements-test.txt

2.1.3.テスト実施

# テスト実行
pytest

# 【レスポンス(一部省略)】
== test session starts ==
platform linux -- Python 3.12.3, pytest-7.4.4, pluggy-1.5.0
rootdir: /home/tetutetu/my-cloudrun-app
plugins: cov-4.1.0
collected 1 item

test_main.py .                   [100%]

== 1 passed in 0.30s ==

2.2.GitHub Actionsの準備

2.2.1.Workflows修正

#  GitHub Actionsワークフローファイルを作成
cat > .github/workflows/cloudrun-deploy.yml << 'EOF'
name: Build and Deploy to Cloud Run
 # masterブランチにプッシュされたタイミング
on:
  push:
    branches: [ master ]
# 環境変数
env:
  SERVICE_NAME: test-service
  REGION: asia-northeast1
# 実行する作業の定義
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    # コードを取得するステップ
    - name: Checkout code
      uses: actions/checkout@v4

### ここから 新規追加ステップ部分 ###
    # GitHubでの仮想マシン(ランナー)のPythonセットアップ
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.12'

    # 依存関係のインストール
    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
        pip install -r requirements-test.txt

    # テストを実行するステップ
    - name: Run tests
      run: |
        pytest
### ここまで 新規追加ステップ部分 ###

    # Google 認証のステップ
    - name: Authenticate to Google Cloud
      if: success()  # テストが成功した場合のみ実行
      uses: google-github-actions/auth@v2
      with:
        credentials_json: ${{ secrets.GCP_SA_KEY }}
        project_id: ${{ secrets.GCP_PROJECT_ID }}

    # SDKによるコマンドを利用できるようにするステップ
    - name: Set up Cloud SDK
      if: success()  # テストが成功した場合のみ実行
      uses: google-github-actions/setup-gcloud@v2
      with:
        project_id: ${{ secrets.GCP_PROJECT_ID }}

    # デバッグ認証ステップ
    - name: Debug Authentication
      if: success()  # テストが成功した場合のみ実行
      run: |
        echo "Current project: $(gcloud config get-value project)"
        echo "Current account: $(gcloud auth list --filter=status:ACTIVE --format='value(account)')"

    # Cloud Runにデプロイ (テストが成功した場合のみ)
    - name: Deploy to Cloud Run
      if: success()  # テストが成功した場合のみ実行
      run: |
        gcloud config set project ${{ secrets.GCP_PROJECT_ID }}
        gcloud run deploy ${{ env.SERVICE_NAME }} \
          --source . \
          --project ${{ secrets.GCP_PROJECT_ID }} \
          --platform managed \
          --region ${{ env.REGION }} \
          --allow-unauthenticated
EOF

2.2.2.ファイルをコミットしてプッシュ

# ファイルをコミットしてプッシュ
git add .
git commit -m "Update Workflowsyaml"
git push

2.3.push後の確認

2.3.1.GitHubでの画面

項番 手順名 内容
1 Set up Python テスト(Python)環境をセットアップするステップ
2 Install dependencies テストに必要なライブラリをインストールするステップ
3 Run tests pytestコマンドを実行
4 Post Set up Python 環境のクリーンアップ

2.3.2.希望した内容と異なる(失敗)結果になった場合の画面(ローカル)

# テスト実行
pytest

# 【レスポンス(一部省略)】
== test session starts ==
platform linux -- Python 3.12.3, pytest-7.4.4, pluggy-1.5.0
rootdir: /home/lemoned_i_scream_art_of_noise/20250427_my-cloudrun-app
plugins: cov-4.1.0
collected 1 item
test_main.py F   [100%]

== FAILURES ==
__ test_hello_http __
    def test_hello_http():
        """
        hello_http関数が'Hello World!!!'を返すことを確認するテスト。
        このテストはAPIのグリーティングメッセージが正しいことを検証します。
        """
        # 引数をNone(無し)で hello_http関数を実際に呼び出し
        response = main.hello_http(None)
        # 関数の戻り値が"Hello World!!!"と等しい
>       assert response == "Hello World!!!"
E       AssertionError: assert 'Hello World' == 'Hello World!!!'
E         - Hello World!!!
E         ?            ---
E         + Hello World

test_main.py:12: AssertionError
== short test summary info ==
FAILED test_main.py::test_hello_http - AssertionError: assert 'Hello World' == 'Hello World!!!'
== 1 failed in 0.22s ==

2.3.3.希望した内容と異なる(失敗)結果になった場合の画面(GitHub)

3.おわりに

3.1.得られた知見

3.2.今後の課題

モバイルバージョンを終了