End-Users2017-12-07機械学習を使ってUI自動テストをサイト間で再利用する機械学習SWETの薦田(@toshiya-komoda)です。今回は第3回目の記事で言及させていただいた機械学習とUIテストに関して実験的に進めている技術開発について紹介させていただこうと思います。この記事で紹介している内容の実装はGitHubにアップロードしていますので、もし興味がある方はこちらも覗いてみていただければと思います。2017第7日目の記事にもなっています。機械学習の実装の中でKerasを用いてます。デモ最初に以下のデモ動画をご覧いただきたいです。会員登録フォームに対する自動テストのデモです。各入力欄に適切な情報を入力しつつ、パスワード欄にだけ'weak'という不正なパスワード文字列を入力して、バリデーションで弾かれることを確認するテストです。Extensionを用いて自動化しています。動画は2倍速にしています。youtu.be一見何の変哲もないテストの動画です。このデモの中では「ページ中の入力欄の意味を機械学習を用いて判別し、適切な値を入力する」ことを行っています。Elementを扱うロジックが存在せず、入力欄へ正しくデータを埋めるロジックがサイトに依存せず流用可能となっています。以下、この技術の詳細についてUIテスト開発の課題のおさらいも含めて、順に説明させていただきます。UIテストにおけるDOM操作とその課題まずは、そもそものUIテスト開発における課題のおさらいです。Elementに埋め込んでおくテストコード側で埋め込んだIDを用いて、テストロジックを記述するというフローになります。この結果として、テスト実装者がテスト対象ページのDOMの詳細を理解しなければならないテスト対象ページのDOMの変更で容易にテストが壊れるテストロジックがテスト対象ページのDOMに密結合するため、テストコードの再利用性が乏しいなどの問題が発生します。一般的なウェブアプリケーションにとって、UIの変更頻度が比較的高いことを考えるとこれらのUIテストコードの特性が、テストの開発コスト・運用コストを増大させてしまうことは想像できるかと思います。UIテストコードとテスト対象のDOMを疎結合にするでは、どういったことができると嬉しいのかについて簡単な例で考えてみます。今、サイトAの会員登録ページと、サイトBの会員登録ページがあるとします。2つのサイトで同じテストケース「会員登録ページのフォームを埋めて、次の画面に進む」を自動化したいとします。サイトA、サイトBでもちろんフロントエンドのコードは異なるため、現状ではそれぞれのページにカスタマイズされたUIテストコードを個別に書くしかありません。ここで、もし個々のサイトをUIテスト実装で必要な程度にうまく抽象化してくれるレイヤが存在したとしたらどうでしょう?この状況を表現したのが以下の図になります。同じテストケースを自動化する場合のみとはいえ、サイトA・サイトBに対して、抽象レイヤを挟むことでテストコードを再利用できます。この抽象レイヤがUIの細かい詳細を吸収してくれるのであれば、細かいUIの変更によってテストが壊れる問題も緩和できると期待できます。ここで、具体的にどのような操作をどの程度の粒度で抽象化すればよいか、という問題はテストケースに依存します。このため、どのように抽象化を行うかを一般的に議論することは難しい問題といえますが、冒頭のデモの例では「該当ページ中の入力欄が入力を求めている値の意味」を抽象化した例といえます。このようなアプローチではサイト固有の仕様をテストすることは難しく、UI自動テストの全てのニーズを捉えることは難しいでしょう。限定的なテストケースに限られるとしても、UIテストの導入・メンテナンスコストを大きく削減できることからこのようなアプローチが有効であるケースはあると考えています。Elementの意味を推定するそれでは、UIテスト設計における抽象化の問題をどのように機械学習の問題に置き換えたのかについて説明していきます。冒頭のデモは以下の論文で述べられている手法をベースにしつつ、細かいところを自分たちで試行錯誤しつつ作成したデモです。機械学習でいうところの多値分類問題として問題を定式化し、解くことで実現される具体的には、自然言語に対して開発されてきた機械学習の手法を、よしなにHTMLに対して適用してやるとうまくいくというものです。HTMLの文字列を見てその意味やページ上での役割を推定するということは、まさに前項で説明したDOMの抽象化レイヤの役割そのものです。Elementの分類問題を以下のように定式化しました。登場人物は以下のようになります。同じ機能を提供するテストページの集合。複数のサイトにまたがって存在している。ElementのHTML文字列。分類問題の入力値となる。テスト対象としてElementの意味を表すラベル。分類問題の出力値となる。ありうるトピックラベル全体の有限集合。抽象化したいテストケースごとに定義されます。HTMLを入力として、トピックラベルを出力とする多値分類器が作れれば良いことになります。定式化の具体例を用いた説明を記事の最後に補足として付記していますので、詳細に興味のある方はそちらも御覧ください。教師データの半自動的な収集さて、前節で教師ありの分類問題としての定式化ができました。次は実際に意味のある教師データを集めることが必要です。Elementに対応するHTML文字列を抽出して、これらに適切なトピックラベルをつけていくという作業を行う必要があります。この問題を解決するために、以下のようなアプローチを取りました。最初に小さなサンプル数で良いので手動で教師データを作る。この教師データを用いてトピック分類器をつくる。この時点では、推定精度は高くない。このトピック分類器を用いて、半自動的に教師データを収集するスクリプトを作る。半自動的に作られた教師データの正誤判定のみ人間が行う。このような収集の半自動化を行うことで、素直に手動で教師データを作成する場合に比べて約10倍の速度で学習データを集められるようになりました。最後にトピックラベルの推定精度を評価してみます。冒頭のデモで用いている「会員登録ページにおいて入力フォームに値を入力する」というユースケースに絞って実験を行っています。教師データコーパスとなるウェブサイトは、Google検索に「会員登録」と入力して出てきた200サイト分の会員登録ページを用いています。会員情報を実際に入力するページへの導線はサイトごとに異なるので、ここは手動で入力ページまでいってデータを集めました。Elementが10個以上存在するもののみを用いて評価を行っています。Elementに対して、意味のある学習を行うことはそもそも難しいからです。Elementを用いてモデルのバリデーションを行っています。用いた教師データはトレーニングスクリプトと合わせて、冒頭のGitHub上で公開しています。冒頭のデモ中ではテスト対象ページの教師データを取り除いた上で学習させたモデルを用いています。解くべき問題は自然言語処理を用いた多値分類問題です。比較的扱いが簡単だった以下の2つの分類器を用いました。ロジスティック回帰(以下、LSI)ライブラリにgensimとsklearnを用いて実装しました。圧縮後の次元数は500です。単純なニューラルネットワーク(以下、NN)ライブラリにkerasを用いて実装しました。全結合層を1つ重ねた場合(NN1)と2つ重ねた場合(NN2)で評価しています。学習時のエポック数はNN1、NN2ともに決め打ちで800epochs分学習させています。目分量ですが800epochs程度でだいたい学習が収束したように見えていました今回用いたニューラルネットワークはもっともシンプルといって良い単純なネットワークかと思いますが、kerasのmodel.summary()の出力を記載しておきます。結果は以下のようになりました。テストセットをランダムに5回ずつ変えて平均を計測しています。%今、トピックラベルの取りうる値は18通りあり、ランダムに予測した場合の正答率は5.6%程度となることを考えると悪くない精度が出ていると考えられます。TensorBoardで表示したニューラルネットワークの学習曲線は以下のようになっていました。NN1(全結合1層)の学習過程(TensorBoard)NN2(全結合2層)の学習過程(TensorBoard)全結合2層の学習では過学習が起きてしまっているように見えるなど、ニューラルネットワークに関してはもう少しチューニングの余地がありそうですが今回は深追いしていません。精度の良かった全結合2層の場合に、具体的にどのような場合に推定が失敗しているかを見てみましょう。addressこのケースではサイトの変数名の付け方に正解を予測するための情報がほとんどなく、人間が見たとしてもこのHTMLが住所の入力欄であることを判定するのは難しいといえます。入力欄のHTMLだけでなく関連するDOM要素(labelなど)を入力として与えるなど入力の定式化自体を考え直さないといけないと考えられます。userName今回は教師データ中に含まれる単語のみから辞書を作成し、単語列をベクトルに変換しています。このため、辞書内の単語数は3000強しかありません。従って、このケースで現れている「オナマエ」という日本語の文字列が「名前」と同じ意味であることを判定することができなかったと考えられます。Wikipediaなど一般的なコーパスから作成した単語の分散表現を組み合わせることで精度を改善できる可能性があると考えています。その他、予測すべきトピックラベルが教師データ中にあまり存在せず、教師データが足りていないように見えるケースもありました。デモおよび推定精度の評価では会員登録ページの入力フォームを埋めるというテストケース。HTMLをレイアウト情報として利用するウェブページがテスト対象。いう2つの条件を仮定しています。一方で実用的にはより広い範囲のユースケースでの適用可能性を検討する必要があります。複雑なテストケースに拡張できるかどうかを検討する必要があります。複数のページにまたがるテストケースを扱うシングルページアプリケーションのようにより複雑な構造を持つページを扱うテストの成功・失敗を判定するロジックを学習させるといった課題が挙げられます。この手法自体の適用範囲はHTMLに限定されるものではありません。このため、HTMLとは異なるフォーマット(XMLなど)を用いてレイアウト情報を管理しているモバイル・アプリケーションの世界への適用も試してみたい課題となります。まとめ今回は、機械学習を用いてUIテストコードをサイトをまたいで再利用する技術について紹介させていただきました。課題欄でも述べた通り、まだまだ検討すべき課題が多くある状態です。SWETではこうした技術的チャレンジを楽しめる方を随時募集しています。仮想的で簡単なフォームの例で考えると、以下のようになります。value="登録"></form>トピックラベル集合。このリストは抽象化したいテスト対象ページに合わせて、手動で作成する必要があります。"email_input""password_input""password_confirm_input""service_term_input""form_submit_button"ElementのHTML。value="登録">トピックラベルの列。この値がいわゆる正解データ、教師データと呼ばれるものになります。各値はトピックラベル集合の要素のどれか1つが入ります。番号が対応するElementのHTMLにひも付きます。"form_submit"HTML文字列の単語列への分解さらにElementのHTMLは、HTMLパーサを用いて意味のある単語のみを抽出した単語列として扱います。この後、日本語が含まれている場合は形態素解析も行います。先の例のElementのHTMLの列は以下のように変換されます。"登録"]この形までくれば、あとは完全に自然言語処理の世界の問題として扱うことができます。ラベル付けについての補足この手法ではラベル付けに任意性が存在します。ユースケースごとにモデルを学習することを想定しているので当然といえば当然です。これは最終的にどこまでテストをしたいのかに依存して変わるものです。(細かい分類)の2種類のラベル付けに対して評価を行っています。'telephone_number_last'とするかでトピックラベルの付け方を変えるということです。後者のラベル付けの方は分類がより詳細なため、分類問題としては難しくなります。前者のような粗いラベル付けでも、テスト実装時の工夫でテストを実装することは可能です。'telephone_number'と推定されたElementの数を数えて値を分割して入力するなどが考えられます。本文中の評価では、冒頭のデモを作成するのに粗いラベル付けで十分だったため粗い方のラベル付けを用いた場合の精度を評価として示しています。参考までですが、この節で説明した後者の細かいラベル付の場合の推定精度をいかに示します。%精度は前者の粗いラベル付けの場合と比べて10%程度低くなり、今回用いたものよりもさらに洗練された分類器が必要になる事がわかっています。07:00機械学習を使ってUI自動テストをサイト間で再利用するTweet関連記事2019-12-16SWETの2名が執筆に加わった「iOSテスト全書」が一般発売されましたSWETグループ、iOS自動テスト領域チームの平田(tarappo)です...2019-06-24SWETグループが考える形式手法の現在とこれからの可能性こんにちは、SWETの鈴木穂高(@hoddy3190)です。JUnit5でUIテストを書こうこんにちは。SWETチームの@zhailujiaです。J...2019-04-26テストの社内普及のための取り組みとして、Androidテストハンズオンを実施しましたこんにちは、SWETグループの田熊です。2days開催レポートはじめまして、SWETの井口(@hisa9chi)です。(1)リンクプライバシーポリシースターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。