エムスリーテックブログ

エムスリー(m3)のエンジニア・開発メンバーによる技術ブログです

API テスト事始め ーテストツールscenarigoを添えてー

【QAチームブログリレー5日目】
こんにちは、エンジニアリンググループの末吉です。最近十数年ぶりに再開したピアノにハマっています。何年先になるかはわかりませんが、英雄ポロネーズを弾けるようになろう! と目標を立てて励んでいます。

実家の猫です、可愛い。

初めに

今回scenarigoと呼ばれるAPIのE2Eテストツールを紹介します。
APIに変更が入り、QAを実施する場合は変更範囲に絞ってユーザーストーリーマッピングに沿ったパターンを設計し画面検証を実施するか、Swagger Editor / GraphQLを利用したチェックを行っていました。
scenarigoで作成したシナリオとしてCIに組み込み、デプロイ時に回すようにすることでデグレの確認が容易になりました。

scenarigoの紹介

scenarigoはメルカリのarchitectチームが提供しているAPIのe2eテストツールです*1

  • シナリオがyaml形式
  • go言語でプラグインを記述可能

という特徴があります。

別のシナリオを前提としてインポートできるため、 シナリオ上必ず実行される共通の操作(ログイン認証など)は分けることにしています。 共通操作のシナリオを分けることで可読性が上がり、このシナリオは何を確認したいのか、流れを容易に把握できます。

シナリオ例

例としてニュース記事一覧を取得するシナリオ(get_news.yaml)を作成してみます。

  1. ログイン認証操作
  2. ニュースのトピック一覧を取得

という流れで構成されています。

steps: 
- title: ログイン認証、セッションIDを取得し保持
  include: './login.yaml'
  bind:
    vars:
      session_id: '{{vars.session_id}}'

- title: 記事一覧を取得
  protocol: http
  request:
    method: GET
    url: "https://api.hogehoge.com/news/topic.json"
    header:
      cookie: session_id={{vars.session_id}}  #保持したセッションID
  expect:
    code: 200

このシナリオでは最初にログイン認証のシナリオを別にインポートして実行、セッションIDをbind:以下の変数session_idで保持します。
以下その保持した値を使い記事取得のAPIを叩き、得られたレスポンスをexpect:以下でチェックします。上のシナリオ例ではレスポンスコードの200が返ればテストとしてOKになります。

コードを普段書かない人でもこのyamlで何を実施しているのか理解しやすいと思います。

続いてシナリオを下のような形でCI上に組み込み、ビルド時に回しています。

.apitest_template:
  stage: APItest
  tags:
    - docker
  image: golang:1.19
  script:
    - go install github.com/zoncoen/scenarigo/cmd/scenarigo@v0.14.2
    - scenarigo run get_news.yaml

まとめ

E2Eテストツールとしてscenarigoを紹介しました。
現在の一部のサービスのCIに組み込まれ導入されていますが、まだまだ導入し始めの段階です。
エムスリーでは多くのサービスに色々なQAメンバーが関わっていますので、これから先横展開をする上でもscenarigoの可読性の高さや拡張性の高さが魅力的に感じました。

今回紹介した例ではレスポンスコードだけチェックしましたが、body部のコンテンツをチェックすることもできますし、またレスポンスの特定のフィールド値を保持できるため、シナリオの拡張も容易です。また要素のnull checkや数値比較などの関数も備わっており、盛り沢山です。
今後は実装範囲を広げていきながら作ってはい終わり! にならないよう保守性の点でも整備を続けていきたいと思います。

We are hiring!!

エムスリーではQAエンジニアの採用活動にも力を入れています。 自動テストに限らず品質活動に興味のある方など、様々なQAエンジニアを募集しています! jobs.m3.com

*1:メルカリで書かれた紹介記事はこちらhttps://engineering.mercari.com/blog/entry/20210928-mtf2021-day5-3/