Slide 1

Slide 1 text

退屈なブラウザテストは 退屈なブラウザテストは 退屈なブラウザテストは 退屈なブラウザテストは 退屈なブラウザテストは 退屈なブラウザテストは CodeceptJS にやらせよう CodeceptJS にやらせよう CodeceptJS にやらせよう CodeceptJS にやらせよう CodeceptJS にやらせよう CodeceptJS にやらせよう 末村 拓也 @ 株式会社オープンロジ 末村 拓也 @ 株式会社オープンロジ 末村 拓也 @ 株式会社オープンロジ 末村 拓也 @ 株式会社オープンロジ 末村 拓也 @ 株式会社オープンロジ 末村 拓也 @ 株式会社オープンロジ 1 / 72

Slide 2

Slide 2 text

はじめまして はじめまして はじめまして はじめまして はじめまして はじめまして 末村 拓也(すえむら たくや) 末村 拓也(すえむら たくや) 末村 拓也(すえむら たくや) 末村 拓也(すえむら たくや) 末村 拓也(すえむら たくや) 末村 拓也(すえむら たくや) 物流スタートアップ「OPENLOGI 」のQA エンジニア 物流スタートアップ「OPENLOGI 」のQA エンジニア 物流スタートアップ「OPENLOGI 」のQA エンジニア 物流スタートアップ「OPENLOGI 」のQA エンジニア 物流スタートアップ「OPENLOGI 」のQA エンジニア 物流スタートアップ「OPENLOGI 」のQA エンジニア です です です です です です まんがとヒトカラがすきです まんがとヒトカラがすきです まんがとヒトカラがすきです まんがとヒトカラがすきです まんがとヒトカラがすきです まんがとヒトカラがすきです                   2 / 72

Slide 3

Slide 3 text

エンジニア歴短めです エンジニア歴短めです エンジニア歴短めです エンジニア歴短めです エンジニア歴短めです エンジニア歴短めです 新卒から5 年間ぐらいフォークリフト乗ってました 新卒から5 年間ぐらいフォークリフト乗ってました 新卒から5 年間ぐらいフォークリフト乗ってました 新卒から5 年間ぐらいフォークリフト乗ってました 新卒から5 年間ぐらいフォークリフト乗ってました 新卒から5 年間ぐらいフォークリフト乗ってました エンジニアを名乗り始めたのはここ3 年ぐらい エンジニアを名乗り始めたのはここ3 年ぐらい エンジニアを名乗り始めたのはここ3 年ぐらい エンジニアを名乗り始めたのはここ3 年ぐらい エンジニアを名乗り始めたのはここ3 年ぐらい エンジニアを名乗り始めたのはここ3 年ぐらい 3 / 72

Slide 4

Slide 4 text

バズりました バズりました バズりました バズりました バズりました バズりました https://qiita.com/tsuemura/items/56ba9942565963858d8f https://qiita.com/tsuemura/items/56ba9942565963858d8f https://qiita.com/tsuemura/items/56ba9942565963858d8f https://qiita.com/tsuemura/items/56ba9942565963858d8f https://qiita.com/tsuemura/items/56ba9942565963858d8f https://qiita.com/tsuemura/items/56ba9942565963858d8f 4 / 72

Slide 5

Slide 5 text

今日はこの記事で登場した技術を使って 今日はこの記事で登場した技術を使って 今日はこの記事で登場した技術を使って 今日はこの記事で登場した技術を使って 今日はこの記事で登場した技術を使って 今日はこの記事で登場した技術を使って ブラウザテスト自動化を ブラウザテスト自動化を ブラウザテスト自動化を ブラウザテスト自動化を ブラウザテスト自動化を ブラウザテスト自動化を 圧倒的に効率化していきます 圧倒的に効率化していきます 圧倒的に効率化していきます 圧倒的に効率化していきます 圧倒的に効率化していきます 圧倒的に効率化していきます (記事を読んでいない方もお楽しみいただけます) (記事を読んでいない方もお楽しみいただけます) (記事を読んでいない方もお楽しみいただけます) (記事を読んでいない方もお楽しみいただけます) (記事を読んでいない方もお楽しみいただけます) (記事を読んでいない方もお楽しみいただけます) 5 / 72

Slide 6

Slide 6 text

記事ではPuppeteer を使いましたが 記事ではPuppeteer を使いましたが 記事ではPuppeteer を使いましたが 記事ではPuppeteer を使いましたが 記事ではPuppeteer を使いましたが 記事ではPuppeteer を使いましたが このセッションではSelenium を使います このセッションではSelenium を使います このセッションではSelenium を使います このセッションではSelenium を使います このセッションではSelenium を使います このセッションではSelenium を使います 6 / 72

Slide 7

Slide 7 text

突然ですが 突然ですが 突然ですが 突然ですが 突然ですが 突然ですが 7 / 72

Slide 8

Slide 8 text

皆さん 皆さん 皆さん 皆さん 皆さん 皆さん ブラウザテスト ブラウザテスト ブラウザテスト ブラウザテスト ブラウザテスト ブラウザテスト 自動化してますか? 自動化してますか? 自動化してますか? 自動化してますか? 自動化してますか? 自動化してますか? 8 / 72

Slide 9

Slide 9 text

ブラウザテスト書くの ブラウザテスト書くの ブラウザテスト書くの ブラウザテスト書くの ブラウザテスト書くの ブラウザテスト書くの めんどくさくないですか? めんどくさくないですか? めんどくさくないですか? めんどくさくないですか? めんどくさくないですか? めんどくさくないですか? 9 / 72

Slide 10

Slide 10 text

例えば 例えば 例えば 例えば 例えば 例えば 10 / 72

Slide 11

Slide 11 text

セレクタを書くのがめんどくさい セレクタを書くのがめんどくさい セレクタを書くのがめんどくさい セレクタを書くのがめんどくさい セレクタを書くのがめんどくさい セレクタを書くのがめんどくさい 11 / 72

Slide 12

Slide 12 text

12 / 72

Slide 13

Slide 13 text

13 / 72

Slide 14

Slide 14 text

たかがボタンひとつクリックするために たかがボタンひとつクリックするために たかがボタンひとつクリックするために たかがボタンひとつクリックするために たかがボタンひとつクリックするために たかがボタンひとつクリックするために めんどくさいこと考えたくないですね めんどくさいこと考えたくないですね めんどくさいこと考えたくないですね めんどくさいこと考えたくないですね めんどくさいこと考えたくないですね めんどくさいこと考えたくないですね 14 / 72

Slide 15

Slide 15 text

それから それから それから それから それから それから 15 / 72

Slide 16

Slide 16 text

要素の表示待ちを 要素の表示待ちを 要素の表示待ちを 要素の表示待ちを 要素の表示待ちを 要素の表示待ちを 考えるのが面倒 考えるのが面倒 考えるのが面倒 考えるのが面倒 考えるのが面倒 考えるのが面倒 16 / 72

Slide 17

Slide 17 text

17 / 72

Slide 18

Slide 18 text

18 / 72

Slide 19

Slide 19 text

言わなくても待ってて欲しいですね 言わなくても待ってて欲しいですね 言わなくても待ってて欲しいですね 言わなくても待ってて欲しいですね 言わなくても待ってて欲しいですね 言わなくても待ってて欲しいですね (Implicitly Wait でもいいんだけど有効範囲が限定的なイメージ) (Implicitly Wait でもいいんだけど有効範囲が限定的なイメージ) (Implicitly Wait でもいいんだけど有効範囲が限定的なイメージ) (Implicitly Wait でもいいんだけど有効範囲が限定的なイメージ) (Implicitly Wait でもいいんだけど有効範囲が限定的なイメージ) (Implicitly Wait でもいいんだけど有効範囲が限定的なイメージ) 19 / 72

Slide 20

Slide 20 text

さらにさらに さらにさらに さらにさらに さらにさらに さらにさらに さらにさらに 20 / 72

Slide 21

Slide 21 text

デバッグがめんどくさい デバッグがめんどくさい デバッグがめんどくさい デバッグがめんどくさい デバッグがめんどくさい デバッグがめんどくさい 21 / 72

Slide 22

Slide 22 text

22 / 72

Slide 23

Slide 23 text

23 / 72

Slide 24

Slide 24 text

デバッグなんてしなくてもすむように デバッグなんてしなくてもすむように デバッグなんてしなくてもすむように デバッグなんてしなくてもすむように デバッグなんてしなくてもすむように デバッグなんてしなくてもすむように 最初から動くコードを書きたいですね!! 最初から動くコードを書きたいですね!! 最初から動くコードを書きたいですね!! 最初から動くコードを書きたいですね!! 最初から動くコードを書きたいですね!! 最初から動くコードを書きたいですね!! 24 / 72

Slide 25

Slide 25 text

どうすれば簡単に書けるんでしょうか どうすれば簡単に書けるんでしょうか どうすれば簡単に書けるんでしょうか どうすれば簡単に書けるんでしょうか どうすれば簡単に書けるんでしょうか どうすれば簡単に書けるんでしょうか 25 / 72

Slide 26

Slide 26 text

__.. - ―─ 、__ __.. - ―─ 、__ /` 三ミー ヘ、_ /` 三ミー ヘ、_ ゝ' ;; ,, , ,, ミミ , il ゙Z, ゝ' ;; ,, , ,, ミミ , il ゙Z, _ 〉,.. ////, , 彡ff ッィ彡从j 彡 _ 〉,.. ////, , 彡ff ッィ彡从j 彡 〉, ィiiif , ,, ' ノ川j ノ川; :. `フ公) 了 〉, ィiiif , ,, ' ノ川j ノ川; :. `フ公) 了 \.:.:.:i= 珍/二''= く、 ! ノ一ヾ゙;.;.; ) \.:.:.:i= 珍/二''= く、 ! ノ一ヾ゙;.;.; ) く:.:.:.:l ムj イ rf モテ〉゙} ij ィt ケ 1 イ'´ く:.:.:.:l ムj イ rf モテ〉゙} ij ィt ケ 1 イ'´ 〕:.:.|,Y!:! 、 ニ ' 、 ; | `ニ イj' 逆に考えるんだ 〕:.:.|,Y!:! 、 ニ ' 、 ; | `ニ イj' 逆に考えるんだ {:.:.:j {: :} ` 、_{__} / ノ {:.:.:j {: :} ` 、_{__} / ノ 〉イ 、゙! , ィ__ 三ー、 j ′ 「これらをやらなければテストは楽に書けるはずさ」 〉イ 、゙! , ィ__ 三ー、 j ′ 「これらをやらなければテストは楽に書けるはずさ」 ,{ \ ミ \ ゝ' ェェ' `' / ,{ \ ミ \ ゝ' ェェ' `' / -‐' \ \ ヽ\ 彡 イ- 、 と考えるんだ -‐' \ \ ヽ\ 彡 イ- 、 と考えるんだ \ \. ヽゝ‐‐‐ 升 ト、 ヽ、__ \ \. ヽゝ‐‐‐ 升 ト、 ヽ、__ \ ヽ- 、./ / j!:.} ` ー 、 \ ヽ- 、./ / j!:.} ` ー 、 ヽ\ 厶_r__ ハ/!:.{ ヽ\ 厶_r__ ハ/!:.{ ´ / ! ヽ ´ / ! ヽ 26 / 72

Slide 27

Slide 27 text

裏を返せば 裏を返せば 裏を返せば 裏を返せば 裏を返せば 裏を返せば これらをやらなければ これらをやらなければ これらをやらなければ これらをやらなければ これらをやらなければ これらをやらなければ テストは楽に書ける(はず) テストは楽に書ける(はず) テストは楽に書ける(はず) テストは楽に書ける(はず) テストは楽に書ける(はず) テストは楽に書ける(はず) 27 / 72

Slide 28

Slide 28 text

ブラウザテストを楽に書くコツ ブラウザテストを楽に書くコツ ブラウザテストを楽に書くコツ ブラウザテストを楽に書くコツ ブラウザテストを楽に書くコツ ブラウザテストを楽に書くコツ CSS セレクタやXPath を(なるべく)使わない CSS セレクタやXPath を(なるべく)使わない CSS セレクタやXPath を(なるべく)使わない CSS セレクタやXPath を(なるべく)使わない CSS セレクタやXPath を(なるべく)使わない CSS セレクタやXPath を(なるべく)使わない 動かなかったら自動でリトライさせる 動かなかったら自動でリトライさせる 動かなかったら自動でリトライさせる 動かなかったら自動でリトライさせる 動かなかったら自動でリトライさせる 動かなかったら自動でリトライさせる 一行ずつ動かしながら書く 一行ずつ動かしながら書く 一行ずつ動かしながら書く 一行ずつ動かしながら書く 一行ずつ動かしながら書く 一行ずつ動かしながら書く                   28 / 72

Slide 29

Slide 29 text

これ全部できます。 これ全部できます。 これ全部できます。 これ全部できます。 これ全部できます。 これ全部できます。 そう、CodeceptJS ならね そう、CodeceptJS ならね そう、CodeceptJS ならね そう、CodeceptJS ならね そう、CodeceptJS ならね そう、CodeceptJS ならね 29 / 72

Slide 30

Slide 30 text

CodeceptJS ってなんなの? CodeceptJS ってなんなの? CodeceptJS ってなんなの? CodeceptJS ってなんなの? CodeceptJS ってなんなの? CodeceptJS ってなんなの? https://codecept.io https://codecept.io https://codecept.io https://codecept.io https://codecept.io https://codecept.io NodeJS 製のブラウザテストフレームワーク NodeJS 製のブラウザテストフレームワーク NodeJS 製のブラウザテストフレームワーク NodeJS 製のブラウザテストフレームワーク NodeJS 製のブラウザテストフレームワーク NodeJS 製のブラウザテストフレームワーク 他のブラウザ操作フレームワークと組み合わせる 他のブラウザ操作フレームワークと組み合わせる 他のブラウザ操作フレームワークと組み合わせる 他のブラウザ操作フレームワークと組み合わせる 他のブラウザ操作フレームワークと組み合わせる 他のブラウザ操作フレームワークと組み合わせる ことでブラウザやモバイル実機を操作できる ことでブラウザやモバイル実機を操作できる ことでブラウザやモバイル実機を操作できる ことでブラウザやモバイル実機を操作できる ことでブラウザやモバイル実機を操作できる ことでブラウザやモバイル実機を操作できる 受け入れテストを直感的に分かりやすく書くこと 受け入れテストを直感的に分かりやすく書くこと 受け入れテストを直感的に分かりやすく書くこと 受け入れテストを直感的に分かりやすく書くこと 受け入れテストを直感的に分かりやすく書くこと 受け入れテストを直感的に分かりやすく書くこと に注力している に注力している に注力している に注力している に注力している に注力している                   30 / 72

Slide 31

Slide 31 text

同じ文法で複数のドライバを利用できる 同じ文法で複数のドライバを利用できる 同じ文法で複数のドライバを利用できる 同じ文法で複数のドライバを利用できる 同じ文法で複数のドライバを利用できる 同じ文法で複数のドライバを利用できる 31 / 72

Slide 32

Slide 32 text

CodeceptJS の様々な機能の中から CodeceptJS の様々な機能の中から CodeceptJS の様々な機能の中から CodeceptJS の様々な機能の中から CodeceptJS の様々な機能の中から CodeceptJS の様々な機能の中から ブラウザテスト記述を特に楽にしてくれる ブラウザテスト記述を特に楽にしてくれる ブラウザテスト記述を特に楽にしてくれる ブラウザテスト記述を特に楽にしてくれる ブラウザテスト記述を特に楽にしてくれる ブラウザテスト記述を特に楽にしてくれる 3 つの機能を紹介します 3 つの機能を紹介します 3 つの機能を紹介します 3 つの機能を紹介します 3 つの機能を紹介します 3 つの機能を紹介します Semantic Locator Semantic Locator Semantic Locator Semantic Locator Semantic Locator Semantic Locator retryFailedStep Plugin retryFailedStep Plugin retryFailedStep Plugin retryFailedStep Plugin retryFailedStep Plugin retryFailedStep Plugin Debugger Debugger Debugger Debugger Debugger Debugger                   32 / 72

Slide 33

Slide 33 text

さっそく使ってみましょう さっそく使ってみましょう さっそく使ってみましょう さっそく使ってみましょう さっそく使ってみましょう さっそく使ってみましょう 33 / 72

Slide 34

Slide 34 text

まずは準備 まずは準備 まずは準備 まずは準備 まずは準備 まずは準備 34 / 72

Slide 35

Slide 35 text

必要なもの 必要なもの 必要なもの 必要なもの 必要なもの 必要なもの NodeJS v8.9 以上 NodeJS v8.9 以上 NodeJS v8.9 以上 NodeJS v8.9 以上 NodeJS v8.9 以上 NodeJS v8.9 以上 npm npm npm npm npm npm Javascript チョット デキル Javascript チョット デキル Javascript チョット デキル Javascript チョット デキル Javascript チョット デキル Javascript チョット デキル UNIX 系OS 前提で話しますが UNIX 系OS 前提で話しますが UNIX 系OS 前提で話しますが UNIX 系OS 前提で話しますが UNIX 系OS 前提で話しますが UNIX 系OS 前提で話しますが Windows でも普通に動く(はず) Windows でも普通に動く(はず) Windows でも普通に動く(はず) Windows でも普通に動く(はず) Windows でも普通に動く(はず) Windows でも普通に動く(はず)                   35 / 72

Slide 36

Slide 36 text

インストールは簡単です インストールは簡単です インストールは簡単です インストールは簡単です インストールは簡単です インストールは簡単です $ $ mkdir mkdir sample sample && && cd cd sample sample $ $ npm npm init init # Enter 連打!!!!! # Enter 連打!!!!! $ $ npm npm install install codeceptjs webdriverio codeceptjs webdriverio $ npx codeceptjs init $ npx codeceptjs init # Enter 連打!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! # Enter 連打!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 36 / 72

Slide 37

Slide 37 text

Selenium Server Selenium Server Selenium Server Selenium Server Selenium Server Selenium Server 別途インストールし起動しておいてください 別途インストールし起動しておいてください 別途インストールし起動しておいてください 別途インストールし起動しておいてください 別途インストールし起動しておいてください 別途インストールし起動しておいてください やりかたがわからない方向け やりかたがわからない方向け やりかたがわからない方向け やりかたがわからない方向け やりかたがわからない方向け やりかたがわからない方向け $ $ sudo sudo npm npm install install -g selenium-standalone -g selenium-standalone $ selenium-standalone $ selenium-standalone install install $ selenium-standalone start $ selenium-standalone start 37 / 72

Slide 38

Slide 38 text

準備完了 準備完了 準備完了 準備完了 準備完了 準備完了 38 / 72

Slide 39

Slide 39 text

ここでもういちどおさらい ここでもういちどおさらい ここでもういちどおさらい ここでもういちどおさらい ここでもういちどおさらい ここでもういちどおさらい ブラウザテストを楽に書くコツ ブラウザテストを楽に書くコツ ブラウザテストを楽に書くコツ ブラウザテストを楽に書くコツ ブラウザテストを楽に書くコツ ブラウザテストを楽に書くコツ CSS セレクタやXPath を(なるべく)使わない CSS セレクタやXPath を(なるべく)使わない CSS セレクタやXPath を(なるべく)使わない CSS セレクタやXPath を(なるべく)使わない CSS セレクタやXPath を(なるべく)使わない CSS セレクタやXPath を(なるべく)使わない 動かなかったら自動でリトライさせる 動かなかったら自動でリトライさせる 動かなかったら自動でリトライさせる 動かなかったら自動でリトライさせる 動かなかったら自動でリトライさせる 動かなかったら自動でリトライさせる 一行ずつ動かしながら書く 一行ずつ動かしながら書く 一行ずつ動かしながら書く 一行ずつ動かしながら書く 一行ずつ動かしながら書く 一行ずつ動かしながら書く                   39 / 72

Slide 40

Slide 40 text

書く時は 書く時は 書く時は 書く時は 書く時は 書く時は 一行ずつ動かしながら 一行ずつ動かしながら 一行ずつ動かしながら 一行ずつ動かしながら 一行ずつ動かしながら 一行ずつ動かしながら CSS やXPath をなるべく使わず CSS やXPath をなるべく使わず CSS やXPath をなるべく使わず CSS やXPath をなるべく使わず CSS やXPath をなるべく使わず CSS やXPath をなるべく使わず 動かす時は 動かす時は 動かす時は 動かす時は 動かす時は 動かす時は 動かない時は適宜リトライさせる 動かない時は適宜リトライさせる 動かない時は適宜リトライさせる 動かない時は適宜リトライさせる 動かない時は適宜リトライさせる 動かない時は適宜リトライさせる という方針でやってみましょう という方針でやってみましょう という方針でやってみましょう という方針でやってみましょう という方針でやってみましょう という方針でやってみましょう                   40 / 72

Slide 41

Slide 41 text

例として 例として 例として 例として 例として 例として Github のユーザー登録フォームをテストします Github のユーザー登録フォームをテストします Github のユーザー登録フォームをテストします Github のユーザー登録フォームをテストします Github のユーザー登録フォームをテストします Github のユーザー登録フォームをテストします 41 / 72

Slide 42

Slide 42 text

一行ずつ動かしながら書く 一行ずつ動かしながら書く 一行ずつ動かしながら書く 一行ずつ動かしながら書く 一行ずつ動かしながら書く 一行ずつ動かしながら書く $ npx codeceptjs shell $ npx codeceptjs shell → 対話型コンソールが起動します → 対話型コンソールが起動します → 対話型コンソールが起動します → 対話型コンソールが起動します → 対話型コンソールが起動します → 対話型コンソールが起動します 42 / 72

Slide 43

Slide 43 text

次のコードを入力していきます 次のコードを入力していきます 次のコードを入力していきます 次のコードを入力していきます 次のコードを入力していきます 次のコードを入力していきます > > I I. .amOnPage amOnPage( ('https://github.com' 'https://github.com') ) > > I I. .fillField fillField( ('Username' 'Username', , 'shen-long1234' 'shen-long1234') ) > > I I. .fillField fillField( ('Email' 'Email', , '[email protected]' '[email protected]') ) > > I I. .fillField fillField( ('Password' 'Password', , 'P@ssword1234' 'P@ssword1234') ) > > I I. .click click( ('Sign up for GitHub' 'Sign up for GitHub') ) 43 / 72

Slide 44

Slide 44 text

動きましたね 動きましたね 動きましたね 動きましたね 動きましたね 動きましたね 44 / 72

Slide 45

Slide 45 text

動いたのでそのままコピペして 動いたのでそのままコピペして 動いたのでそのままコピペして 動いたのでそのままコピペして 動いたのでそのままコピペして 動いたのでそのままコピペして 再実行しましょう 再実行しましょう 再実行しましょう 再実行しましょう 再実行しましょう 再実行しましょう Feature Feature( ('Github' 'Github') ) Scenario Scenario( ('Can Sign Up' 'Can Sign Up', , async async ( (I I) ) => => { { I I. .amOnPage amOnPage( ('https://github.com' 'https://github.com') ) I I. .fillField fillField( ('Username' 'Username', , 'shen-long1234' 'shen-long1234') ) I I. .fillField fillField( ('Email' 'Email', , '[email protected]' '[email protected]') ) I I. .fillField fillField( ('Password' 'Password', , 'P@ssword1234' 'P@ssword1234') ) I I. .click click( ('Sign up for GitHub' 'Sign up for GitHub') ) } }) ) → → → → → → github_test.js github_test.js github_test.js github_test.js github_test.js github_test.js として保存 として保存 として保存 として保存 として保存 として保存 45 / 72

Slide 46

Slide 46 text

実行 実行 実行 実行 実行 実行 $ npx codeceptjs run github_test.js --steps $ npx codeceptjs run github_test.js --steps Github -- Github -- Can Sign Up Can Sign Up I am on page "https://github.com" I am on page "https://github.com" I fill field "Username", "shen-long1234" I fill field "Username", "shen-long1234" I fill field "Email", "[email protected]" I fill field "Email", "[email protected]" I fill field "Password", "P@ssword1234" I fill field "Password", "P@ssword1234" I click "Sign up for GitHub" I click "Sign up for GitHub" ✔ OK in 5593ms ✔ OK in 5593ms 46 / 72

Slide 47

Slide 47 text

ここでもう一度コードを見てみます ここでもう一度コードを見てみます ここでもう一度コードを見てみます ここでもう一度コードを見てみます ここでもう一度コードを見てみます ここでもう一度コードを見てみます Feature Feature( ('Github' 'Github') ) Scenario Scenario( ('Can Sign Up' 'Can Sign Up', , async async ( (I I) ) => => { { I I. .amOnPage amOnPage( ('https://github.com' 'https://github.com') ) I I. .fillField fillField( ('Username' 'Username', , 'shen-long1234' 'shen-long1234') ) I I. .fillField fillField( ('Email' 'Email', , '[email protected]' '[email protected]') ) I I. .fillField fillField( ('Password' 'Password', , 'P@ssword1234' 'P@ssword1234') ) I I. .click click( ('Sign up for GitHub' 'Sign up for GitHub') ) } }) ) CSS セレクタの類は全然出てきませんね CSS セレクタの類は全然出てきませんね CSS セレクタの類は全然出てきませんね CSS セレクタの類は全然出てきませんね CSS セレクタの類は全然出てきませんね CSS セレクタの類は全然出てきませんね 47 / 72

Slide 48

Slide 48 text

なぜセレクタを書かずに動くの? なぜセレクタを書かずに動くの? なぜセレクタを書かずに動くの? なぜセレクタを書かずに動くの? なぜセレクタを書かずに動くの? なぜセレクタを書かずに動くの? 秘密は Semantic Locator 秘密は Semantic Locator 秘密は Semantic Locator 秘密は Semantic Locator 秘密は Semantic Locator 秘密は Semantic Locator 48 / 72

Slide 49

Slide 49 text

Semantic Locator とは Semantic Locator とは Semantic Locator とは Semantic Locator とは Semantic Locator とは Semantic Locator とは アクションにCSS でもXPath でもない文字列を渡すと アクションにCSS でもXPath でもない文字列を渡すと アクションにCSS でもXPath でもない文字列を渡すと アクションにCSS でもXPath でもない文字列を渡すと アクションにCSS でもXPath でもない文字列を渡すと アクションにCSS でもXPath でもない文字列を渡すと なんか良い感じにその文字列を持つ要素を なんか良い感じにその文字列を持つ要素を なんか良い感じにその文字列を持つ要素を なんか良い感じにその文字列を持つ要素を なんか良い感じにその文字列を持つ要素を なんか良い感じにその文字列を持つ要素を 探索してくれる機能 探索してくれる機能 探索してくれる機能 探索してくれる機能 探索してくれる機能 探索してくれる機能 https://codecept.io/locators#semantic-locators https://codecept.io/locators#semantic-locators https://codecept.io/locators#semantic-locators https://codecept.io/locators#semantic-locators https://codecept.io/locators#semantic-locators https://codecept.io/locators#semantic-locators 49 / 72

Slide 51

Slide 51 text

例えば 例えば 例えば 例えば 例えば 例えば 文字入力なら 文字入力なら 文字入力なら 文字入力なら 文字入力なら 文字入力なら などのうち、 などのうち、 などのうち、 などのうち、 などのうち、 などのうち、 label label label label label label や や や や や や placeholder placeholder placeholder placeholder placeholder placeholder や や や や や や name name name name name name などに などに などに などに などに などに 指定されたテキストを含むものを 指定されたテキストを含むものを 指定されたテキストを含むものを 指定されたテキストを含むものを 指定されたテキストを含むものを 指定されたテキストを含むものを 自動的に探索します 自動的に探索します 自動的に探索します 自動的に探索します 自動的に探索します 自動的に探索します             51 / 72

Slide 52

Slide 52 text

最高 最高 最高 最高 最高 最高 52 / 72

Slide 53

Slide 53 text

もちろんSemantic Locator で もちろんSemantic Locator で もちろんSemantic Locator で もちろんSemantic Locator で もちろんSemantic Locator で もちろんSemantic Locator で 対応できないケースはあります 対応できないケースはあります 対応できないケースはあります 対応できないケースはあります 対応できないケースはあります 対応できないケースはあります そういうときは割り切って そういうときは割り切って そういうときは割り切って そういうときは割り切って そういうときは割り切って そういうときは割り切って CSS セレクタとか使っていきましょう CSS セレクタとか使っていきましょう CSS セレクタとか使っていきましょう CSS セレクタとか使っていきましょう CSS セレクタとか使っていきましょう CSS セレクタとか使っていきましょう I I. .click click( ('#submit' '#submit') ) 53 / 72

Slide 54

Slide 54 text

CSS セレクタやXPath を使わざるを得ない時も CSS セレクタやXPath を使わざるを得ない時も CSS セレクタやXPath を使わざるを得ない時も CSS セレクタやXPath を使わざるを得ない時も CSS セレクタやXPath を使わざるを得ない時も CSS セレクタやXPath を使わざるを得ない時も locate locate locate locate locate locate 関数を使えば可読性を保ったまま書けます 関数を使えば可読性を保ったまま書けます 関数を使えば可読性を保ったまま書けます 関数を使えば可読性を保ったまま書けます 関数を使えば可読性を保ったまま書けます 関数を使えば可読性を保ったまま書けます const const checkBox checkBox = = locate locate( ('input' 'input') ) . .withAttr withAttr( ({ {type type: : 'checkbox' 'checkbox'} }) ) . .inside inside( ('form#register' 'form#register') ) const const submit submit = = locate locate( ('button' 'button') ). .withText withText( (' 送信する' ' 送信する') ) I I. .checkOption checkOption( (checkBox checkBox) ) I I. .click click( (submit submit) ) withText() withText() withText() withText() withText() withText() を使えばSemantic Locator がなくても を使えばSemantic Locator がなくても を使えばSemantic Locator がなくても を使えばSemantic Locator がなくても を使えばSemantic Locator がなくても を使えばSemantic Locator がなくても 分かりやすく書けますね 分かりやすく書けますね 分かりやすく書けますね 分かりやすく書けますね 分かりやすく書けますね 分かりやすく書けますね 54 / 72

Slide 55

Slide 55 text

locate locate locate locate locate locate を使う場合、 を使う場合、 を使う場合、 を使う場合、 を使う場合、 を使う場合、as as as as as as メソッドを使うと メソッドを使うと メソッドを使うと メソッドを使うと メソッドを使うと メソッドを使うと ロケータに別名を持たせることができます ロケータに別名を持たせることができます ロケータに別名を持たせることができます ロケータに別名を持たせることができます ロケータに別名を持たせることができます ロケータに別名を持たせることができます const const submit submit = = locate locate( ('button' 'button') ) . .withText withText( (' 送信する' ' 送信する') ) . .as as( (' 送信ボタン' ' 送信ボタン') ) I I. .click click( (submit submit) ) // レポートでは `I click 送信ボタン` のように表示される // レポートでは `I click 送信ボタン` のように表示される 55 / 72

Slide 56

Slide 56 text

特定の要素の内側でのみ探索することもできます 特定の要素の内側でのみ探索することもできます 特定の要素の内側でのみ探索することもできます 特定の要素の内側でのみ探索することもできます 特定の要素の内側でのみ探索することもできます 特定の要素の内側でのみ探索することもできます const const dialog dialog = = locate locate( ('div' 'div') ) . .withText withText( (' 送信してよろしいですか?' ' 送信してよろしいですか?') ) . .as as( (' 送信確認ダイアログ' ' 送信確認ダイアログ') ) // 送信確認ダイアログの中のみを探索 // 送信確認ダイアログの中のみを探索 with with( (dialog dialog, , ( () ) => => { { I I. .click click( (' 送信' ' 送信') ) } }) ) 56 / 72

Slide 57

Slide 57 text

locate locate locate locate locate locate の話は の話は の話は の話は の話は の話は 永遠に続けられるので 永遠に続けられるので 永遠に続けられるので 永遠に続けられるので 永遠に続けられるので 永遠に続けられるので いったんここまで! いったんここまで! いったんここまで! いったんここまで! いったんここまで! いったんここまで! (興味のある方は終了後 (興味のある方は終了後 (興味のある方は終了後 (興味のある方は終了後 (興味のある方は終了後 (興味のある方は終了後 またはTwitter 等でお声がけください) またはTwitter 等でお声がけください) またはTwitter 等でお声がけください) またはTwitter 等でお声がけください) またはTwitter 等でお声がけください) またはTwitter 等でお声がけください) 57 / 72

Slide 58

Slide 58 text

ここまでの説明で ここまでの説明で ここまでの説明で ここまでの説明で ここまでの説明で ここまでの説明で 動かしながら書くのでデバッグ不要 動かしながら書くのでデバッグ不要 動かしながら書くのでデバッグ不要 動かしながら書くのでデバッグ不要 動かしながら書くのでデバッグ不要 動かしながら書くのでデバッグ不要 CSS セレクタやXPath を考えずに記述できる CSS セレクタやXPath を考えずに記述できる CSS セレクタやXPath を考えずに記述できる CSS セレクタやXPath を考えずに記述できる CSS セレクタやXPath を考えずに記述できる CSS セレクタやXPath を考えずに記述できる ようになりました ようになりました ようになりました ようになりました ようになりました ようになりました             58 / 72

Slide 59

Slide 59 text

まだ大事な課題が残っていますね まだ大事な課題が残っていますね まだ大事な課題が残っていますね まだ大事な課題が残っていますね まだ大事な課題が残っていますね まだ大事な課題が残っていますね 59 / 72

Slide 60

Slide 60 text

方針のおさらい 方針のおさらい 方針のおさらい 方針のおさらい 方針のおさらい 方針のおさらい 書く時は 書く時は 書く時は 書く時は 書く時は 書く時は 一行ずつ動かしながら 一行ずつ動かしながら 一行ずつ動かしながら 一行ずつ動かしながら 一行ずつ動かしながら 一行ずつ動かしながら CSS やXPath をなるべく使わず CSS やXPath をなるべく使わず CSS やXPath をなるべく使わず CSS やXPath をなるべく使わず CSS やXPath をなるべく使わず CSS やXPath をなるべく使わず 動かす時は 動かす時は 動かす時は 動かす時は 動かす時は 動かす時は 動かない時は適宜リトライさせる ←未解決 動かない時は適宜リトライさせる ←未解決 動かない時は適宜リトライさせる ←未解決 動かない時は適宜リトライさせる ←未解決 動かない時は適宜リトライさせる ←未解決 動かない時は適宜リトライさせる ←未解決                   60 / 72

Slide 61

Slide 61 text

例えば 例えば 例えば 例えば 例えば 例えば Github のユーザー登録フォームで、 Github のユーザー登録フォームで、 Github のユーザー登録フォームで、 Github のユーザー登録フォームで、 Github のユーザー登録フォームで、 Github のユーザー登録フォームで、 すでに登録済みのユーザー名を入れると すでに登録済みのユーザー名を入れると すでに登録済みのユーザー名を入れると すでに登録済みのユーザー名を入れると すでに登録済みのユーザー名を入れると すでに登録済みのユーザー名を入れると エラーが表示されます エラーが表示されます エラーが表示されます エラーが表示されます エラーが表示されます エラーが表示されます 「このエラーが表示されること」をテストします 「このエラーが表示されること」をテストします 「このエラーが表示されること」をテストします 「このエラーが表示されること」をテストします 「このエラーが表示されること」をテストします 「このエラーが表示されること」をテストします 61 / 72

Slide 62

Slide 62 text

コンソールから書いてみます コンソールから書いてみます コンソールから書いてみます コンソールから書いてみます コンソールから書いてみます コンソールから書いてみます > I.amOnpage('https://github.com') > I.amOnpage('https://github.com') > I.fillField('Username', 'tsuemura') > I.fillField('Username', 'tsuemura') > I.see('Something went wrong') // エラーが表示されているこ > I.see('Something went wrong') // エラーが表示されているこ とを確認 とを確認 これは成功します これは成功します これは成功します これは成功します これは成功します これは成功します 62 / 72

Slide 63

Slide 63 text

このコードを自動実行させてみます このコードを自動実行させてみます このコードを自動実行させてみます このコードを自動実行させてみます このコードを自動実行させてみます このコードを自動実行させてみます Feature Feature( ('Github' 'Github') ) Scenario Scenario( ('Username must be unique' 'Username must be unique', , async async ( (I I) ) => => { { I I. .amOnPage amOnPage( ('https://github.com' 'https://github.com') ) I I. .fillField fillField( ('Username' 'Username', , 'tsuemura' 'tsuemura') ) I I. .see see( ('Something went wrong' 'Something went wrong') ) } }) ) → → → → → → github2_test.js github2_test.js github2_test.js github2_test.js github2_test.js github2_test.js として保存 として保存 として保存 として保存 として保存 として保存 $ npx codeceptjs run github2_test.js --steps $ npx codeceptjs run github2_test.js --steps 63 / 72

Slide 64

Slide 64 text

失敗しました 失敗しました 失敗しました 失敗しました 失敗しました 失敗しました バリデーションメッセージが出る前に バリデーションメッセージが出る前に バリデーションメッセージが出る前に バリデーションメッセージが出る前に バリデーションメッセージが出る前に バリデーションメッセージが出る前に アサーションしてしまったからですね アサーションしてしまったからですね アサーションしてしまったからですね アサーションしてしまったからですね アサーションしてしまったからですね アサーションしてしまったからですね 64 / 72

Slide 65

Slide 65 text

ここで登場するのが ここで登場するのが ここで登場するのが ここで登場するのが ここで登場するのが ここで登場するのが retryFailedStep retryFailedStep retryFailedStep retryFailedStep retryFailedStep retryFailedStep プラグイン プラグイン プラグイン プラグイン プラグイン プラグイン 文字通り「失敗したらリトライする」機能です 文字通り「失敗したらリトライする」機能です 文字通り「失敗したらリトライする」機能です 文字通り「失敗したらリトライする」機能です 文字通り「失敗したらリトライする」機能です 文字通り「失敗したらリトライする」機能です (デフォルトでは1 秒ごとに最大5 回リトライ) (デフォルトでは1 秒ごとに最大5 回リトライ) (デフォルトでは1 秒ごとに最大5 回リトライ) (デフォルトでは1 秒ごとに最大5 回リトライ) (デフォルトでは1 秒ごとに最大5 回リトライ) (デフォルトでは1 秒ごとに最大5 回リトライ) WebDriver の WebDriver の WebDriver の WebDriver の WebDriver の WebDriver の implicitly wait implicitly wait implicitly wait implicitly wait implicitly wait implicitly wait に似てますが に似てますが に似てますが に似てますが に似てますが に似てますが implicitly wait implicitly wait implicitly wait implicitly wait implicitly wait implicitly wait が要素の表示待ちにのみ適用されるのに対し が要素の表示待ちにのみ適用されるのに対し が要素の表示待ちにのみ適用されるのに対し が要素の表示待ちにのみ適用されるのに対し が要素の表示待ちにのみ適用されるのに対し が要素の表示待ちにのみ適用されるのに対し こちらはアサーション含め全アクションにも適用されます こちらはアサーション含め全アクションにも適用されます こちらはアサーション含め全アクションにも適用されます こちらはアサーション含め全アクションにも適用されます こちらはアサーション含め全アクションにも適用されます こちらはアサーション含め全アクションにも適用されます 65 / 72

Slide 66

Slide 66 text

インストールは超簡単 インストールは超簡単 インストールは超簡単 インストールは超簡単 インストールは超簡単 インストールは超簡単 codecept.conf.js codecept.conf.js codecept.conf.js codecept.conf.js codecept.conf.js codecept.conf.js に以下を追記 に以下を追記 に以下を追記 に以下を追記 に以下を追記 に以下を追記 plugins plugins: : { { retryFailedStep retryFailedStep: : { { enabled enabled: : true true, , } }, , } }, , 66 / 72

Slide 67

Slide 67 text

改めて実行してみます 改めて実行してみます 改めて実行してみます 改めて実行してみます 改めて実行してみます 改めて実行してみます $ npx codeceptjs run github2_test.js $ npx codeceptjs run github2_test.js Github -- Github -- Can Sign Up Can Sign Up I am on page "https://github.com" I am on page "https://github.com" I fill field "Username", "tsuemura" I fill field "Username", "tsuemura" I see "Something went wrong" I see "Something went wrong" ✔ OK in 4039ms ✔ OK in 4039ms 今度は成功! 今度は成功! 今度は成功! 今度は成功! 今度は成功! 今度は成功! 67 / 72

Slide 68

Slide 68 text

設定ファイルにたった5 行追加するだけで 設定ファイルにたった5 行追加するだけで 設定ファイルにたった5 行追加するだけで 設定ファイルにたった5 行追加するだけで 設定ファイルにたった5 行追加するだけで 設定ファイルにたった5 行追加するだけで テストコードが テストコードが テストコードが テストコードが テストコードが テストコードが SPA 対応になってしまいました!!!! SPA 対応になってしまいました!!!! SPA 対応になってしまいました!!!! SPA 対応になってしまいました!!!! SPA 対応になってしまいました!!!! SPA 対応になってしまいました!!!! 68 / 72

Slide 69

Slide 69 text

おわかりいただけただろうか…… おわかりいただけただろうか…… おわかりいただけただろうか…… おわかりいただけただろうか…… おわかりいただけただろうか…… おわかりいただけただろうか…… (CodeceptJS の便利さを) (CodeceptJS の便利さを) (CodeceptJS の便利さを) (CodeceptJS の便利さを) (CodeceptJS の便利さを) (CodeceptJS の便利さを) 69 / 72

Slide 70

Slide 70 text

他にもいろんな機能が盛り沢山 他にもいろんな機能が盛り沢山 他にもいろんな機能が盛り沢山 他にもいろんな機能が盛り沢山 他にもいろんな機能が盛り沢山 他にもいろんな機能が盛り沢山 ビジュアルテスト(画像比較) ビジュアルテスト(画像比較) ビジュアルテスト(画像比較) ビジュアルテスト(画像比較) ビジュアルテスト(画像比較) ビジュアルテスト(画像比較) テスト失敗時に自動でスクリーンショット撮影 テスト失敗時に自動でスクリーンショット撮影 テスト失敗時に自動でスクリーンショット撮影 テスト失敗時に自動でスクリーンショット撮影 テスト失敗時に自動でスクリーンショット撮影 テスト失敗時に自動でスクリーンショット撮影 Allure Reporter によるキレイなレポート Allure Reporter によるキレイなレポート Allure Reporter によるキレイなレポート Allure Reporter によるキレイなレポート Allure Reporter によるキレイなレポート Allure Reporter によるキレイなレポート テストコードとレポートの翻訳 テストコードとレポートの翻訳 テストコードとレポートの翻訳 テストコードとレポートの翻訳 テストコードとレポートの翻訳 テストコードとレポートの翻訳 Appium によるネイティブアプリのテスト Appium によるネイティブアプリのテスト Appium によるネイティブアプリのテスト Appium によるネイティブアプリのテスト Appium によるネイティブアプリのテスト Appium によるネイティブアプリのテスト BDD(Gherkin) 記法のサポート BDD(Gherkin) 記法のサポート BDD(Gherkin) 記法のサポート BDD(Gherkin) 記法のサポート BDD(Gherkin) 記法のサポート BDD(Gherkin) 記法のサポート ...etc ...etc ...etc ...etc ...etc ...etc                                     70 / 72

Slide 71

Slide 71 text

質問等あれば遠慮なくどうぞ! 質問等あれば遠慮なくどうぞ! 質問等あれば遠慮なくどうぞ! 質問等あれば遠慮なくどうぞ! 質問等あれば遠慮なくどうぞ! 質問等あれば遠慮なくどうぞ! Twitter: @tsueeemura Twitter: @tsueeemura Twitter: @tsueeemura Twitter: @tsueeemura Twitter: @tsueeemura Twitter: @tsueeemura Teratail: @tsuemura Teratail: @tsuemura Teratail: @tsuemura Teratail: @tsuemura Teratail: @tsuemura Teratail: @tsuemura 71 / 72

Slide 72

Slide 72 text

おわり おわり おわり おわり おわり おわり 72 / 72