見出し画像

Playwright × Gaugeで拓くE2Eの新境地 〜 社内の自前E2Eが最高な話

こんにちは、アルプでQAエンジニアをやっているyokota(@katawara)です。
アルプではQAエンジニアの働き方として3つのロールがあり、以下のように分類されています。

・リードQAエンジニア(L-QA) : 組織全体のQAプロセスを改善する責務を担う
・チームQAエンジニア(T-QA) : プロダクトチーム内のQAプロセスを改善する責務を担う
・オートメーションQAエンジニア(A-QA) : プロダクトチームが行っているテストとは別軸の自動テストを作成を担う

QAエンジニアの幅広い業務を整理し、3つのジョブディスクリプションを作ってみた より引用

この記事を書いている2024年5月現在では、一人でいろいろな帽子を使い分けているといった塩梅なのですが、今回はA-QAとしての帽子をかぶり、E2Eテスト(自動テスト)の話をしてみたいと思います。


アルプでのE2E事情

アルプで使われているE2Eは大きく2つあります。

SaaSとして提供されているAutifyと、プログラムで自前で構築するPlaywright & Gauge、この2つを併用しています。
それぞれの特性とテスト対象の特徴を踏まえながら使い分けをしている形ですね。

今回は後者のPlaywright & Gaugeのほうにスポットを当てます。

社外の方とお話する際、自動テストの技術スタックの説明は「AutifyとPlaywrightを使っています」に留めてしまうことも多いのですが、実は後者については、さらにGaugeというものを組み合わせており、これがかなりユニークながら最高の組み合わせなんじゃないかと思っています。
ちょっとテクニカルな話も入ってくるかもしれませんが、いかにこの組み合わせが素敵か布教してみたいと思います。

なお、この自前のE2Eは社内では "harness" というコードネームで呼ばれています。以降の記事の中でその名が出てきたら、PlaywrightとGaugeを使った社内の自前E2Eのことだとご理解ください。

技術スタックの紹介

まずは登場人物から整理していきましょう。

Playwright

Microsoftが開発したテスト自動化フレームワークです。Node.js(TypeScript, JavaScript), Python, Java, .NETそれぞれサポートしています。
クロスブラウザ・クロスプラットフォームに対応し、InspectorTrace Viewerでの実装サポートも手厚く、flakyテスト対策を取りやすい実装が取り揃えられているのが魅力的です。

社外のQAの方と会話した際にも結構名前が上がってくるので、使っている人も徐々に増えてきているのではないでしょうか。

アルプでは、提供しているScalebaseのフロントエンドがReactであるというスキルの親和性と、型があるほうが何かと便利ということでTypeScriptを選んでいます。

Gauge

オープンソースのテストフレームワークです。C#, Java, JavaScript, Python, Rubyといったところを公式でサポートしています。TypeScriptについても、非公式のようではありますがGaugeのコミッターの方が用意してくださっているものが使えます。
また、Visual Studio Codeであれば、拡張機能も用意してくれていて、ステップ間の移動や補完、呼び出し元の参照やシナリオの実行といったIDEっぽいサポートを得ることもできます。

何と言ってもこれの特徴は、spec, cptというファイルにMarkdownでテストを記述し、その裏側の実装を何らかのプログラミング言語で書くことができるというものです。
Markdownのリスト一行が操作を表すステップとなり、そのステップを裏側で別の言語で実装する、みたいなイメージです。

また、裏側のライブラリとしてTaikoというものを使うことができ、簡単に操作を表現できるようになっています。

Playwright × Gauge = ?

アルプでは、ここまで紹介したGaugeとPlaywrightを組み合わせて使っています。「Gaugeをベースにして、裏側で動くライブラリとしてTaikoの代わりにPlaywrightを使うことにした」というのが正確な説明になるでしょうか。
当初Taikoも検討はしていますが、Playwrightのほうがいろいろと柔軟にできそうだったのでこの組み合わせにしたという背景があります。

この組み合わせの結果として、アルプの自前E2EはMarkdownとTypeScriptで実装されています。

つまり、表側のテストはMarkdownで書くことができつつ、裏側はPlaywrightの恩恵を受けながらプログラムとして書くことができるといった形ですね。
さながら、E2Eの中で、フロントエンドがMarkdown、バックエンドがTypeScript、という状態が成立していると言ってもいいのではないでしょうか。

かつ、GaugeとPlaywright双方を使っているので、Gaugeが提供するレポーティング機能を利用しつつ、Playwrightが提供するInspectorやTrace Viewerでデバッグや実装の補助を利用する、みたいなことができます。それなりにコードを書く必要はありますが、だいぶ便利に作り込むことができます。

Gaugeからはこんな感じのレポートが出せます

テストフレームワークの掛け算による化学反応

この2つの組み合わせにより、3つの可能性が生まれました。順に紹介します。

1. E2Eを書くのに、プログラムが書ける人とそうでない人で分業できる可能性

GaugeとPlaywrightの併用により、MarkdownとTypeScriptに分けることができるようになりました。これはつまり、言語を境界線に作業分担ができる可能性を示唆します。E2Eを自前で用意するにあたって、すべてができる人を求めなくてもいいというのは採用面にも好影響を与えるのではないでしょうか。

Markdownは、近頃ではNotionやConfluenceといったドキュメントツール、noteやQiitaといったブログ投稿システムでもサポートされており、プログラミングに馴染みが薄い人でも書くハードルが低いと思われます。

TypeScriptで言えば、操作内容はコード上にアノテーションをつければ実装できるので、「特定の文字列をクリックする」といった汎用性の高いステップを用意すれば、かなりの操作が定型的に書けるようになります。
たとえばこんな感じですね。

これくらいのコードで収まるものも結構多いので、もしかすると初学者が入るのにもいいかもしれません。

アルプでもPdMにMarkdown側を書いてもらい、足りないところを開発メンバーに実装してもらう、みたいなことをやってみたことがあります。開発メンバーからはどう書いたらいいかあまり迷わなかったとも言ってもらえたので、社内の技術スタックと親和性の高いものを選んでおけば、スキルトランスファーも難しくなさそうです。

2. ドキュメントとしてのわかりやすさと、コードとしてのわかりやすさという関心事が分離できる可能性

GaugeのMarkdownがどこまで書けるのか完全に把握できていないところもあり、動かしながら確かめている部分もあるのですが、かなりの自由度で記述ができます。表やリスト、罫線や絵文字といったところまではサポートされており、Gaugeのレポートに変換されると一定のドキュメントとして読むことができます。そこにはなぜこのテストを必要としているのかの意図や、何を確認するものなのかといった、ドキュメントとしての意義を自然言語で記載することができます。

頑張ればこれくらいまで書ける
(なお、記載内容はあくまで投稿時点での話であり、将来まで同様とは限りません)

自然言語で書けるということは、スプレッドシートでテストケースを起こすこととも大差はないと思われます。実行手順みたいなカラムを作ってケースを書くときの知見がここに流用できるはずです。

また、コードは別で書くため、テスト独特の記法みたいなものが入りにくく、素直にコードを書いていけるのでそれぞれが一定読みやすくできるというメリットも生まれていると感じます。

3. ドキュメントでありながら同時に実行可能であり、文字通り生きたドキュメントとなる可能性

ドキュメントの宿命として、書いたそばから陳腐化していくというものがあります。
しかし、このドキュメントは(Visual Studio Codeの拡張機能を利用してではありますが)動作させることができます。

クリックするとブラウザが立ち上がって動作を見ることができます

「この機能はこう操作するとこう動くはずである」がいつでも検証でき、異なる動きに変わっていないかを随時チェックすることができるのです。
自然言語で書かれたドキュメントからその場でアプリを動かす導線があり、正しい動作をするか検証できる、というのはなかなか見ない体験ではないでしょうか。

現状の課題

さて、ここまでいいことばかり書いてきましたが、当然悩ましい部分もあるのでそこも触れておきます。

1. わかりやすく書くことは難しい

Markdownであるがゆえに自由度の高い記述をすることはできますが、最終的にどう書くのがいいのか、みたいな点はずっと模索が続いています。
一番シンプルな形として、操作を順番に愚直に羅列することでも成立はしますが、アウトプットを見ると結構目が滑ります。

また、どんな操作が事前に実装されているのかがわかりにくいので、入力候補が出るとしても不慣れな書き手にとってのハードルもあります。
かといって、粒度を粗くしすぎると、今度はプログラム側で再利用しにくいものができてしまい、実装の複雑さにつながってしまうので、バランスが難しいところです。

最近ではBDDで言うところの定式化と呼ばれるやり方が答えに近いのでは、みたいなことを考えていますが、それはまた別のお話としたいと思います。

2. 書くこと自体に少し工数が重い

E2Eという特性からかは判断が難しいところですが、作業に慣れていても1シナリオ書くのに1〜2日持っていかれるところは否めません。
一人で一気通貫で書こうとすると、Markdownの頭からTypeScriptの頭へのスイッチも発生し、それなりのスイッチングコストがかかります。
また、効果的なテストを書こうと思うと、どういうシナリオを書くのが適切か、どういうテストデータを用意するのが適切か、といったことにも頭を使う必要もあり、都度壁打ち相手も欲しくなったりします。

3. 小さく大量にシナリオを作るというのはやりづらい

E2Eとして動かすという側面を持たせてしまっているため、ついついシナリオが大きくなりがちなところがあります。
もちろん小さく作ることもできなくはないし、そっちのほうが理想的だとも思うのですが、操作の上では前の工程で作ったデータを使って続きの操作をしたほうが都合がいい場面もあります。しかしそれが途中で失敗してしまうと、後続のテストが総崩れになってしまったり、ちょっと安定性に欠けるテストとなってしまうのも事実です。
現時点ではハッピーパスを中心に置くことで、テストの肥大化を防ぐほうを重視していますが、ここのさじ加減はまだ模索中です。

最後に

ということで、アルプのE2E、コードネーム "harness" の紹介でした。
オープンソースの組み合わせなので、(やろうと思えば)誰でも試せるのが良いところですね。もっとこうできたら、みたいなアイディアを実装して使い勝手が拡張できるのも良いです。
ここまでで紹介した通り、MarkdownとTypeScriptの組み合わせで作る自動テストは3つの可能性を持ち、それらをフルに活かせば、アルプで培ってきたBDDでいうところの「発見」の次、「定式化」と「自動化」へとつなげる選択肢のひとつとなりうるのではと考えています。

今回はコードや動いている様子をほとんど出さずにコンセプトを中心にお話しているので、わかりにくいところも多々あったかと思います。
コードとしてどう作るものなのか知りたいよ、だったり、普段の運用はどうしているのか知りたいよ、みたいなお話がもしあるならそちらに特化した続編も考えてみようかなと思うので、よかったらフィードバックをもらえたら嬉しいです。

この記事が気に入ったらサポートをしてみませんか?