ブログに実装したテストについて

このブログに実装したテストについてまとめる。
特にVRTとCI周りで色々検討することが多かったので、備忘録として記録しておく。

結論

  • PlaywrightでE2E、ComponentTest、アクセシビリティテスト、VRTを実装
  • Vitestでユニットテストを実装
  • GitHubActionsで各種テストを実行、テストレポートをGitHubPagesにアップロード

やりたいこと

しっかりテストを書いてライブラリを自動でアプデしていきたい。
renovateがアプデのPRを作成して、CI通ったらオートマージしていくイメージ。
もし壊れたらそれはそれで良い経験になりそうなのでヨシ。
たかがブログなので必要なテストもそんなに多く無いはず。

E2E

Playwrightを使って書く。
あまり内容は無い。ページ遷移の確認ぐらい。

Component Test

PlaywrightのComponent Testでコンポーネントの挙動を検証する。

Components (experimental) | Playwright

Introduction

playwright.dev

といっても現状ここで検証したいものはほぼ無く、リンクの表示をリッチにするLinkCard(👆でも使ってるやつ)ぐらいしかない。

アクセシビリティテスト

Playwrightを使って書く。

Accessibility testing | Playwright

Introduction

playwright.dev

unit test

Vitestを使って書く。
記事の情報を取得するための関数がいくつかあるので、正しく動くことをここで検証している。
UIコンポーネントについては他のテストで十分に検証できているのでunit testは書いてない。

VRT

Playwrightを使って書く。

Visual comparisons | Playwright

Introduction

playwright.dev

ここが一番テストの量が多くなった。
主に以下の描画内容を検証している。

  1. 各ページ
  2. mdxで書いたコンテンツ
  3. LinkCardコンポーネント
  4. OG画像

1.各ページ

このブログにはホーム画面、記事詳細画面、タグフィルター画面の3つの画面がある。
それぞれについてスナップショットを撮ってVRTを実行している。

2.mdxで書いたコンテンツ

mdxで書いたコンテンツをhtmlで描画する処理は、ライブラリを使いつつ自前で実装しているため、正しく描画されることを確認しておきたかった。
現状対応できているmd記法を羅列したテスト用のページを作り、そのスナップショットを撮ってVRTを実施している。

テスト用ページのイメージ

見出しレベル1

見出しレベル2

見出しレベル3

見出しレベル4

見出しレベル5
見出しレベル6

テキストのスタイル設定

これは太字テキストです

これは斜体テキストです

これは取り消し線テキストです

この文章は とても 重要です

全てが重要なテキストです

これは下付き文字です

これは上付き文字です

これは下線付きです。

これは取り消し線です。

これはマークです。

他にもいくつかテスト用の記事を作成しており、記事のfrontmatterにtest: trueが設定されている場合は本番環境で表示されないように制御している。

3.LinkCardコンポーネント

LinkCardはリンク先のOG情報を取得して描画している。
ただしどんなOG情報を提供しているかはリンク先のページに左右されるため、イレギュラーなパターンでもレイアウトが崩れないかを確認しておきたかった。
(OG画像の比率が想定外のパターン、そもそも画像が無いパターン、descriptionやsitenameが欠落してたり長すぎるパターンなど)

PlaywrightのComponent Testを利用して各種パターンを用意して、それらに対してスナップショットを撮ることで自動テストを実現できた。 正常系のデータを表示したLinkCard リンク先のページのタイトルやdescriptionが長い場合のLinkCard リンク先のOG画像がない場合のLinkCard

PlaywrightのドキュメントにはComponent TestとVRTを組み合わせて利用できる旨は書いてなかったけど、やってみたらできた。
E2Eでできることは基本的にComponent Testでもできるっぽい。

4.OG画像

これは少し変わったテストで、動的に生成しているOG画像の描画内容を検証している。
動的生成の実装にはNext.jsのImageResponseを利用している。

Metadata Files: opengraph-image and twitter-image | Next.js

API Reference for the Open Graph Image and Twitter Image file conventions.

nextjs.org

自分でCSSをゴリゴリ書いているので、ページのタイトルが長すぎたり短すぎたりしてもレイアウトが崩れないことを検証したかった。
OG画像のスナップショットを撮ることで自動テストを実現できた。

タイトルが1行の時のOG画像 タイトルが2行の時のOG画像 タイトルが3行の時のOG画像

CI

ここまでのテストをGitHub Actionsで実行している。
テストの実行だけなら何も難しいことは無いんだけど、Playwrightのreportの確認とVRTのスナップショット更新の仕組みを整えるのが少し大変だった。

report

Playwrightのreportはデフォルトだとテスト実行後playwright-report/に保存される。
単純にこれをアーティファクトとしてアップロードするだけだと、reportを確認するにはまずアーティファクトをダウンロードして、ダウンロードしたファイルをplaywrightがセットアップされているディレクトリに移動して、npx playwright show-reportコマンドを実行してreportを起動する必要がある。
さすがにこれは手間すぎるので避けたい。

ちなみにドキュメントにも「毎回ダウンロードして確認するのはあまり便利ではない」と書いており、reportをAzureにアップロードするやり方が紹介されている。

Setting up CI | Playwright

Introduction

playwright.dev

Azureは利用したことがないのとあまり勉強のモチベーションも無かったので、今回は一番手軽に済ませられそうなGitHub Pagesを利用することにした。

ここでPlaywrightのE2EのreportとComponent Testのreportを別管理する必要があることに気がつき、少し悩んだ。
両者のreportはデフォルトだとどちらもplaywright-report/に保存される設定になっており、後から実行したテストのreportしか残らない
これを避けるために保存先をそれぞれplaywright-report/e2e/playwright-report/ct/に分けて、playwright-reportフォルダごとGitHub Pagesにアップロードすることにした。
これでGitHub Pages上から両方のreportを確認することができるようになった。

常に最新のテストの結果しかGitHub Pages上から確認することができないという課題が残ってるけど、これをGitHub Pagesで解決するのは中々大変そうなのと、過去のreportもダウンロードさえしてしまえば確認することはできるので、今回はスルーした。

VRTのスナップショット

PlaywrightのVRTは、リポジトリ内のスナップショットの画像ファイルと比較して差分検知する仕組みのため、最新のスナップショットをgit管理することになる。
つまり、差分をAcceptする場合は最新のスナップショットをコミットする必要がある。
また、スナップショットはローカルでの実行結果とCI上での実行結果では差があるため、CI上で作成されたスナップショットをgit管理しなければならない

一応Playwrightのreportからもスナップショットを一枚一枚ダウンロードすることはできるけど、update対象のスナップショットを一枚ずつダウンロードするのはあまりに手間すぎる。
Playwrightの実行環境がDesktopのChrome, EdgeとMobileのChrome, Safariの4つあり、スナップショットも4環境分あるので、割と量もある。

これについては、毎回最新のスナップショットをartifactとしてアップロードして、差分をAcceptする時はそれをそのままリポジトリのスナップショット管理ディレクトリにぶち込んでコミットできるようにした
差分が発生したブランチに向けてスナップショットを更新するPRを自動で作成するような仕組みを作ると一番良いと思うので、そのうち気が向いたらやるかもしれない。
ブログはほとんどVRTの差分も出ないのでこれでも十分運用できるけど、実務で運用する場合はそういう仕組みがないと流石に辛すぎると思った。

まとめ

色々悩むこともあったけど、とりあえずライブラリのアプデを自動でできるぐらいには整備できたと思う。