はじめに
こんにちは。ソーシャル経済メディア「NewsPicks」の QA/SET チームの海老澤です。 今回は NewsPicks WebにおけるPlaywrightでのユーザー行動ログのテストの取り組みを紹介させていただきます。
ログについて
NewsPicks では法人向けサービスや広告システムがあり、法人向けサービスや広告パフォーマンスのレポート、またKPIの追跡などログデータの信頼性がビジネスに直結しています。ログはただの記録ではなく、ビジネスインサイトを得るための重要なデータソースです。 そのため、ログが正確に記録され、リクエストが期待通りに発生しているかをテストで保証することが不可欠になります。
ログシステムについて説明するとまずユーザーの操作をトリガーにして、Webフロントエンドもしくはアプリからリクエストが飛びます。リクエストをサーバーで受けデータストアに保存し、その後ワークフローエンジンなどで成形されたログがDBに保存され、各種システムからレポートなどの形で閲覧できる状況になります。
今回紹介するテストのスコープとしては NewsPicks の Webにおいて、ログのリクエストが送られることと、正常なレスポンスが返ってくるかをテストします。 クライアントからリクエストを送る部分になるので、仮にここにバグがあり、一部のログが送られない状態になったとしてもサーバーやクライアントでエラーが発生するわけではないので気づきにくい部分です。
リクエストの検証方法
Playwright でのリクエストの検証は page.on('request') を使います。これはリクエストが投げられたときに定義したコールバックが実行されます。 リクエストの取得方法としては waitForRequest もあり、こちらはリクエストが送られるまで待機する仕様で、NewsPicksではログが送られないこともテストするため 共通関数ではpage.on('request') を使っています。仮に意図しないところでログが送られてしまった場合、レポート等に水増しされた値が反映されてしまい、場合によってはより深刻な障害になる可能性があります。
下記はリクエストを取得する関数の例です。 page.on('request') を準備し、その後 await action
で一定の操作を実行し、リクエストを返す関数になります。
NewsPicksでは一度の操作で複数のログリクエストを送ることがあるため、複数リクエストが返ってくるような実装になっています。別々にテストを書いても問題ないですが、ログのテストケースは多くテスト実行時間が長くなるため、このようにしています。
export async function getRequests( page: Page, action: Promise<void>, // 特定のアクション(例 記事のクリック) conditions: RequestCondition[], // urlPathNameやqueryString, requestBodyなどの条件 ): Promise<Map<string, Request[]>> { const requestMap: Map<string, Request[]> = new Map( conditions.map((c): [string, Request[]] => [c.urlPathName, []]), ) page.on('request', (request) => { const url = new URL(request.url()) for (const condition of conditions) { if (isMatched(request, condition)) { // urlPathName, queryString, requestBodyが一致するか. requestMap.get(url.pathname).push(request) } } }) await action return requestMap }
リクエストを取得した後はリクエスト数や ResponseHeader 等のアサーションを書くだけです。
expect( requests, `1件の hoge リクエストが送信されること`, ).toHaveLength(1) const headers = response.headers() expect( headers['fuga'], `fuga のresponseHeaderが返ってくること`, ).not.toBeUndefined()
終わりに
今回はPlaywrightでのユーザー行動ログのテストについてご紹介させていただきました。
ご参考になれば幸いです。