WebDriverで、新規会員登録フローのE2Eブラウザテストを自動化してみた。ハウテレビジョン開発者ブログスマートフォン用の表示で見るハウテレビジョン開発者ブログ『外資就活ドットコム』を日夜開発している技術陣がプログラミングネタ・業務改善ネタ・よしなしごとについて記していきます。WebDriverで、新規会員登録フローのE2Eブラウザテストを自動化してみた。エンジニアの@bumcruです。Qiitaの「Selenium/Appium」アドベントカレンダー9日目の記事です。去る10月に行われた開発合宿、今年のテーマは「自動化」でした。僕が選んだお題は「Seleniumでのブラウザテスト自動化」です。ハマりやすいポイント、その解決法をご紹介します。テスト計画を立て、きちんとテストを行ってから納品します。テストを手作業で行う方が工数が少なく済む場合が多く、テストを自動化するメリットがほとんど無いケースも間々あります。テストの質を一定に保つのも困難です。3ヶ月もしない内に気が狂ってピクニックに出かけてしまうでしょう。サービスの成長やマネタイズに密接に関わっている部分からテストを作成するのが良いのではないでしょうか?ほとんどのWebサービスにとって、最も重要な導線の1つに「会員登録」があります。そのサービスの成長規模を示す最も分かりやすい指標となるからです。会員登録フローで何らかの異常が発生し新規登録ができなくなっていたら、サービスにとって大打撃となることは間違いありません。「外資就活ドットコム」の会員登録フローは手作業でやると7分以上もかかります。ユーザーの皆さん、よく登録してくれているな...。そもそもテストする人によって、かかる時間も精度もマチマチでは、せっかくテストをしても全く安心感がありませんね。SeleniumでできることSeleniumとは何か。❝ブラウザで出来る大体のことをコード化するためのライブラリ❝です。*2といった基本的な操作を組み合わせたテストコードを、RubyやJava、PHPなどの多様な言語で書き、CLIから実行することができます。コマンド一発で同じ内容のテストを全て自動で再現でき、成功か失敗かを簡単に確認できるのです。Seleniumには他にも、Firefox、Chrome、IEなどのクロスブラウザテストAndroidやiOSなどのモバイルブラウザテスト画面のスクリーンショットを画像として保存ヘッドレス化してブラウザを表示せずに実行し、CIに組み込むなどなど、豊富な機能が用意されており、開発コミュニティも活発です。ベストプラクティス』を読み進める形で開発を行いました。備えあれば憂いなしです。同書ではFirefoxとRubyを使ってサンプルが作成されているため、使用言語はRuby。ちなみに、Firefox以外のブラウザを使う場合は別途ドライバーをインストールする必要があり、少し手間がかかるようです。テストシナリオ今回の目的は、新規会員登録したユーザーが登録したアカウントで正常にログインできることを確認することです。...なかなかゴツいですね。完了画面へ遷移した後は、ログイン画面へリダイレクト作成したばかりのアカウントでログインログイン後のページに登録したユーザ名が表示されていることを確認で、晴れてテスト成功となります。準備など前提として、RubyFirefoxのインストールは終わってるものとします。Selenium::WebDriver.for(:firefox)で、Objectを生成するだけです。上述の新規会員登録フローを突破するテストを書くには、いくつか超えなければならない関門があります。ベーシック認証テスト実行に本番環境を使うのはちょっと...、という方も多いでしょう。テストはそこで実行することにしました。普通にテストを動かすとブラウザを起動した後にベーシック認証のユーザー名とパスワードを入力するダイアログが表示されて止まってしまいます。認証ダイアログを表示しないようにすることができます。一工夫しないとバリデーションに引っかかってしまい次の画面に進めずテストが中断してしまいます。これは、タイムスタンプを含めたメールアドレスをテストごとに生成するようにすることで(ほぼ)解決できます。そのURL以外からだと登録画面にアクセスできない、という仕様はよくあるパターンです。該当メールをクリックメール本文のワンタイムURLを取得ということも難しくありません。「@」以前の「.」(ドット)は認識されない「+」と「@」の間の文字列は認識されないというものがあります。その全てを同じメーラで受信することが出来るのです。これで何回でもテストを走らせることができますね。ステージングサーバが送信したメールは本物のアドレスには届かず、代わりに全てのメールをMailCatcherのメーラで確認できるようになっています。ワンタイムURLを取得することができます。開発合宿での成果をお見せしてしまいます。↓コマンドファイルを叩き、ブラウザが起動する↓画面中の入力項目を自動で埋め尽くす最初にcommandファイルをクリックしてからは、マウスにもキーボードにも一切触れていません。恐るべきスピードで入力欄を埋め尽くしていますが、もちろん早送りなどもしていません。(全編を見たい人はこちら。100秒のGIFアニメです。)ハマりがちなポイントTest::Unitが使えない自分がRuby初心者ということもあり、以下の警告で盛大に出鼻を挫かれました。"minitest/autorun"'調べてみると、test-unitはRuby用のxUnit系の単体テストフレームワークです。1.9.1からはminitestというフレームワークが標準添付されています。(引用元)...、とのこと。Minitest::Testと読み替えることで解決です。2泊3日の間、僕がハマりにハマったポイントとその対処法をいくつかご紹介します。リッチなセレクトボックス画像のような、少しリッチなセレクトボックスでは注意が必要です。検索ワードを入力すると、選択肢が動的に絞り込まれるというものです。IDを指定してもNoSuchElementErrorというエラーが出てテストが失敗します。「あれ、さっきとID変わってるやん!」という驚愕の真実に気が付きます。jQuery系のライブラリを利用して実装されており、選択肢に振られているIDは便宜上振られているに過ぎないようでした。CSSパスで指定しやすくしてから選択肢の要素をクリックする、という方法で切り抜けました。非エンジニアのメンバーにテストデータを作ってもらう時にも作りやすくなりますね。「IDもアテにならないな...」という、良い勉強になりました。「一意のセレクタ」でも指定できない?MailCatcherのメールの本文をクリックしようと思った時のことです。今受信したばかりのメール1件のみを表示するところまでは上手くいきました。表示されているメールの本文をクリックしようとしても、NoSuchElementErrorが出てしまいます。この機能を使って取得した一意なCSSパスを使っても上手く行きません。DOMを読み解いていくと、MailCatcherの本文を表示する領域は<iframe>の中に入れ子になっています。Seleniumで<iframe>内部の要素を指定する場合、以下のように向いているフレームを切り替える必要があります。WebDriverでの自動ブラウザテストを導入するにあたり、アプリケーション側でも対応すべきことがありそうです。「セレクタ(ロケータ)を書くのが大変!」ということでした。CSSやXPathでセレクタを書くと長くなってしまい、後から見てもどの要素のセレクタなのか分からないことが多々ありました。何らかの事情によりIDを付けられない場合は、例えばdata-seleniumなどのカスタムデータ属性を付ける、という方法がベターのようです。対象の項目が画面に表示されるまで、きちんと待ってあげる必要があります。WebDriverには、処理完了を待つためのWaitクラスも用意されていますが、ここでは自分で完了条件を記述する必要があります。定義した完了条件が不十分でテストが中断してしまったりということは十分に考えられます。そこで、同書ではjQueryを使った方法が有効だと紹介されています。jQueryなら標準のメソッドやプロパティを使うことで、Ajaxやアニメーション処理の完了を簡単に確認することが可能です。jQueryを導入した方がSeleniumでのテストを書くのが楽になる場面は多いでしょう。しても難しい場合は、上述のWaitクラスを使うしかないのかもしれません。サービスに異常が発生した場合、迅速に検知することができます。テストの量が膨大になってきたら、PhantomJSなどのヘッドレスブラウザを使うことで、実行時間を短縮することも出来るようです。要素を指定して入力/クリックする、などの処理は、jQueryに近い感覚で書くことができます。工夫次第であらゆるシステムのE2Eテストに導入できると思います。このエントリーを読んだ皆さんならきっと、つまずくことなく、もっと速くテストを書けることでしょう。自分の得意な言語で書けば学習コストもそれほど高くありません。眺めているだけで心が震えます!!皆さんもこの爽快感を味わったら、テストを書くのが好きで好きで堪らなくなるでしょう。ベストプラクティス』は、かなりの名著だと思います。日本版の初版が出たのは2015年9月で、かなり最近です。良いテストの書き方をスムーズに理解することができました。それぞれの利点と欠点がわかりやすく解説されており、自分たちの開発規模に応じてどのパターンを採り入れるのがベストなのかを考えさせてくれます。Windows、MacそれぞれのCLIの起動方法から、Rubyの基本的な文法まで手厚くレクチャーしてくれます。WebDriverを始めようと考えているなら、一度読んでおくと習得がより速くなると思うのでオススメです。*1:Seleniumには1系と2系があります。Webdriver」と呼ばれており、単に「Webdriver」とも呼びます。1系と2系とではかなり仕様が異なっており、本エントリーでは常に2系を指しています。Webdriver自身に、テストツールとしての機能はありません。テスト可否の判定は、JUnitやPHPUnitなどの言語ごとに用意されたテストライブラリと組み合わせて行います。WebDriverの標準メソッドをラップしたヘルパーメソッドです。標準メソッドとやや異なりますが、何をしてるのかは理解できるはずです。Explorerでは、セキュリティ上の理由によりこの方法でBASIC認証は突破できないようです。文字列として取得してから「ユーザ名:パスワード@」を挿入し、URLを書き換える必要があります。WebDriverで、新規会員登録フローのE2Eブラウザテストを自動化してみた。Tweet関連記事2015-10-27【画像57枚】開発合宿にいってきたぜ!【合宿当日編】どうもこんにちは。エンジニアのvsannaです。データ解析本部のn_maoです。Chromeマリオカート8でレートが7000を超えた津田です。ハウテレビジ...2014-09-05nginxのアクセスログにユーザーIDを記録する方法こんにちは。来週末のPyConが待ち遠しくてたまらない祖山です。GTMの概要...フロントエンド中心に担当している津田(id:YTsuda)です。はてなブログPro『外資就活ドットコム』の開発チームです。技術ネタ・プログラミングネタ等々書いていきます。業務未経験からエンジニアになって半年を振り返るDocker初心者がRails+MySQLの環境構築をDockerでやってみた月別アーカイブ検索はてなブログをはじめよう!howtvさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。