Tavernは優れたエンジニアリングです。pytestに組み込まれており、APIテストをYAMLファイルとして記述し、そのファイルを通常のpytestテストのように実行できます。pytestの完全なエコシステム(フィクスチャ、プラグイン、pytest-xdistによる並列実行、カバレッジ、Pythonチームがすでに使用しているコマンド)を無料で利用できます。pytestを中心に活動するバックエンドチームにとって、ユニットテストの隣にtest_*.tavern.yamlファイルをもう1つ書くのは自然に感じられます。
YAMLが肥大化すると、問題が生じます。ボディを送信し、トークンを保存し、いくつかの応答フィールドをチェックする単一のリクエストは、正確なインデントが必要なrequest、response、save、verify_response_withキーのネストされたブロックに変わります。複数段階のフロー(ログイン、リソース作成、読み戻し、削除)は、これらのブロックを1つの長いファイルに積み重ね、そこでは誤ったスペースが解析を壊し、テストが検証するAPI契約が全く別の場所(Swaggerファイル、Wikiページ、数ヶ月前に古くなったPostmanコレクションなど)に存在します。
Tavernの長所
Tavernには功績があるので、まずはそこから始めましょう。
pytestを置き換えるのではなく、pytestに乗っ取ります。 Tavernはpytestのプラグインです。pip install tavernでインストールし、テストディレクトリにYAMLファイルを置くだけで、pytestが他のテストと同じようにそれを発見して実行します。つまり、チームがすでに持っているすべてのpytest習慣(フィルタリング用の-k、最初の失敗で停止する-x、レポート用のpytest-html、並列実行用のpytest-xdist、共通セットアップ用のフィクスチャ)を維持できます。ランナーについて何も変更する必要はありません。Pythonを使用する企業にとって、これは大きな利点であり、既存のスイートとこれほどきれいに統合できるAPIテストツールはほとんどありません。
YAMLは宣言的で読みやすいです。 シンプルなTavernテストは本当に簡単に読み取れます。
test_name: Get a single order
stages:
- name: Fetch order 1042
request:
url: https://api.shop.test/orders/1042
method: GET
response:
status_code: 200
json:
id: 1042
status: shipped
結合コードも、インポートするアサーションライブラリも、書くべきテストハーネスもありません。リクエストと期待されるレスポンスが並んで配置されています。ステータスコードといくつかのフィールドをチェックする場合、これは同等のrequestsとassertのPythonコードよりも読みやすくなっています。
変数の保存と連携。 Tavernは、saveと{variable}の置換機能を使って、あるレスポンスから値を取り出し、次のステージに注入できるため、ログイン後にAPIを呼び出すようなフローをカスタムコードなしで実現できます。
stages:
- name: Log in
request:
url: https://api.shop.test/auth/login
method: POST
json:
username: tester
password: hunter2
response:
status_code: 200
save:
json:
token: access_token
- name: Read the profile with the saved token
request:
url: https://api.shop.test/me
method: GET
headers:
Authorization: "Bearer {token}"
response:
status_code: 200
HTTP以上の機能。 TavernはMQTTもテストできます。これはIoTやメッセージ駆動型システムを扱う場合に重要です。また、基盤がpytestであるため、YAML形式のAPIテストと通常のPythonテストを同じ実行とレポートで混在させることができます。
これらは宣伝文句ではありません。Tavernは堅実なツールです。問題は、その前提があなたと一致するかどうかです。
YAMLの定型句が積み重なる場所
Tavernモデルには3つのコストが伴い、それらが重要かどうかはスイートの規模によって異なります。
YAMLはホワイトスペースが重要であり、スキーマが深いです。 上記の簡単な例はきれいです。しかし、現実的なテストはそうではありません。ヘッダー、クエリパラメータ、リクエストボディ、レスポンスボディのアサーション、型チェック、保存された変数、そしてverify_response_with外部関数を追加すると、1つの誤ったスペースが明確なメッセージではなく解析エラーとなるフォーマットで、4〜5レベルも深くネストすることになります。エディタはIDEがPythonメソッドを自動補完するようにはTavernのキーを自動補完しないため、新しいフィールドごとにstatus_codeかstatusか、jsonかbodyかドキュメントを確認することになります。
テストとAPI契約は別個の成果物です。 TavernのYAMLは、URL、メソッド、期待されるフィールド、およびそれらの型をハードコードします。実際のAPI定義は、OpenAPIファイル、フレームワークのルートデコレータ、または誰もはっきりとは知らない場所に存在します。APIがフィールド名を変更しても、YAMLには何も通知されません。テストはCIで失敗するまで、あるいはさらに悪いことに、古い期待値に対して合格し続けます。誰かが手作業でこの2つを同期させる必要があり、その誰かとは通常、午前2時に障害に直面する人物です。
PythonツールチェーンとPythonに精通した人材を前提としています。 テスターがPythonを書くのであれば、Tavernは素晴らしいツールです。しかし、QAグループ、フロントエンドエンジニア、またはプロダクト担当者がテストを追加したり読んだりしたい場合、HTTPリクエストを送信してレスポンスを確認するためだけに、pip、仮想環境、pytestの慣例、YAMLスキーマルールを一度にすべて学ぶ必要があります。Pythonの世界にいない人にとっては、導入のハードルが高いです。
YAMLをスキップする道
代替策は、テストをテキストファイルとして作成するのをやめ、すでに持っているAPI定義に基づいてテストを構築し始めることです。
Apidogでは、API仕様、リクエスト、テストが同じオブジェクトです。APIを一度インポートまたは設計し(OpenAPI、Swagger、またはPostmanコレクションのインポートはワンクリックで可能)、各エンドポイントは実際のスキーマを伴います。これらのエンドポイントを視覚的に連結することでテストシナリオを構築します。ログインコールをドラッグし、トークンが必要なコールをドラッグして、手動でsave:ブロックや{variable}文字列を記述することなく値を渡します。アサーションはパネル内のチェックボックスと式であり、覚える必要のあるインデントされたYAMLキーではありません。
テストは仕様に基づいて構築されるため、仕様が唯一の信頼できる情報源となります。デザインで応答フィールドを変更すると、それを参照するテストシナリオが、黙ってずれていくのではなく、その変更を表面化させます。これはTavernが構造的にできない部分です。TavernのYAMLには契約へのリンクがありません。
そして自動化する際も、Tavernの魅力的だったヘッドレスでCIフレンドリーな特性を失うことはありません。Apidog CLIは、pytestが現在のTavernファイルを実行するのとまったく同じように、GUIなしで、CIで、コマンドラインから同じシナリオを実行します。
Apidog CLIのインストールと実行
このランナーはapidog-cliという無料のnpmパッケージです。グローバルにインストールします。
npm install -g apidog-cli
次に、apidog runコマンドでテストシナリオを実行します。
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e 1629989 -r cli
各要素の役割は以下の通りです。
--access-tokenはApidogアカウントに対する実行を認証します。トークンはシナリオのCI/CDタブから生成し、ファイルには含めずにシークレットとして保存してください。-tはテストシナリオIDです。-eは環境ID(開発、ステージング、本番)で、同じシナリオが正しいベースURLと変数にアクセスできるようにします。-rはレポーターを選択します。cliはターミナルに読みやすい出力を表示します。
これらのIDを覚える必要はありません。Apidogでテストシナリオを開き、CI/CDタブに切り替え、コマンドラインオプションを選択し、「トークンを生成」をクリックします。ApidogがシナリオIDと環境IDがすでに記入された完全なapidog runコマンドを生成してくれます。それをコピーし、トークンをCIのシークレットに移動してください。
グローバルにインストールしたくない場合、特に一時的なCIランナーでは、npxを使って実行します。
npx apidog-cli run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e 1629989 -r cli
レポーターはcli、html、json、junitをカバーしています。CIの場合、便利な組み合わせは-r html,junitです。junitは、ほとんどすべてのCIダッシュボードが合格/失敗ツリーとして解析する標準XMLを出力し、htmlはビルド成果物としてアーカイブできる閲覧可能なレポートを生成します。出力先を制御するには--out-dirを追加します。
apidog run --access-token $APIDOG_ACCESS_TOKEN -t 605067 -e 1629989 -r html,junit --out-dir ./apidog-reports
インストールされているバージョンのフラグの完全なリストについては、apidog run --helpを実行してください。
比較
| Tavern | Apidog | |
|---|---|---|
| テスト形式 | YAMLファイル(*.tavern.yaml) |
仕様に基づいて構築されたビジュアルシナリオ |
| 実行環境 | Python + pytest | ヘッドレス apidog run(npmパッケージ) |
| 作成方法 | YAMLを手書きでインデント | エンドポイントをドラッグ&チェーン、チェックボックスでアサーション |
| API契約 | 別の成果物で手動で同期 | 仕様がテストの信頼できる唯一の情報源 |
| 変数連携 | save:ブロックと{var}の置換 |
UIでステップ間で値を渡す |
| レポーター | pytest-html、pytestプラグイン経由のJUnit |
cli、html、json、junitを内蔵 |
| テストを作成できる人 | Pythonに慣れたテスター | 非コーダーを含むチーム全員 |
| プロトコル | HTTPとMQTT | HTTPに加え、SOAP、WebSocket、gRPCなど |
チームがPythonを全面的に採用しており、ユニットテストと同じリポジトリ、同じpytest実行でテストを管理したい場合はTavernが優れています。YAMLのメンテナンスをやめ、契約とテストを一体化させ、Pythonを書かない人々もテストに貢献できるようにしたい場合はApidogが優れています。
CIへの組み込み
ヘッドレス実行は、ローカルのテストファイルからパイプラインへ移行する際の重要なポイントです。GitHub Actionsの記述例を次に示します。
name: API tests
on: [push, pull_request]
jobs:
api-tests:
runs-on: ubuntu-latest
steps:
- name: Install Apidog CLI
run: npm install -g apidog-cli
- name: Run API test scenario
run: |
apidog run \
--access-token "$APIDOG_ACCESS_TOKEN" \
-t 605067 \
-e 1629989 \
-r html,junit \
--out-dir apidog-reports
env:
APIDOG_ACCESS_TOKEN: ${{ secrets.APIDOG_ACCESS_TOKEN }}
- name: Upload report
if: always()
uses: actions/upload-artifact@v4
with:
name: apidog-report
path: apidog-reports
トークンはリポジトリのシークレットから取得され、環境変数としてステップに渡されます。アップロードステップのif: always()は、テストが失敗した場合でもレポートが取得できることを意味し、それはまさにあなたがそれを読みたい時です。アサーションが失敗すると、apidog runステップはゼロ以外の終了コードで終了し、ジョブは失敗と表示され、プルリクエストには失敗したチェックが表示されます。
この終了コードの動作は品質ゲートとして機能し、Tavernの場合と同じです。CIは各ステップの終了コードを読み取り、ゼロ以外の終了コードはジョブを失敗させ、失敗したジョブはマージやデプロイをブロックします。追加で何も設定する必要はありません。より詳細なパイプライン設定については、CI/CDパイプラインでのApidog CLIおよびGitHub Actionsのチュートリアルで、GitLab CIおよびJenkinsのバリアントもカバーしています。
pytestとより広いPythonテストの世界についての注記
TavernのYAMLから離れることは、pytestを放棄することを意味しません。多くのチームは、純粋なPythonのユニットテストと統合テストをpytestで維持し、API契約レイヤーにはApidogを使用しています。これはテストが仕様を追跡し、Pythonを扱わない貢献者でも実行できる部分です。この2つは相互に排他的ではありません。Tavernの価値は、pytestユーザーが生のrequestsコードよりも軽量な形式でAPIテストを書けるようにすることに常にありました。Apidogの価値は、APIテストが契約を追跡し、少数のファイルを超えてスイートが成長しても読みやすさを維持できるようにすることにあります。
他のランナーも検討している場合、同様のロジックがPostman CLIとNewmanの比較におけるPostmanのコマンドライン機能や、PostmanなしでのAPIテストにおける追加ツールなしでのコレクション実行にも当てはまります。
よくある質問 (FAQ)
Apidog CLIは無料ですか? はい。apidog-cli npmパッケージはnpm install -g apidog-cliで無料でインストールおよび実行できます。Apidogプロジェクトからテストシナリオを実行するため、実行できる内容はApidogのプランによって異なりますが、コマンドラインランナー自体は別途有料の製品ではありません。
Apidogと同時にpytestを使用できますか? はい。Pythonのユニットテストと統合テストはpytestで管理し、API契約テスト層にはApidogを使用してください。多くのチームが両方を実行しています。違いは、Apidogテストは別のファイルにハードコードするのではなく、仕様を追跡することです。
ApidogはCIでの不適切なマージをどのようにブロックしますか? 終了コードを介して行われます。いずれかのアサーションが失敗すると、apidog runはゼロ以外の終了コードで終了します。CIはその終了コードを読み取り、ステップを失敗とマークし、マージやデプロイをブロックします。これを機能させるために追加の設定は必要ありません。
CIにはどのレポーターを使用すべきですか? CIダッシュボードが合格/失敗ツリーに解析する機械可読な結果にはjunitを使用し、成果物として保存できる閲覧可能なレポートが必要な場合はhtmlを追加してください。一般的な選択肢は-r html,junitで、読みやすいビルドログ出力のためにcliもオンにしておきます。
ApidogはTavernのHTTPモードのようにHTTPのみをテストしますか? いいえ。ApidogはHTTPに加え、SOAP、WebSocket、Server-Sent Events、gRPCをカバーしています。TavernはHTTPにMQTTを追加しており、これはApidogがカバーしない唯一のプロトコル範囲です。したがって、MQTTがあなたのスタックの中心である場合はこの点に留意してください。
正直な結論
もしあなたがすでにpytestとYAMLで考えているのであれば、TavernはAPIテストを記述するクリーンな方法であり、pytestとの統合がまさにその最高の機能です。しかし、コストはYAMLそのものにあります。スイートが大規模になるにつれて、YAMLは深く複雑で脆くなり、検証するAPI契約へのリンクがありません。YAMLを手動でインデントしたり、仕様の2つのコピーを維持したりすることなく、同じヘッドレスでCIで明確に失敗する動作を望むなら、契約に基づいてテストを構築し、apidog runで実行する方がより簡単な道です。
コミットする前に、Apidogをダウンロードして既存のAPIをインポートし、「仕様がテストである」ワークフローを体験してみてください。無料で始められます。
