転職会議でWebエンジニアをしております @ishitan-liv です。
転職会議では、昨年末の記事にも紹介したようにDatadogを活用したE2Eテストに取り組んでいます。 今回は実践編として、具体的な実例を元にA/Bテストの実施方法などについて書きます。
参考までに昨年度末の紹介記事: made.livesense.co.jp
A/Bテストの影響でテストが失敗した例
転職会議では動線の変更の影響をA/Bテストを元に判断しています。 E2Eの対象になっている導線を変更するためのA/Bテストを実施すると、表示される画面がランダムに変わるためテストが落ちてしまいます。 今回はそういったテストケースに対応するためにどのような対応をしたのかを紹介したいと思います。
エラーが起きた際の実例
とあるチームが会員登録導線を修正した例を出します。 E2Eテスト作成時のテストフローと異なっていたため、slackに通知が届いていました。
その後、エラー箇所のテストを1箇所修正したことで自動実行フローが改善されテストが通った通知が届きました。
このように簡単にテストを直せるケースならば良いですが、自動実行しているテストなのに毎回ちょっとしたテストで改修をするのは効率的ではありません。 ではどうするのが良さそうなのか、転職会議での例を出してみます。
A/Bテストのパターンを固定化する
一般的にA/Bテストする際はオリジナルとテストパターンの2パターンが多いかと思いますが、Datadogからのアクセスの場合はオリジナルパターンを固定化することで回避する方法です。
この方法は様々なやり方があるかと思いますが、転職会議では以下の方法で対応しています。
特定のRequest Headersを付与する
Datadogの設定でAdvanced Optionsとして提供されているのが「Request Headers」です。
この設定は本番環境とステージング環境に双方設定しています。 転職会議のステージング環境と一部のWebAPIでは、特定のネットワークからのみアクセス可能にしており、そちらを突破する際にもこちらの設定が生きています。 例えば死活監視なども特定のヘッダーやIPアドレスからのみ許可しておりセキュリティを高めています。
Cookieに値を保持してDatadogアクセスであることを判定
転職会議のシステムは多数のマイクロサービスで構成されており、サービスによってはフロントエンドでも判定をおこなわないといけないため、アクセス判定には以下の方法で対応しました。
- バックエンド側でDatadogからのRequest Headersが付与されている場合はCookieを発行する
- フロントエンド側では発行されたCookieを確認し特定のKey-Valueをチェックする
バックエンド実装例(Ruby On Railsの場合)
例としてDatadogからアクセスがあった場合にリクエストヘッダーから情報を取得しておく処理を追加します。
class ApplicationController < ActionController::Base include Authenticatable include CacheControl before_action :set_cookie_from_datadog_access ...省略 def set_cookie_from_datadog_access cookies[:hoge_param] = true if request.env["HOGE_HEADER"].present? && cookies[:hoge_param].blank? end
viewやコントローラーなどで使う際にはcookiesから値を取得すればOKです。
フロントエンド側の実装例 (React + TypeScriptの場合)
実際にはもっと複雑な処理で実装されており、具体的なA/Bテスト処理を全て載せるのは難しいので、雰囲気だけ載せます。 バックエンド側で設定したCookieの値を取得することでフロントエンド側でのA/Bテストをします。
import * as Cookies from 'js-cookie'; ...省略 // Cookieにセットしている箇所はバックエンド側 const DATADOG_ACCESS_COOKIE = 'hoge_param'; const getDatadogAccess = () => { return Cookies.get(DATADOG_ACCESS_COOKIE); }; export const isDatadogAccess = () => { return getDatadogAccess(); };
使う際にはこんな感じで判定させます。 実際にはもっと複雑なA/Bテスト用のコンポーネントなどが存在し、その中でユーザー毎に振り分けています。
import { useEffect, useState } from 'react'; import { isDatadogAccess } from 'hoge-cookie'; export const useAbTest = (salt: string, id: string, patternNum: 2): string => { const pattern = useMemo(() => { if (isDatadogAccess()) { // datadogからのアクセスの場合は必ずデフォルトパターンを返す return "original"; } else { // 実際はここにid, salt, patternNumによりテストパターンを生成するロジックが入ります return 'test'; } }, [salt, id, patternNum]); return pattern; };
運用で大事なこと
ここまで実装について書きましたが、運用で一番大事なのはプロダクトマネージャーやエンジニアの各メンバーにきちんと周知することです。 もちろん上記の実装をある程度示した上で、A/Bテスト時にはこのようなE2Eテストが動いていることを認知してもらうことも大事です。 最初に紹介しましたがslackなどでエラーが通知された際に誰でも直せるように対応マニュアルの作成も必要になります。
最後に
E2Eテストの自動化はまだまだ課題が多く、実際に運用するには周囲からの理解を得ることが不可欠です。 個人開発であれば一人ですぐ対応できますが、複数のプロジェクトが走っている最中ですと頻繁にA/Bテストも実施されるでしょうし、都度直していては本末転倒ですので、ある程度放置出来る仕組み化が大事です。
次回はDatadogでプルリクエスト作成後、リリース前に修正で問題がないかをチェックする方法について紹介できればと思います。
では。