9
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?

API自動テストはGoogle Colaboratoryにやらせればいいんじゃないかと思った

9
Last updated at Posted at 2025-12-06

何かしらのWebAPIを外からテストしたい場合にわざわざCIを組むのは面倒なので、Google Colaboratoryを使えば楽な気がした。

スクリーンショット 2025-12-03 12.37.13.png

メリット

  • リリースフローへの組み込みなどでテストを複数人で共有する場合、各自のローカルでテスト作成すると属人化や管理の問題が出てくるが、colab上で共有して書けば解消される
  • colabからスプレッドシートの閲覧が楽なので、テスト設計者がスプレッドシートに内容を書くだけでそのまま実行できる。変更履歴も残る。
  • (Pro+を契約すれば)定期実行ができる

実装

流れ

  1. 各種認証
  2. テスト条件をスプレッドシートから取得
  3. 条件に従いAPIエンドポイントを叩く
  4. 結果判定

条件

  • 特定のエンドポイントに対し、指定したURLパラメータを付与して結果を確認する

    https://example.com/hoge?hoge={hoge}&piyo={piyo}
    
  • テスト条件はスプレッドシートに以下フォーマットで記入する

    項番, テスト名, 期待出力, 条件, expected, skip
    
    • 条件は hoge=123___piyo=aaa のような形式で入力します
  • テストの実行ログをGoogle Drive等へ保存するのもありだと思います

1. 認証設定

from google.colab import auth
import gspread
from google.auth import default

auth.authenticate_user()
creds, _ = default()
gc = gspread.authorize(creds)

ここで認証を求められる

2. テストパターンの取得

import pandas as pd

url = "https://docs.google.com/spreadsheets/xxxxxxxxxxxxxxxxxx"
ss = gc.open_by_url(url)
st = ss.get_worksheet(0)

data = st.get_all_values()
test_patterns = pd.DataFrame.from_records(data[1:], columns=data[0])

test_patterns

スクリーンショット 2025-12-02 19.00.39.png

3. テスト実行

import requests

BASE_URL = 'https://example.com/hoge?hoge={hoge}&piyo={piyo}'

class RequestSender():
  def __init__(self, tps):
    self.tps = tps

  def get_cond(self, conds, key, default):
    return conds[key] if conds.get(key) else default

  def execute_post(self, tp):
    conds = {}

    for cond in tp.条件.split("___"):
      if '=' in cond:
        k, v = cond.split("=")
        conds[k] = v

    url = (
        BASE_URL
          .replace('{hoge}', self.get_cond(conds, 'hoge', ''))
          .replace('{piyo}', self.get_cond(conds, 'piyo', 'aaa'))
    )

    response = requests.get(url)
    res_body = response.text
    exp_body = tp.期待出力
    exp_b = tp.expected.upper() == 'TRUE'
    res_b = exp_body == res_body

    res = {
      '項番': tp.項番,
      'テスト名': tp.テスト名,
      'ステータスコード': response.status_code,
      '期待出力': exp_body,
      '結果出力': res_body,
      '期待値': exp_b,
      '結果': res_b,
      '一致': '✅️' if exp_b == res_b else '🆖'
    }
    return res

  def run(self):
    results = []

    for tp in self.tps.itertuples():
      if tp.skip == 'TRUE': continue
      results.append(self.execute_post(tp))

    res_df = pd.DataFrame(results)

    if len(res_df[res_df.一致 == '🆖']) > 0:
      print('⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n⚠️⚠️⚠️⚠️ Fail ⚠️⚠️⚠️⚠️⚠️\n⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n')
    else:
      print('🎉 Success\n')

    display(res_df)

if __name__ == "__main__":
    RequestSender(test_patterns).run()

(メソッド名にマルチバイトが入るのに慣れない)

4. 結果

スクリーンショット 2025-12-02 18.59.34.png

結果をSlackに投げるようにすると使いやすいと思います。

おまけ

実行ログを永続化したい場合は以下を追記すればいいと思う

from google.colab import drive
drive.mount('/content/drive')

import datetime
import pytz
import logging

logging.basicConfig(
    filename="/content/drive/MyDrive/RequestSender/" + datetime.datetime.now(pytz.timezone('Asia/Tokyo')).isoformat() + '.log',
    level=logging.INFO,
    force=True)
def execute_post(self, tp):
    ....
    logging.info(res)

まとめ

今回はGoogle Colaboratory上にてローカル環境に依存しないAPIの自動テストの方法を紹介しました。

colabに搭載されているGeminiが使いづらすぎるのが社内で有名でしたが、VS Codeからも利用できるようになったので今後はAIコーディングの利便性も上がりそうです。

最後に宣伝です。
Supershipではプロダクト開発やサービス開発に関わる人を絶賛募集しております。
ご興味がある方は以下リンクよりご確認ください。
Supership 採用サイト
是非ともよろしくお願いします。

9
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
9
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?