0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【ハンズオン】手動QAが未経験から Flask + pytest + GitHub Actions で API 自動テスト(CI)を構築するまで

0
Posted at

1. はじめに

手動QAとしての経験を活かしつつ、Web APIの自動テスト(pytest)とCI環境(GitHub Actions)の構築を一通り自力で体験してみました。

この記事では、「APIの簡易実装」から「テストコード記述」「GitHub Actionsでの自動化」までの全手順に加え、開発環境構築の段階で実際に自分がつまずいたリアルなエラーと解決策をまとめています。

同じようにテスト自動化(SETE / QAエンジニア)を目指している方の参考になれば幸いです!


2. 構成・使用技術

  • 言語・フレームワーク: Python 3.12, Flask
  • テストツール: pytest
  • 環境構築: venv
  • エディタ: VS Code
  • バージョン管理・CI: Git, GitHub, GitHub Actions

3. ハンズオン手順

Step 1: 作業フォルダの作成とVS Codeの起動

ターミナルから作業フォルダを作成し、VS Codeを起動します。

# フォルダの作成と移動
mkdir api-test-demo
cd api-test-demo

# 今いるフォルダをVS Codeで直接開く
code .

(※ code . で別ウィンドウが開きますが、code -r . を使うと同ウィンドウ内で開くことも可能です)


Step 2: 仮想環境(venv)の作成とツールの準備

Pythonの環境を汚さないよう、プロジェクト専用の仮想環境を作ります。

# 1. 仮想環境(専用の部屋)を作成
python3 -m venv venv

# 2. 仮想環境を有効化(Mac / zsh の場合)
source venv/bin/activate
# ※成功するとターミナルの行頭に (venv) と表示されます

# 3. 必要なパッケージをインストール
pip install flask pytest


Step 3: API本体とテストコードの実装

venv フォルダと同じ階層(プロジェクト直下)に以下の2ファイルを作成します。

① app.py(タスク管理API)

新規タスク作成(POST)とステータス更新(PATCH)を行うシンプルなAPIです。

from flask import Flask, jsonify, request

app = Flask(__name__)

tasks = []
task_id_counter = 1


@app.route("/tasks", methods=["POST"])
def create_task():
    global task_id_counter
    data = request.get_json() or {}

    title = data.get("title", "").strip()
    if not title:
        return jsonify({"error": "タイトルは必須です"}), 400

    new_task = {
        "id": task_id_counter,
        "title": title,
        "status": "未着手",
    }
    tasks.append(new_task)
    task_id_counter += 1

    return jsonify(new_task), 201


@app.route("/tasks/<int:task_id>/status", methods=["PATCH"])
def update_task_status(task_id):
    data = request.get_json() or {}
    new_status = data.get("status")

    allowed_statuses = ["未着手", "進行中", "完了"]
    if new_status not in allowed_statuses:
        return jsonify({"error": "無効なステータスです"}), 400

    for task in tasks:
        if task["id"] == task_id:
            task["status"] = new_status
            return jsonify(task), 200

    return jsonify({"error": "タスクが存在しません"}), 404

② test_app.py(自動テストコード)

QA観点を含めた正常系・異常系計5ケースのテストです。

import pytest
from app import app, tasks


@pytest.fixture
def client():
    app.config["TESTING"] = True
    tasks.clear()
    with app.test_client() as client:
        yield client


# ① 正常系:タスク作成
def test_create_task_success(client):
    response = client.post("/tasks", json={"title": "pytestをマスターする"})
    assert response.status_code == 201
    assert response.get_json()["title"] == "pytestをマスターする"


# ② 異常系(QA観点):タイトルが空のとき
def test_create_task_empty_title(client):
    response = client.post("/tasks", json={"title": "   "})
    assert response.status_code == 400
    assert response.get_json()["error"] == "タイトルは必須です"


# ③ 正常系:ステータス更新
def test_update_status_success(client):
    create_res = client.post("/tasks", json={"title": "テスト用タスク"})
    task_id = create_res.get_json()["id"]

    update_res = client.patch(
        f"/tasks/{task_id}/status", json={"status": "進行中"}
    )
    assert update_res.status_code == 200
    assert update_res.get_json()["status"] == "進行中"


# ④ 異常系(QA観点):無効なステータス
def test_update_status_invalid_value(client):
    create_res = client.post("/tasks", json={"title": "テスト用タスク"})
    task_id = create_res.get_json()["id"]

    update_res = client.patch(
        f"/tasks/{task_id}/status", json={"status": "保留"}
    )
    assert update_res.status_code == 400


# ⑤ 異常系(QA観点):存在しないタスクID
def test_update_status_not_found(client):
    update_res = client.patch("/tasks/999/status", json={"status": "完了"})
    assert update_res.status_code == 404


Step 4: ローカルでのテスト実行

ターミナルで pytest を実行します。

python3 -m pytest test_app.py

全5ケースが合格すると 5 passed と表示されます。


Step 5: Git管理とGitHubへのプッシュ

容量の大きい仮想環境(venv)を送信除外にするため、.gitignore を作成します。

  1. .gitignore の作成
venv/
__pycache__/
.pytest_cache/

  1. Gitの初期化とローカルコミット
git init
git add .
git commit -m "Initial commit: Task management API and tests"

  1. GitHubへプッシュ
git branch -M main
git remote add origin [https://github.com/](https://github.com/)<自身のユーザー名>/api-test-demo.git
git push -u origin main


Step 6: GitHub Actions(CI)の設定

.github/workflows/test.yml を作成し、プッシュ時に自動テストが回るように設定します。

name: Run Pytest

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install flask pytest

      - name: Run tests with pytest
        run: |
          pytest test_app.py

作成したらコミットしてGitHubへ送信します。

git add .github/workflows/test.yml
git commit -m "Add GitHub Actions workflow"
git push

GitHub上の Actions タブで実行状況を確認し、緑色のチェックマーク(✅ Passed) になれば構築完了です!


4. 実際にハマったポイント・エラーと解決策 ⚠️

個人的に一番勉強になった「実際につまずいたポイント」と「原因・解決策」のまとめです。

① command not found: code と出でVS Codeが開かない

  • 原因: ターミナルから code コマンドを呼び出すためのPATH設定がされていなかった。
  • 解決策:
  1. VS Codeで Cmd + Shift + P を押し、コマンドパレットを開く。
  2. shell command と入力し、「シェル コマンド: PATH 内に 'code' コマンドをインストールします」 を選択・実行。
  3. (※誤ってアンインストールを選択してしまった場合は、全く同じ手順で再度「インストール」を選択し直せば復旧します)

② pytest 実行時に ImportError: cannot import name 'app' from 'app'

  • 原因: VS Codeでコードを貼り付けた後、保存(Cmd + S)が実行されていなかった ため、ディスク上のファイルの中身が空(未保存)の状態だった。
  • 解決策:
  • Cmd + S を明確に押して保存する(タブの丸い点 ● が消えたことを確認)。
  • 根本対策: VS Codeの設定(Cmd + ,)から files.autoSave を afterDelay 等に変更し、自動保存を有効化するとミスを防げます。

③ ファイルの配置場所ミス(venv フォルダ内への格納)

  • 原因: app.py や test_app.py を誤って venv/ フォルダの中に作成してしまい、Pythonのインポートパスから外れていた。
  • 解決策: ソースコードやテストコードは、必ず venv/ フォルダと同じ階層(プロジェクト直下)に配置する。

④ GitHub Actionsで Error: No event triggers defined in 'on'

  • 原因: test.yml(YAML形式)のインデント(スペース)や構文が崩れていたため、GitHub側でイベント(起動トリガー)として認識されなかった。
  • 解決策: YAML形式はスペースの数やネスト構造に非常に厳密なため、インデントを見直して修正後に再プッシュする。

5. おわりに

手動QAで培った「どんなケースをテストすべきか(正常系・異常系・境界値)」という視点は、コードに落とし込む際にも強力な武器になると実感しました。

ローカルでのテスト実行だけでなく、GitHub Actionsで自動化(CI環境構築)まで繋げられたことで、開発から品質保証までの全体像を一気に掴むことができました!

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?