2021年10月6日、Autifyは約11億円のシリーズAでの資金調達Autify for Mobileの正式リリースを発表いたしました。 それに伴い、Autifyで働くそれぞれのチームが日頃どのような業務をしており、どのような “Aim High” をしているのかをご紹介する「みんなの”Aim High”」を連載形式でお届けします。 今回はAutify for Webの開発やサポートを担当するエンジニアリングチームの末村より、お客様に使いやすいテストシナリオレコーディングの仕組みを実現する “Aim High” をご紹介致します。是非ご覧ください。

“Aim High” とは? わたしたちはコーポレートバリューとして

  • Solve burning needs
  • Aim high, stay grounded
  • Ownership & collaboration

を掲げています。その中でのキーワードのひとつ、“Aim High”をテーマに今後Autifyがどのような飛躍を目指しているのかをご紹介します。


はじめに

レコードアンドプレイバック(キャプチャーリプレイ)とは、テスト自動化の テストスクリプト を作成する方式の一つです。これは、ユーザーが実際に操作している様子を記録(レコード)し、それをテストスクリプトに変換することで、自動化システムが操作の流れを再生(プレイバック)できるようにするものです。プログラミングの知識が無くてもテストスクリプトを作成できることから、初心者にとってはとっつきやすく便利なものである一方、ある程度経験を積んだ自動化エンジニアからは批判の対象にされてきたものです。例えば、『システムテスト自動化実践ガイド』の2章のタイトルは『キャプチャーリプレイはテスト自動化ではない』です。

あなたがテスティングの自動化についてよく知らなければ、テスト担当者が席につき、キャプチャーリプレイツールの操作記録機能をオンにすることが、テスティングを自動化する一番の早道だと考えてしまうかもしれない。手動で行うテストをこのツールで記録し、再生することで、同じテストを正確に繰り返し実施できると。不幸なことに、あなただけでなく大勢の人が、これがテストの自動化の全てだと信じている。私たちは、なぜこれが真実から程遠いかを示すつもりだ。

Mark Fewster; Dorothy Graham. システムテスト自動化 標準ガイド CodeZine BOOKS. 株式会社 翔泳社 第2章『キャプチャーリプレイはテスト自動化ではない』より引用

しかし、Autifyはレコードアンドプレイバックを採用しています。それだけでなく、ここ数年で出てきた類似のサービスやOSSなど、E2Eテストをより良くしていこうと試みる多くのプレイヤーがこの方式を採用しています。

では、一体なぜレコードアンドプレイバックは批判の対象にされ続けてきたのでしょう?そして、我々はレコードアンドプレイバックの欠点をどのように解決できるのでしょう?本記事では、レコードアンドプレイバックに対する代表的な批判と本質的な問題、そしてそれらをAutifyがどのように解決しようとしている(または、既に解決した)のかについて説明します。

素朴な「自動記録」が忘れてしまうもの

素朴なレコーディングの結果、意図が分からないステップが多く記録されている

レコードアンドプレイバックの最大の利点は、専門知識の有無に関わらず、誰でも自動テストスクリプトを記述できることです。つまり、HTMLやCSSの知識が無く、ブラウザの開発者ツールの使い方を知らない人であっても、ツールをインストールできれば自動テストスクリプトを記述できます。

別の言い方をすれば、レコードアンドプレイバックを用いることで、専門知識が無い人でも無数に自動テストスクリプトを量産できてしまいます。つまり、テストコードの管理やメンテナンス性にまったく考慮せず、ただただ素朴に自動記録しただけのものを「テスト自動化」と称してしまうことが出来たのです。

自動記録で作成されたテストスクリプトは、あくまでユーザーが「この通りに操作した」という結果だけを記録します。例えば、入力フォームに文字を入力する場合に、もともと入っていた文字を BackSpace キーで削除したとしましょう……操作を素朴に記録したならば、こんな風に記録されてしまいます(※実際にこういうツールが多いというわけではなく、ものの例えとして捉えてください)。

  • input 要素をクリックする
  • Backspace キーを 5回 押す
  • "H" "E" "L" "L" "O" キーを押す

しかし、この実装ではもし入力フォームに6文字以上の文字が入力されていた場合に失敗してしまいます。BackSpaceキーを押すのは5回だけなので、それ以上の文字数を削除することは出来ないからです。ユーザーが意図していたのは「既に入力されている文字を空にする」だったはずです。

自動テストの経験が無くても、たとえばExcelの「マクロの自動記録」のようなツールを使って事務作業を自動化しようとしたことがある人は、同じようなことを経験したかもしれません。例えば、「データが入っているセルを選択」したつもりが、「A1からC55までの範囲のセルを選択」のように固定的な選択として記録されてしまうようなことです。そのままでは次回以降の実行では意図した動作をしません。

加えて、自動記録したテストスクリプトは人間にとって意味不明なものになっていることが多いです。つまり、div > div > div > p > span > span > a のようなセレクタは、それが何を意味するのかをまるで表現しません。プログラミングで言えば、マジックナンバーだけで構成されたソースコードのようなものです。また、スクロール操作のような暗黙の操作が scrollTo(47,564) のような絶対値でのスクロール操作として記録されてしまうこともあるでしょう。こうした可読性の低いロケーターやノイズなどが邪魔をして、テストスクリプトは意味不明でメンテナンス不能なものになってしまいがちです。

自動記録した「だけ」のテストシナリオは、そのままでは2回目以降の実行で失敗してしまう可能性が高いです。これを回避するには、継続してメンテナンスしていくのが重要です。しかし、メンテナンスするにはあまりにテストスクリプトが読みにくいため、最終的に「一度実行して終わり」「いつの間にか実行が失敗するようになってしまい、そのまま放ったらかし」になってしまうだろう……というのが、ここまでで説明してきたことです。

レイアウトは盛大に崩れてるけど、ヨシ!

もう一つ、自動記録で忘れがちなものとして「検証」があります。

もちろん、多くのレコードアンドプレイバックツールがページ内のテキストの検証などをサポートしています。しかし、これらは多くの場合「指定されたテキストを含んでいるか」「要素が表示されているか(いないか)」といった、かなり厳格な基準になっています。暗黙のうちに見ていたようなデザインの崩れなどは、人の目から見れば一目瞭然でも、CSSセレクタなどを用いた要素探索では全く考慮されません。例えば、会社のロゴがちゃんと表示されているかどうかや、レイアウトが意図せず3段組から2段組に変わってしまっているとか、そういった確認は自動記録されたスクリプトからは抜け落ちてしまいます。

レコードアンドプレイバックツールが提供する自動記録は、人間がやっている仕事をそっくり模倣して、人間を繰り返し作業から解き放ってくれると期待されてきました。でも、素朴すぎる自動化は、もともとのテストシナリオが持っていた様々な目的や観点をすっかり忘れてしまい、マヌケで硬直したボットスクリプトに変えてしまいます。もちろん、記録されたロケーターをより意図を反映しやすいものに書き換えたり、スクリプトにコメントを追加して分かりやすくしたりすることは出来るでしょう。でも、それってほとんどテストコードをプログラミングするのと変わらないんじゃないでしょうか?

読みやすいテストコードを書くには経験が必要

では、レコードアンドプレイバックツールを使うのを諦めて、単純にテストコードを書くのに切り替えれば良いのかというと、そう単純ではないようにも思えます。

個人的に、テストコードを書く上での最大の苦痛は、アプリケーション側のコードと二重メンテに陥りやすいことです。例えば、要素のidやclassなどを変更するたびに、それに対応したテストコードも変更しなければなりません。これらを回避するために、例えば文言やアクセシビリティIDをロケーターとして指定したり、 data-test のようなテスト用のユニークな属性を付与したりすることがあります。しかし、本質的にアプリケーションとテストコードをそれぞれ管理しなければいけないということには変わりありません。

加えて、テストコードだけを見ても、それらが意味するものが分からないこともあります。例えば、 button[type="submit"] というロケーターがあったとして、そのロケーターが画面の中のどの要素を指すのか、テストコードだけを見て想像するのは至難の技です。テストコードには、今その時点で画面がどのような状態になっているのかが表現されていないからです。これらを解決するために、Page Object Patternなどのプラクティスを適用し、UIコンポーネントとそのロケーターをセットで管理するようなことをすることもあります。しかし、テストコードを構造化し、実際のUIの構造を反映させようとすればするほど、アプリケーションと重複する箇所は増えてきます。

アプリケーションのコードとテストコードの間でうまく共通化部分を共有するようなことが出来れば、自動テストはより洗練されたものになるでしょう(StoryBookはこうした問題を解決する一つの手段ではないかと考えています)。チームによっては、そうした取り組みに投資するのも一つの手ではないかと思います。しかし、当然ですが相応のヒューマンリソースを必要としますし、何より開発とテスト双方に十分な技術、経験、それに情熱のあるエンジニアがいなければ成り立たないものです。

何より、レコードアンドプレイバックツールは、既に存在するソフトウェアをテストするのにぴったりなのです。BDD (Behavior Driven Development = 振る舞い駆動開発) のように、まだ存在しないソフトウェア(あるいは機能)のテストを記述するところから開発を始めるスタイルを採るのであればテストコードを書くほうがしっくり来るでしょうが、そうでない場合には「ブラウザ上で対象の要素のロケーターを調べる」「テストコードにコピペする」「動かしてみて期待通りの動きをするか確認する」という流れを繰り返すことになります。テストコードの行数が多ければ多いほど、これは大変な作業になるでしょう。

レコードアンドプレイバックはどう改善できるか

ここまでの話をざっくりまとめると、素朴に記録しただけのテストスクリプトは不安定で可読性が低く、可読性とメンテナンス性の高いテストコードを書くには開発プロセスの改善も含めた大掛かりな投資が必要なことが分かってきました。筆者の周囲だと、ユーザー企業においては後者の方法を採用する方が多いように感じています。例えば、Software Engineer in Testと呼ばれるようなテスト自動化専門のエンジニアを雇い、他の開発者やQAと連携して自動テストのアーキテクチャを構築するような形です。

じゃあ、レコードアンドプレイバックはどうなんでしょう?5年前から全然変わっていないのでしょうか……?いえいえ、そんなことはありません!ここからは、これまでの課題と、Autifyがどのように改善してきたかについてご紹介していきたいと思います。

想像力を求めない

テストコードにしろレコードアンドプレイバックのスクリプトにしろ、テストコードを読み解くのに想像力が必要だと、メンテナンスはどんどん面倒になります。ここでいう想像力とは、「実際の画面を想像しながらテストコードを読む」ことです。

レコードアンドプレイバックツールは、その名の通り記録した操作を再生できるので、ステップ実行しながらコードを読むこともできるでしょう。ですが、個人的にはコードそのものの可読性を上げる方に注目しています。一例として、 Puppeteer Recorder では、記録されたスクリプトは次のようにAccessibility IDを用いたものになっていました。

const {open, click, type, submit, expect, scrollToBottom} = require('@puppeteer/recorder');
open('https://github.com', {}, async (page) => {
  await click('aria/link[name="Sign up"]');
  await type('aria/textbox[name="Enter your email e.g. [email protected]"]', '[email protected]');
  await click('aria/button[name="Continue"]');
  await type('aria/textbox[name="Create a password"]', 'asdffdsa');

残念ながら、Puppeteer Recorderは実験的なプロジェクトで、既にメンテナンスされなくなってしまいました。しかし、Accessibility IDなどのアクセシビリティ属性を用いたテストスクリプトの記述は見た目にも分かりやすいですし、アクセシビリティを意識することにも繋がります。今後、他のプロジェクトやOSSで引き継がれることを期待しています。

Autify's scenario editor

さて、Autifyはどうしているかというと、スクリーンショットを使います。Autify上でレコーディングしたテストシナリオは、スクリーンショット付きで保存されます。

スクリーンショット付きのシナリオエディタは、シンプルで、誰でも思いつきそうなものですが、密かにAutifyの自慢の一つです……百聞は一見に如かず!テストスクリプトの中に山ほどコメントを残さなくても、スクリーンショットがあればそのステップで何が行われたのかは一目瞭然です。もう、テストコードを見ながら画面を想像したり、ブレークポイントを仕込んで一行ずつ動かしながら動作を確認する必要はありません。

また、それぞれのステップには名前や詳細情報を付けることができます。これもシンプルなものではありますが、一見しただけでは何のためにやっているのかわかりにくいステップにちょっとした説明を加えておくと、後々の可読性が非常に良くなります。

もちろん、記録したシナリオをそのままローカルのChrome上で実行することもできるので、「このテストがどういう動きをするのか、実際に動かして試してみたい」というケースにも対応しています。

シナリオ内の「ノイズ」を防ぐ

スクロールや文字の削除などの余計なステップを除くことについてはどうでしょう?Autifyでは、例えば文字入力一つ取っても、以下のような処理が内部的になされています。これらは「文字を入力する」というステップの中にまとまっているため、ユーザーがこれらの存在を意識することはありません。

  • 対象の要素が画面の中央付近に来るように自動でスクロールする
  • 対象の要素にフォーカスする
  • 文字を入力する前に、入力フォームの中のテキストをクリアする

ですので、例えば「Backspaceキーを5回押す」のような、意図がよくわからないステップが記録されることがないようにしています。

エンジニアの方なら、このような「よしなにやってくれる」ツールが上手く動かないときがあることをよくご存知でしょう……もちろん、Autifyも例外ではありませんので、様々なUIをサポートするべく日々改善を行っています!トライアルや本契約の後でもし上手く動かない箇所がありましたら、ご遠慮無くお問い合わせください :)

要素探索

レコードアンドプレイバック方式で記録されるロケーターは、時として不安定なものになりがちです。要素を特定する方法はいくつかあり、例えば要素の文言(textContentやvalueなど)を利用したり、idなどの内部的な属性を用いることもありますが、問題はレコーディング時にどの方法が最も安定しているのかを判断する材料が無いことです。サイトによってはidすら不変のものではないこともあるでしょう。

Autifyでは、それぞれのステップがどのように要素を見つけるのかは完全にAutify任せです。Autifyはシナリオのレコーディング時に、要素の様々なメタデータや、周辺の要素の情報を保存しており、これらを元に要素を探索しています。ざっくり説明すると、以下のような情報に基づいて要素を探索し、最も一致度が高かったものを見つけます。

  • タグ名
  • id や class などの属性
  • 文言
  • 親要素や兄弟要素
  • 要素の座標
  • 絶対パス

この方式は、レコードアンドプレイバック方式の欠点であった、記録されたロケーターが意味不明だったり、不安定だったりするのを解消するのに一躍買ってくれます。もしidやclassが不変のものでなかったとしても、文言や周りの要素など別の特徴を元に要素を探索すれば見つかる可能性があります。見つかった要素の情報は都度アップデートされるので、実行すれば実行するほど安定性が高まる可能性があります。

「人の目」を模倣する

visualdiff

それから、現在βテスト中の「ビジュアルリグレッションテスト」について触れておきましょう。この機能は、テスト対象の画面が以前と比べてどのぐらい変わったのかを教えてくれます。例えば、CSSのレイアウト崩れや、文章の変更などを広い範囲で検知するのに役立ちます。これまでは自動化が難しかった「人の目なら一目瞭然」な問題を自動的に検知してくれる……そんな未来は、すぐそこまで来ていますよ!

これからのチャレンジ

最後に、これからAutifyがどんなことをしようと企んでいるのか、ちょっとだけネタバレしましょう。まだ詳細についてお知らせできる段階ではありませんが、要素探索に関するいくつかのアップデートを予定しています。

要素の見た目を使って探索する

WebのE2Eテストでよくある問題は、「見かけは変わってないのに、内部実装の変更に引っ張られてテストが失敗してしまう」というものです。前述のような、様々な情報を元に要素を見つけるというのはこの問題を解決するためのものですが、完全ではありません。例えば、見かけ上は同じ画像だが、画像の読み込み元のURLが変わってしまった場合などは、正しい要素を見つけられなくなる可能性があります。

現在検討中のVisual Locatorという機能は、記録された要素の「見た目」に一致する要素を探索するための機能です。この機能は、おそらく上述のようなトラブルを避け、よりユーザーが意図したものに近い要素を探すようになるでしょう。

よりユーザーの意図に近い要素を探索する

もう一つ、よくある問題として、ユーザーがどのような操作をしようとしたのかの「意図」はテストシナリオには反映されない、というものがあります。例えば、ブログ記事のうち一つをクリックしているとして、クリックしたいのは「特定のタイトルの記事」なのか「一番上の記事」を判別する術はありません。

しかし、Autifyはクリックされた要素の情報を数多く記録しています。その中には、要素がリスト要素の中で何番目に登場したものなのか、なども含まれています。例えば、テストを記録するときに、ユーザーが要素探索のための「ヒント」を与えられるような仕組みがあるとうまく行く可能性があります。この方法は、似たような要素がたくさん存在する場面で有効です。

別の手段として、似たような要素が複数見つかった場合に、テスト結果にいくつかの候補を出しておいて、その中からユーザーが選択できるようにするというものです。選択した候補の特徴量を分析すれば、その要素を特定するためにどの特徴が最も重要なのかがわかります。そうすれば、次からは意図した要素を安定して見つけられるようになるはずです。

まとめ

Autifyは、既存のレコードアンドプレイバックツールへの批判や反省を活かしながら、ユーザーの皆様からのフィードバックを元に、より理想的な形を目指して進化を続けています。 過去に別のレコードアンドプレイバックツールを使って苦い経験をしたことがある人にこそ、Autifyを使って頂きたいです。ご興味がある方は、ぜひ公式サイトから無料のデモリクエストにお申し込みください!


採用イベント開催のお知らせ

2021年10月18日(月)より5夜連続で「Autify Team Talk Session」を開催致します。 Autifyのメンバーたちが日々どんなことを考え、業務を遂行しているかを座談会形式でお伝えするオンラインイベントです。 この記事を読んで興味をお持ちいただいた方はぜひイベントで、Autifyのことを色々聞いてみてください。ご参加お待ちしております。

Autify Team Talk Session 〜Backend / SRE〜

Autify Team Talk Session 〜Frontend / TSE〜

その他開催中の採用イベントはこちら