SmartHR Tech Blog

SmartHR 開発者ブログ

E2Eテストを Playwright で作り直して開発プロセスに組み込む話

こんにちは。SmartHR プロダクトエンジニアの sasaki (@s_sasaki_0529) です。

今回は、私が開発に携わっている届出書類機能における E2E テストを、Capybara + Selenium の構成から Playwright に移行し、開発プロセスに組み込んだお話をします。

記事タイトルが記載されたアイキャッチ画像

扱う話題

  • E2Eテスト基盤を移行する具体的な背景と理由
  • 移行における提案から、合意形成までの流れ
  • 移行後の開発プロセスがどう変わったか

扱わない話題

  • Playwright など、記事内で扱う技術要素自体の詳細説明
  • 移行作業自体の詳細
  • テストコードの設計・実装に関する具体的なテクニック

なお、本記事では便宜上、移行前の E2E テストを「旧テスト基盤」移行後を「新テスト基盤」と呼称します。

届出書類機能について

E2Eテストに限らず、テストというのはプロダクトの特性によって最適な手法は大きく変わります。E2Eテストのお話をスムーズに進めるため、まずは対象となる届出書類機能(以下、本プロダクト)について簡単に紹介します。

本プロダクトは、SmartHR の機能を拡張する SmartHR Plus から提供される拡張プロダクトの一つです。

SmartHR 上の従業員情報をもとに、行政手続きの書類作成・電子申請を一括で行えるようになります。

届出書類機能を使って新規書類グループを作成しているスクリーンショット届出書類機能を使って書類のPDFプレビューをしているスクリーンショット
アプリストアの利用イメージより画像引用

本プロダクトが使用する「従業員情報」は、本プロダクトから見たら別プロダクトである「SmartHR 基本機能」に一元管理されているため、REST または GraphQL で提供される API を用いて連携する必要があります。

SmartHRにおける基本機能とオプション機能の関係性の図で、届出書類機能はAPIを用いてSmartHR基本機能にアクセスしていることがわかる
会社紹介スライドから引用*1

よって、以下の観点から本プロダクトでは自動テストの中でもE2Eテストの重要性が高いと考えられます。

  • SmartHR基本機能という、社内の別プロダクトに依存している
  • 行政手続きの電子申請の送信先である行政システム(e-Gov, マイナポータル)に依存している
  • それらを利用した、様々な届出書類・電子申請に対応している

旧テスト基盤について

本プロダクトでは以前から以下のようなE2E テスト(旧テスト基盤)が構築・運用されていました。

  • テストコードは Ruby(RSpec) をベースに、Capybara + Selenium を使用した構成で作成する
  • 上記テストコードでブラウザ操作を自動化し、常時起動しているステージング環境に対してテストする
  • テストは平日日中に2時間おきに自動実行され、デグレの検知や日時デプロイの可否判断に使用される

Slack に実行結果が通知される様子のスクリーンショット
Slack に実行結果が通知される様子

外部システムとの適切なコミュニケーションが重要であるプロダクトであることから、テストごとのインスタント環境は用意せずに、共有のステージング環境を使用しています。 ステージング環境では、SmartHR 基本機能のステージング環境及びテスト用の行政システムに接続するため、依存システム全体を通した E2E テストが可能になります。

また、リポジトリはプロダクトから分離されており、本プロダクト以外の様々なプロダクトのE2Eテストも一元管理されています。 QAチームがテスト基盤そのもののメンテナンスを行い、各開発チームは自分たちのプロダクトのテストコードを作成する運用になっています。

旧テスト基盤のメリット

旧テスト基盤には多くのメリットがありました。

QAチームのフォローを受けやすい

旧テスト基盤は QA チームによって開発・メンテナンスされていることから、E2E テストを作成・運用する上で、技術的及び品質保証の観点からQAチームのレビューを受けやすくなります。

テスト基盤のメンテナンスが不要

前項と重複しますが、QAチームがメンテナンスしているということは、開発チームに技術基盤の整備やCI設定の調整といったメンテナンスコストが少なく済み、プロダクト開発とそのテストコードの作成に集中できます。

Ruby + RSpec の書き慣れた構成で使える

SmartHR の多くのプロダクトは Ruby on Rails を使用していることから、普段のテストも RSpec を使用しているため、同じ技術構成で E2E テストを書くことが出来ます。

他プロダクトとの知見をシェアできる

本プロダクトに限らず、いくつかのプロダクトの E2E テストが同じリポジトリで作成されているため、E2E テストに関する各種知見をプロダクトを超えてシェアしやすくなります。

また、コードベースも共通であることから、チームを異動して別のプロダクトを担当することになっても、E2E テスト基盤が同じであれば再学習のコストが発生せずにキャッチアップしやすくなります。

旧テスト基盤のデメリット

ここまで見ると、旧テスト基盤は非常に優れた仕組みで、代替え不要に見えます。実際良い仕組みであることは間違いないため、使用を続けているプロダクトも少なくありません。

一方、E2Eテストの重要性が高い本プロダクトにおいてそれを最大限活用する上では、旧テスト基盤のままでは無視できないデメリットがいくつかありました。

立ち上がりが低速でサイクルを回しづらい

Capybara + Selenium を使用したE2Eテストでは、ブラウザ自動操作のために WebDriver プロセスを間に挟む都合もあり、起動に時間がかかる傾向があります。

E2E テストを作成・修正する上で、実行ごとに待ち時間が発生してはトライアンドエラーのサイクルが回しづらくなります。

要素セレクタの使い方などの実装が難しい

旧テスト基盤を用いた E2E テストでは、要素の取得に CSS セレクタ、または XPath を使用しています。それらはいずれも DOM ツリーの構造に着目したものであり、ユーザー視点とは異なるメンタルモデルで考える必要があるため、テストコードの読み書きが困難になったり、アプリケーションの変更に弱くなることがあります。*2

また、SmartHR は特に Web アクセシビリティに力を入れた開発を行っているのに、それも活用しづらい状況になっています。

E2Eテストに開発チームがオーナーシップを持ちづらい

リポジトリがプロダクトから分離され、QAチームによってメンテナンスされていることはありがたいことですが、どうしてもE2Eテストに対して他人事になってしまい、開発プロセス内で軽視されてしまう傾向がありました。

E2Eテストを最大限活用するためには、実行基盤まで含めたE2Eテストのオーナーシップを開発チームが持ち、自発的に開発プロセスに組み込みやすくするべきという課題感がありました。

これからのE2Eテストを検討する

旧テスト基盤のメリット・デメリットをまとめると以下のようになります。*3

メリット デメリット
QAチームのフォローを受けやすい 要素セレクタの使い方などの実装が難しい
テスト基盤のメンテナンスが不要 立ち上がりが低速でサイクルを回しづらい
Ruby + RSpec の書き慣れた構成で使える 開発チームがオーナーシップを持ちづらい
他プロダクトとの知見をシェアできる

メリット・デメリットそれぞれあるため、無条件にテスト基盤を移行しようという判断はできません。

そこで、ここまでの内容を整理し、課題感をチームと共有した上で、今後の E2E テストについて検討会を行いました。

ドキュメントのスクリーンショットで、本記事で触れている内容について要約されている。
ディスカッションに使用したドキュメントの見出し

検討会では、メンバーそれぞれの旧テスト基盤に対する印象や課題感などを吸い上げながら、どんな E2E テストにしていきたいかディスカッションし、メリット・デメリットをトータルで考えて新テスト基盤に移行しようという合意に至りました。

そこから、Playwright を用いたE2Eテストのプロトタイプを用意したり、チームでモブプログラミングを実施したり、さらには QA チームにも移行作業に参加してもらうなどの活動を重ね、ゆるやかに移行を進めました。

Playwright の採用

Playwright は Microsoft の OSS で、E2E テストフレームワークです。以下のような特徴を持ちます。

  • モダンWebアプリケーションをターゲットとすることを大前提として設計されている
  • フレーキーを生まない、信頼性の高いテストを作ることに注力している
  • クロスブラウザ対応 (Chrome / Edge / Firefox / Safari)
  • クロスプラットフォーム対応 (Windows / Mac / Linux)
  • クロスオリジン対応
  • JavaScript での実装が基本だが、アダプタを使用することで Python や Ruby も使用可能*4
  • テストシナリオごとに独立したブラウザコンテキストを持ちながら、セッションの共有も可能
  • 複数タブ・複数ウィンドウ・複数セッションを同時に扱うことが可能
  • エディタ連携・デバッグ用GUI・コード自動生成・テストレポートなど、E2Eテスト運用における補助機能の多くがビルトイン

これらの特徴が、旧テスト基盤に対して、以下のような優位性があるため採用しました。*5

オールインワンですぐに使える

Playwright には E2E テストを運用する上での多くの仕組みがはじめから組み込まれています。これはテスト基盤にあたるものを自ら構築し、メンテナンスしていくコストが極めて低いことになります。

例えば使用するブラウザの準備は yarn playwright install で完了し、プロジェクト設定や実行環境に応じたブラウザが必要十分にインストールされます。

テストレポートは実行ごとに自動作成され、 yarn playwright show-report ですぐに確認することができます。テスト結果は単純な成功失敗だけでなく、トレースを有効にした場合は実行ステップごとの DOM スナップショットを元にリプレイすることができ、デバッグを効率的に行えます。CI の場合はレポートを CircleCI のビルドアーティファクト などに保存することで、失敗時にすぐに確認することもできます。

Playwright のTrace viewer 画面のスクリーンショット
トレーサーを用いたテスト結果の確認画面

旧テスト基盤ではこのあたりの仕組みは自前で実装されており、 QA チームに頼りっきりな部分もありましたが、新テスト基盤では大したコストも払わず開発チームだけで完結できるようになりました。

アクセシビリティ属性を用いてテストが書ける

以下コードでは getByRole という関数を使用して、テキストボックスに keyword を入力しています。

await this.page.getByRole('textbox', { name: '検索' }).fill(keyword)

これは「検索」というアクセシブルネームを持ち、ARIA ロールが textbox になっている要素を取り出すロケータです。

このように、Playwright では Testing Library に近いインタフェースを持った API を用いて、アクセシビリティ属性を使ったテストコードを簡単に書くことができます。

SmartHR のプロダクトはアクセシビリティ向上に日々励んでいるため、マシンリーダブルなマークアップの水準が高く、それを E2E テストで使用することで、人間にも機械にも読みやすいテストコードが出来上がります。

逆に、これを用いてテストコードを書くことで、アクセシビリティ上の課題、対応漏れを早期発見することも出来ます。その場合はプロダクトコードのほうを同時に改善できます。*6

起動が高速

説明不要。速ければ速いほど良いですね。

あるテストを実行した際のコマンド実行からブラウザ操作開始までの時間は、旧テスト環境が7秒に対し、新テスト環境は1秒と圧倒的な差が付きました。

開発プロセスへの組み込み

新テスト基盤では Playwright を採用することで以下の恩恵を受けられることお話しました。

  • オールインワンですぐに使える
  • React アプリケーションとの相性が良い
  • アクセシビリティ属性を用いてテストが書ける
  • 起動が高速

これらはいずれも、E2Eテストを書くハードルが下げることに繋がります。

これまでは E2E テストを頑張ってあとから拡充して雰囲気で運用する形式でしたが、今では開発プロセスの一環として E2E テストの対応を行い、抜けもれなく素早くフィードバックを得られるようになりました。

これによって E2E テストのオーナーシップを QA 任せでなく、開発チーム自らが持てるようになり、積極的にテストを書こうという気持ちを強めることができました。

まとめ

本記事では、Capybara + Selenium を使った E2E テストを、Playwright で書き直した事例を紹介しました。

旧テスト基盤のメリットを十分に理解しながらも、これからの E2E テストのありかたをチームでディスカッションし、新テスト基盤に乗り換えてオーナーシップを持つことができ、さらに良い開発チームに一歩近づけたと思います。

We Are Hiring!

SmartHR では一緒に SmartHR を作りあげていく仲間を募集中です!

本記事のように、開発者が自発的に品質保証にも積極的に関わりつつ、周りをどんどん巻き込んでいけるオープンな社風です!

少しでも興味を持っていただけたら、カジュアル面談でざっくばらんにお話ししましょう!

hello-world.smarthr.co.jp

*1:この図は現在では古くなっており不正確ではありますが、本プロダクトが基本機能に対して API で連携している点は変わりません

*2:あるいは data-test / data-specといった、E2Eテスト専用のデータ属性をDOMに割り振る手法もありますが、これもE2Eテスト特化のメンタルモデルが生まれるのでなるべく避けたいです

*3:この他にも、Playwrightを使用することでフレーキーなテストが発生しづらくなるという観点もありましたが、多くの場合はフレーキーなテストとはテストコードの書き方が悪いか、あるいはアプリケーションのUI/UXの問題であると考えられるので、ここでは無理に Selenium/Capybara がフレーキーを生みやすいかに言及しません。

*4:この特徴から、Ruby アダプタを使用して旧テスト基盤からのギャップを減らす案もありましたが、イレギュラーな手法を取り入れるとトラブルシューティングが難しくなることを懸念して見送りました。

*5:モダンなE2Eテストフレームワークとして Cypress も検討しましたが、複数ウィンドウを使用したテストや、並列実行まわりでの課題感があったため、Playwright を採用しました。

*6:ただし、E2Eテストのためだけに aria-role などを無理やり付与するのはアンチパターンです。E2Eテストの文脈を抜きにした純粋なアクセシビリティ観点での妥当性の判断は必要です。