PHPer のための PHPUnit と Selenium を使った
ブラウザテストのすゝめ

218473ff7abad0fcd72865da2b23bb5b?s=47 memory
October 12, 2019

PHPer のための PHPUnit と Selenium を使った
ブラウザテストのすゝめ

- PHP Conference Okianwa 2019 in Japan

English Title:
Evolution for Browser Testing with the PHPUnit and the Selenium for PHP users.

218473ff7abad0fcd72865da2b23bb5b?s=128

memory

October 12, 2019
Tweet

Transcript

  1. / / PHP カンファレンス沖縄 2019 めもりー PHPer のための PHPUnit と

    Selenium を使った
 ブラウザテストのすゝめ © - BASE, Inc.
  2. © - BASE, Inc. Who am I? めもりー (@m m

    r ) BASE 株式会社の基盤チームに所属している エンジニアです。 PHP, TypeScript あたりをメインに触ってい ます。 趣味はバイナリファイルを読むことです
  3. © - BASE, Inc. 登壇実績 • PHP で JVM を実装して

    Hello World を出⼒するまで • builderscon tokyo • https://speakerdeck.com/memory /php-de-jvm-woshi-zhuang-site- hello-world-wochu-li-surumade • (前職) PHP で JVM (Java Virtual Machine) に⼊⾨する • PHPerKaigi • https://speakerdeck.com/memory /phperkaigi- • (前職) 開発期間 2 ヶ⽉で Elasticsearch をプロダクトに使って リリースした話 • PHP カンファレンス仙台 2019 • https://speakerdeck.com/memory /php-conference-sendai- - presentation-slides
  4. © - BASE, Inc. みなさんテスト書いてますか?

  5. © - BASE, Inc. 歴史のあるサービスのテスト書くの
 ⾟くないですか?

  6. © - BASE, Inc. でも、⼤丈夫です

  7. © - BASE, Inc. そう、PHPUnit と Selenium を
 使えばね

  8. © - BASE, Inc. 本⽇のお品書き

  9. © - BASE, Inc. 本⽇のお品書き 課題の解決⽅法 我々の抱えている課題 Selenium を導⼊するには?

  10. © - BASE, Inc. 本⽇のお品書き どうテストを書いていくか Selenium を使うことによって得られる恩恵 実際に Selenium

    を導⼊して運⽤した話
  11. © - BASE, Inc. 我々の抱えている課題

  12. © - BASE, Inc. 我々の抱えている課題 • JavaScript でレンダリングされるようなフォー ムのテストが⾟い •

    フロントエンドとバックエンドが密結合なた め、テストが書けない、QA が⾟い • 1 つ実装したら 2 つバグがでる
  13. © - BASE, Inc. 課題の解決⽅法

  14. © - BASE, Inc. 課題の解決⽅法 • フロントエンドとバックエンドは疎結合にして 対象の関⼼事を減らした上でテストを書くのが 望ましい •

    とはいえ、いきなりそのテストが書けるかとい うと NO に近い
  15. © - BASE, Inc. 課題の解決⽅法 • 段階を踏んで、リファクタリングやリプレイス などを⾏っていく • Selenium

    を使うことにより、密結合になって いるサービスを分離したり、テストのリファク タリングなどが⾏えるようになる • さらに E E ⽤のテストツールとしても担える
  16. © - BASE, Inc. Selenium を導⼊するには?

  17. © - BASE, Inc. そもそも Selenium とは?

  18. © - BASE, Inc. Selenium とは? • Web アプリケーションのテストツールのこと •

    テストツールではあるが、ブラウザにレンダリ ングされている画⾯のスクリーンショットを 撮ったりもできる • PHP で使⽤するには Facebook 社が公開してい る facebook/webdriver を⽤いる GitHub: https://github.com/facebook/php-webdriver
  19. © - BASE, Inc. Selenium で出来ること

  20. © - BASE, Inc. Selenium で出来ること • フォーム⼊⼒の⾃動化
 • ページ遷移後のテスト

    • 各ブラウザ (IE, Firefox, Chrome など)でのレ ンダリング結果の確認 • JavaScript の実⾏
  21. © - BASE, Inc. などなど… 上げたらキリがない

  22. © - BASE, Inc. Selenium を使うことによって
 得られる恩恵

  23. © - BASE, Inc. Selenium を使うことによって得られる恩恵 • JavaScript で⽣成されるような DOM

    でもテス トできる • フロントエンドとバックエンドが密結合であっ てもテスト可能である • インテグレーションテストからリグレッション テストの⾃動化が出来る
  24. © - BASE, Inc. Selenium を使うことによって得られる恩恵 • 各ブラウザでの表⽰崩れなどをスクリーン ショットを⽐較することにより検知できる •

    ただし、 reCAPTCHA のような画像認証は難し いので、⼯夫が必要 • Standalone の Node 版の特定のバージョンだ とブラウザが起動できないバグがあるので Java 版を使うのが無難
  25. © - BASE, Inc. どういう仕組み?

  26. © - BASE, Inc. PHPUnit PHP Container Selenium Standalone Selenium

    Container Chrome Facebook WebDriver どういう仕組み? Web Page ( ) Hub につないだり、JSの
 実⾏や要素の探索などをする (2) セッションを作成する (3) 現在のレンダリングの
 状態を取得 (4) セッションの情報を返す ( ) PHPUnit 側に
 実⾏結果を返す (5) 実⾏結果を返す
  27. © - BASE, Inc. どうテストを書いていくか

  28. © - BASE, Inc. Selenium の導⼊

  29. © - BASE, Inc. Selenium の導⼊ • Chrome の Standalone

    版の Selenium を使⽤ する 
 ※今回は Headless は使わない • Docker で導⼊するととても楽なので Docker を使⽤する
  30. © - BASE, Inc. 今回使うサンプル

  31. © - BASE, Inc. 今回使うサンプル • 今回使うサンプルは下記の通り

  32. © - BASE, Inc. サンプルコードはこちら https://github.com/memory-agape/php-conference- webdriver-testing

  33. © - BASE, Inc. PHPUnit にテストを書いていく

  34. © - BASE, Inc. はじめかた

  35. © - BASE, Inc. たったこれだけ

  36. © - BASE, Inc. composer require facebook/php-webdriver GitHub: https://github.com/facebook/php-webdriver ※

    Docker ্Ͱಈ͔͞ͳ͍৔߹͸ɺ Selenium ͷ Standalone ͕ผ్ඞཁͰ͢ɻ
  37. © - BASE, Inc. WebDriver の準備

  38. © - BASE, Inc. WebDriver の準備

  39. © - BASE, Inc. WebDriver の準備 Selenium の Hub を指定

  40. © - BASE, Inc. WebDriver の準備 Chrome のバイナリまでの絶対パスを指定する

  41. © - BASE, Inc. WebDriver の準備 ローカルだとSSL の認証の問題があるため エラーを無視するようにする

  42. © - BASE, Inc. WebDriver の準備 リンク先の⽣存判定をしないようにする

  43. © - BASE, Inc. WebDriver の準備 Selenium から実⾏する JavaScript の挙動が安定しない場合は

    サンドボックスを無効にする
  44. © - BASE, Inc. テスト対象のページをつくる

  45. © - BASE, Inc. テスト対象のページをつくる • JavaScript でフォーム内に DOM を追加するよ

    うなよくあるページにする • 該当のフォームの値が送られて来ていない場 合、エラーを表⽰するようにする
  46. © - BASE, Inc. テスト対象のページをつくる

  47. © - BASE, Inc. テスト対象のページをつくる 送られていなければ
 「added_by_js が送られてきていません」と
 表⽰をする。 added_by_js

    というパラメータが送られてきていれば
 「⼊⼒されたメッセージ」+「が送られてきました」 と表⽰する
  48. © - BASE, Inc. テスト対象のページをつくる added_by_js という名前がある input を JavaScript

    で
 動的にフォームへ追加する
  49. © - BASE, Inc. 実際にテストを書いていく

  50. © - BASE, Inc. 実際にテストを書いていく • 2 パターンのテストを書く • added_by_js

    という名前のパラメータが送ら れてきた場合 • 該当のパラメータが送られてきていない場合
  51. © - BASE, Inc. パラメータが正常に送られてきた場合

  52. © - BASE, Inc. パラメータが正常に送られてきた場合

  53. © - BASE, Inc. パラメータが正常に送られてきた場合 ページに接続する

  54. © - BASE, Inc. パラメータが正常に送られてきた場合 DOM がレンダリングされるのを待つ

  55. © - BASE, Inc. パラメータが正常に送られてきた場合 input の要素を探す

  56. © - BASE, Inc. パラメータが正常に送られてきた場合 Hello World! という⽂字列を⼊⼒する

  57. © - BASE, Inc. パラメータが正常に送られてきた場合 Submit ボタンを探す

  58. © - BASE, Inc. パラメータが正常に送られてきた場合 Submit ボタンをクリック (onSubmit を発⽕)させる

  59. © - BASE, Inc. パラメータが正常に送られてきた場合 ページが切り替わるのを待つ

  60. © - BASE, Inc. パラメータが正常に送られてきた場合 表⽰されるメッセージの要素を探す

  61. © - BASE, Inc. パラメータが正常に送られてきた場合 表⽰されている⽂字列が正しいかどうかをテストする

  62. © - BASE, Inc. パラメータが送られてきていない場合

  63. © - BASE, Inc. パラメータが送られてきていない場合

  64. © - BASE, Inc. パラメータが送られてきていない場合 ページに接続する

  65. © - BASE, Inc. パラメータが送られてきていない場合 DOM がレンダリングされるのを待つ

  66. © - BASE, Inc. パラメータが送られてきていない場合 JavaScript で動的に追加された input を消す

  67. © - BASE, Inc. パラメータが送られてきていない場合 Submit ボタンを探す

  68. © - BASE, Inc. パラメータが送られてきていない場合 Submit ボタンをクリック (onSubmit を発⽕)させる

  69. © - BASE, Inc. パラメータが送られてきていない場合 ページが切り替わるのを待つ

  70. © - BASE, Inc. パラメータが送られてきていない場合 表⽰されている⽂字列が正しいかどうかをテストする

  71. © - BASE, Inc. うまくいくと…

  72. © - BASE, Inc.

  73. © - BASE, Inc. テストが通って、 Selenium が
 正常に動いていることがわかります。

  74. © - BASE, Inc. エラーのあるページの
 チェックをする

  75. © - BASE, Inc.

  76. © - BASE, Inc. エラーのあるページをチェックする • 404 や 500 のあるページを

    Selenium で検出す る • このチェックを⾏うことでリンク切れの検出 が可能になります • 他にも PHP のバージョンアップなどで動かな いページの検出などの⽤途などにも活⽤でき ます
  77. © - BASE, Inc. エラーのあるページをチェックする • Selenium 単体ではステータスコードのチェッ クができないっぽい •

    そのため、 cURL や Guzzle などステータス コードが取れるアプローチを取る
  78. © - BASE, Inc. エラーのあるページをチェックする

  79. © - BASE, Inc. エラーのあるページをチェックする ページに接続する

  80. © - BASE, Inc. エラーのあるページをチェックする アンカーリンクを取得する

  81. © - BASE, Inc. エラーのあるページをチェックする Guzzle の準備をする

  82. © - BASE, Inc. エラーのあるページをチェックする それぞれのアンカーリンクを処理する

  83. © - BASE, Inc. エラーのあるページをチェックする アンカーリンクの href 属性を取得する

  84. © - BASE, Inc. エラーのあるページをチェックする Guzzle で該当の URL にアクセスしてステータスコードを取得する

  85. © - BASE, Inc. エラーのあるページをチェックする ステータスコードが 400 以上の場合は該当のURLを
 含めたエラーメッセージを表⽰する

  86. © - BASE, Inc. 実際に Selenium を導⼊して
 運⽤した話

  87. © - BASE, Inc. どういったケースで導⼊したのか?

  88. © - BASE, Inc. (注)BASE の話ではありません

  89. © - BASE, Inc. どういったケースで導⼊したのか? • 1 つ実装すると 2 つバグがでる状態だった。

    • フレームワークを使っているはずなのに、⼀部 の機能がなぜか、フレームワーク外の common.php 書かれていた。 • しかもその common.php はすべてのファイル に require されていた • テスト⾃体存在してない
  90. © - BASE, Inc. どういったケースで導⼊したのか?

  91. © - BASE, Inc. どういったケースで導⼊したのか? • common.php の何を使っていて何を使ってい ないのか本当に分からない。 •

    スタートアップだったため QA なんて仕組みは 1 ミリもなかった PHPUnit + Selenium を導⼊して該当箇所の テストを⾃動化して、リファクタリングを⾏う
  92. © - BASE, Inc. テストが担保できたため、
 ほぼバグが発⽣することはなくなった

  93. © - BASE, Inc. &&

  94. © - BASE, Inc. 謎の common.php から
 完全ではないが分離していけた

  95. © - BASE, Inc. DEMO

  96. © - BASE, Inc. まとめ

  97. © - BASE, Inc. まとめ • Selenium は PHP でも動かせるし、PHPUnit

    と⼀緒に使うことができる • テストが書きづらい状態でも Selenium を使え ば、ある程度は担保することができるようにな る • QA が難しい環境でも Selenium である程度担 保できる
  98. © - BASE, Inc. Selenium はいいぞ

  99. © - BASE, Inc. 以上です

  100. © - BASE, Inc. THANK YOU FOR YOUR LISTENING