Slide 1

Slide 1 text

/ / PHP カンファレンス沖縄 2019 めもりー PHPer のための PHPUnit と Selenium を使った
 ブラウザテストのすゝめ © - BASE, Inc.

Slide 2

Slide 2 text

© - BASE, Inc. Who am I? めもりー (@m m r ) BASE 株式会社の基盤チームに所属している エンジニアです。 PHP, TypeScript あたりをメインに触ってい ます。 趣味はバイナリファイルを読むことです

Slide 3

Slide 3 text

© - 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

Slide 4

Slide 4 text

© - BASE, Inc. みなさんテスト書いてますか?

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

© - BASE, Inc. 我々の抱えている課題

Slide 12

Slide 12 text

© - BASE, Inc. 我々の抱えている課題 • JavaScript でレンダリングされるようなフォー ムのテストが⾟い • フロントエンドとバックエンドが密結合なた め、テストが書けない、QA が⾟い • 1 つ実装したら 2 つバグがでる

Slide 13

Slide 13 text

© - BASE, Inc. 課題の解決⽅法

Slide 14

Slide 14 text

© - BASE, Inc. 課題の解決⽅法 • フロントエンドとバックエンドは疎結合にして 対象の関⼼事を減らした上でテストを書くのが 望ましい • とはいえ、いきなりそのテストが書けるかとい うと NO に近い

Slide 15

Slide 15 text

© - BASE, Inc. 課題の解決⽅法 • 段階を踏んで、リファクタリングやリプレイス などを⾏っていく • Selenium を使うことにより、密結合になって いるサービスを分離したり、テストのリファク タリングなどが⾏えるようになる • さらに E E ⽤のテストツールとしても担える

Slide 16

Slide 16 text

© - BASE, Inc. Selenium を導⼊するには?

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

© - BASE, Inc. Selenium で出来ること

Slide 20

Slide 20 text

© - BASE, Inc. Selenium で出来ること • フォーム⼊⼒の⾃動化
 • ページ遷移後のテスト • 各ブラウザ (IE, Firefox, Chrome など)でのレ ンダリング結果の確認 • JavaScript の実⾏

Slide 21

Slide 21 text

© - BASE, Inc. などなど… 上げたらキリがない

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

© - BASE, Inc. Selenium を使うことによって得られる恩恵 • JavaScript で⽣成されるような DOM でもテス トできる • フロントエンドとバックエンドが密結合であっ てもテスト可能である • インテグレーションテストからリグレッション テストの⾃動化が出来る

Slide 24

Slide 24 text

© - BASE, Inc. Selenium を使うことによって得られる恩恵 • 各ブラウザでの表⽰崩れなどをスクリーン ショットを⽐較することにより検知できる • ただし、 reCAPTCHA のような画像認証は難し いので、⼯夫が必要 • Standalone の Node 版の特定のバージョンだ とブラウザが起動できないバグがあるので Java 版を使うのが無難

Slide 25

Slide 25 text

© - BASE, Inc. どういう仕組み?

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

© - BASE, Inc. どうテストを書いていくか

Slide 28

Slide 28 text

© - BASE, Inc. Selenium の導⼊

Slide 29

Slide 29 text

© - BASE, Inc. Selenium の導⼊ • Chrome の Standalone 版の Selenium を使⽤ する 
 ※今回は Headless は使わない • Docker で導⼊するととても楽なので Docker を使⽤する

Slide 30

Slide 30 text

© - BASE, Inc. 今回使うサンプル

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

© - BASE, Inc. はじめかた

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

© - BASE, Inc. composer require facebook/php-webdriver GitHub: https://github.com/facebook/php-webdriver ※ Docker ্Ͱಈ͔͞ͳ͍৔߹͸ɺ Selenium ͷ Standalone ͕ผ్ඞཁͰ͢ɻ

Slide 37

Slide 37 text

© - BASE, Inc. WebDriver の準備

Slide 38

Slide 38 text

© - BASE, Inc. WebDriver の準備

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

© - BASE, Inc. WebDriver の準備 Selenium から実⾏する JavaScript の挙動が安定しない場合は サンドボックスを無効にする

Slide 44

Slide 44 text

© - BASE, Inc. テスト対象のページをつくる

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

© - BASE, Inc. テスト対象のページをつくる

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

© - BASE, Inc. テスト対象のページをつくる added_by_js という名前がある input を JavaScript で
 動的にフォームへ追加する

Slide 49

Slide 49 text

© - BASE, Inc. 実際にテストを書いていく

Slide 50

Slide 50 text

© - BASE, Inc. 実際にテストを書いていく • 2 パターンのテストを書く • added_by_js という名前のパラメータが送ら れてきた場合 • 該当のパラメータが送られてきていない場合

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

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

Slide 71

Slide 71 text

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

Slide 72

Slide 72 text

© - BASE, Inc.

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

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

Slide 75

Slide 75 text

© - BASE, Inc.

Slide 76

Slide 76 text

© - BASE, Inc. エラーのあるページをチェックする • 404 や 500 のあるページを Selenium で検出す る • このチェックを⾏うことでリンク切れの検出 が可能になります • 他にも PHP のバージョンアップなどで動かな いページの検出などの⽤途などにも活⽤でき ます

Slide 77

Slide 77 text

© - BASE, Inc. エラーのあるページをチェックする • Selenium 単体ではステータスコードのチェッ クができないっぽい • そのため、 cURL や Guzzle などステータス コードが取れるアプローチを取る

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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

Slide 81

Slide 81 text

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

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

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

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

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

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

© - BASE, Inc. どういったケースで導⼊したのか? • common.php の何を使っていて何を使ってい ないのか本当に分からない。 • スタートアップだったため QA なんて仕組みは 1 ミリもなかった PHPUnit + Selenium を導⼊して該当箇所の テストを⾃動化して、リファクタリングを⾏う

Slide 92

Slide 92 text

© - BASE, Inc. テストが担保できたため、
 ほぼバグが発⽣することはなくなった

Slide 93

Slide 93 text

© - BASE, Inc. &&

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

© - BASE, Inc. DEMO

Slide 96

Slide 96 text

© - BASE, Inc. まとめ

Slide 97

Slide 97 text

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

Slide 98

Slide 98 text

© - BASE, Inc. Selenium はいいぞ

Slide 99

Slide 99 text

© - BASE, Inc. 以上です

Slide 100

Slide 100 text

© - BASE, Inc. THANK YOU FOR YOUR LISTENING