ExcelベースのAPIテストフレームワークの設計と進化

Excelファイルを用いたAPIテストフレームワークの実装アプローチを、バージョンアップごとに紹介する。各バージョンでは機能拡張や設計改善が行われており、最終的にはPytestと統合された柔軟なテストシステムへと発展している。

基本データフォーマット(schema1)

テストケースはExcelファイル(例: data.xlsx)に以下の列で定義される:

  • name: テストケース名
  • method: HTTPメソッド(大文字小文字不問)
  • url: 完全なURL(クエリパラメータ含む)
  • data: 生データ(raw data)。Content-Typeはheadersで指定必須
  • headers: 改行区切りのキー:値ペア(例: Content-Type: application/json
  • verify: Python式による検証ロジック(resはrequests.Responseオブジェクト)
  • result: 実行結果(PASS/FAIL/ERROR)

サポートされるデータ形式:

  • フォームデータ:name=Kevin&age=1 + Content-Type: application/x-www-form-urlencoded
  • JSON:{"key":"value"} + Content-Type: application/json
  • XMLなど:適切なContent-Typeを指定

v1.0:シンプルなループ実行

最初の実装は関数ベースで、Excelを読み込んで各行を順次実行する。主な処理フロー:

  1. ヘッダーを辞書に変換
  2. データをUTF-8バイト列にエンコード
  3. requestsでリクエスト送信
  4. verify式をeval()で評価し、assertで検証
  5. 例外ハンドリングで結果を分類(AssertError→FAIL、その他→ERROR)
import openpyxl
import requests

def execute_test_cases(file_path):
    workbook = openpyxl.load_workbook(file_path)
    worksheet = workbook.active
    session = requests.Session()
    
    for row_idx, row_data in enumerate(worksheet.iter_rows(values_only=True), start=1):
        if row_idx == 1:  # ヘッダー行をスキップ
            continue
            
        case_name, method, url, payload, headers_str, assertions, *_ = row_data
        headers = {}
        if headers_str:
            headers = dict(line.split(':', 1) for line in headers_str.split('\n') if ':' in line)
            
        body = payload.encode('utf-8') if payload else None
        
        try:
            response = session.request(method, url, data=body, headers=headers)
            status = 'PASS'
            
            if assertions:
                for expr in assertions.split('\n'):
                    if expr.strip():
                        try:
                            assert eval(expr.strip())
                        except AssertionError:
                            status = 'FAIL'
                            break
                        except Exception:
                            status = 'ERROR'
                            break
                            
        except Exception:
            status = 'ERROR'
            
        worksheet.cell(row=row_idx, column=7, value=status)
        
    workbook.save(file_path)

v1.1:オブジェクト指向リファクタリング

2つのクラスで構成:

  • TestCase:1行のテストデータをカプセル化し、実行ロジックを内包
  • Runner:Excelファイルをロードしてテストケース群を管理・実行

v1.2:Pytest統合

Pytestのカスタムコレクターを実装し、Excelファイルをテストソースとして認識させる:

  • pytest_collect_file:.xlsxファイルを収集
  • ExcelFile:ファイルレベルのコレクター
  • ExcelTest:各行を個別のテストアイテムとして実行

これにより、標準的なPytestレポートや並列実行などの機能を利用可能に。

v1.3:変数抽出と連携機能

新しいregister列を追加し、前ステップのレスポンスから値を抽出して後続テストで再利用可能に:

  • グローバルコンテキスト辞書で変数を管理
  • string.Template$variable形式の置換をサポート
  • requestsのhooksでレスポンス後の処理(抽出→検証)をチェーン

v1.4:堅牢性向上とデータバリデーション

主要な改善点:

  • カスタム例外クラスでエラー分類(DataError, ConfigMissing等)
  • JSON5ライブラリによる柔軟なJSON解析
  • HTTPメソッド・データタイプの厳密なバリデーション
  • ファイルアップロード対応(FILE:path形式)

v2.0:マルチステップテスト対応

1つのテストケースが複数のリクエスト手順を持つことをサポート:

  • Excelでname列が空の行を同一ケースの継続ステップとみなす
  • ChainMapで環境変数とテスト変数を統合管理
  • pytest-base-urlプラグインとの連携でベースURLを外部から注入

実行例:

CRM_USER=user CRM_PASSWORD=pass pytest --base-url=https://api.example.com -q

この設計により、Excelベースでありながら高度なAPIテストシナリオ(認証→データ作成→検証など)を実現可能となる。

タグ: Python requests openpyxl pytest API Testing

5月30日 02:34 投稿