Slide 1

Slide 1 text

Page Object Pattern 使うのやめた話 Page Object Pattern 使うのやめた話 Page Object Pattern 使うのやめた話 Page Object Pattern 使うのやめた話 Page Object Pattern 使うのやめた話 Page Object Pattern 使うのやめた話 末村 拓也 @ 株式会社オープンロジ 末村 拓也 @ 株式会社オープンロジ 末村 拓也 @ 株式会社オープンロジ 末村 拓也 @ 株式会社オープンロジ 末村 拓也 @ 株式会社オープンロジ 末村 拓也 @ 株式会社オープンロジ Takuya Suemura @ OPENLOGI Inc. Takuya Suemura @ OPENLOGI Inc. Takuya Suemura @ OPENLOGI Inc. Takuya Suemura @ OPENLOGI Inc. Takuya Suemura @ OPENLOGI Inc. Takuya Suemura @ OPENLOGI Inc.

Slide 2

Slide 2 text

自己紹介 自己紹介 自己紹介 自己紹介 自己紹介 自己紹介 末村 拓也 (Takuya Suemura) 末村 拓也 (Takuya Suemura) 末村 拓也 (Takuya Suemura) 末村 拓也 (Takuya Suemura) 末村 拓也 (Takuya Suemura) 末村 拓也 (Takuya Suemura) 物流スタートアップ『OPENLOGI 』のQA エンジニアです 物流スタートアップ『OPENLOGI 』のQA エンジニアです 物流スタートアップ『OPENLOGI 』のQA エンジニアです 物流スタートアップ『OPENLOGI 』のQA エンジニアです 物流スタートアップ『OPENLOGI 』のQA エンジニアです 物流スタートアップ『OPENLOGI 』のQA エンジニアです 日本の皆さんには↓の記事が名刺代わりになるでしょうか 日本の皆さんには↓の記事が名刺代わりになるでしょうか 日本の皆さんには↓の記事が名刺代わりになるでしょうか 日本の皆さんには↓の記事が名刺代わりになるでしょうか 日本の皆さんには↓の記事が名刺代わりになるでしょうか 日本の皆さんには↓の記事が名刺代わりになるでしょうか                  

Slide 3

Slide 3 text

今日は、ロケーターの 今日は、ロケーターの 今日は、ロケーターの 今日は、ロケーターの 今日は、ロケーターの 今日は、ロケーターの メンテナンス性の話を メンテナンス性の話を メンテナンス性の話を メンテナンス性の話を メンテナンス性の話を メンテナンス性の話を したいとおもいます。 したいとおもいます。 したいとおもいます。 したいとおもいます。 したいとおもいます。 したいとおもいます。

Slide 4

Slide 4 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 ( なるべくフレームワーク特有の機能は使わず説明します) ( なるべくフレームワーク特有の機能は使わず説明します) ( なるべくフレームワーク特有の機能は使わず説明します) ( なるべくフレームワーク特有の機能は使わず説明します) ( なるべくフレームワーク特有の機能は使わず説明します) ( なるべくフレームワーク特有の機能は使わず説明します)

Slide 5

Slide 5 text

Page Object Pattern Page Object Pattern Page Object Pattern Page Object Pattern Page Object Pattern Page Object Pattern 使っていますか? 使っていますか? 使っていますか? 使っていますか? 使っていますか? 使っていますか?

Slide 6

Slide 6 text

Page Object Pattern を Page Object Pattern を Page Object Pattern を Page Object Pattern を Page Object Pattern を Page Object Pattern を 知らない人? 知らない人? 知らない人? 知らない人? 知らない人? 知らない人?

Slide 7

Slide 7 text

一応解説: Page Object とは 一応解説: Page Object とは 一応解説: Page Object とは 一応解説: Page Object とは 一応解説: Page Object とは 一応解説: Page Object とは ページの要素セレクタや操作手順をまとめたオブジェクト ページの要素セレクタや操作手順をまとめたオブジェクト ページの要素セレクタや操作手順をまとめたオブジェクト ページの要素セレクタや操作手順をまとめたオブジェクト ページの要素セレクタや操作手順をまとめたオブジェクト ページの要素セレクタや操作手順をまとめたオブジェクト const const page page = = { { nameField nameField: : locate locate( ('input#name' 'input#name') ), , sendButton sendButton: : locate locate( ('button[type=submit]' 'button[type=submit]') ), , register register: : ( (name name) ) => => { { I I. .fillField fillField( (this this. .nameField nameField, , name name) ) I I. .click click( (this this. .sendButton sendButton) ) } } } } page page. .register register( ('Takuya Suemura' 'Takuya Suemura') )

Slide 8

Slide 8 text

Page Object を使うメリット Page Object を使うメリット Page Object を使うメリット Page Object を使うメリット Page Object を使うメリット Page Object を使うメリット 要素や操作が抽象化されるので 要素や操作が抽象化されるので 要素や操作が抽象化されるので 要素や操作が抽象化されるので 要素や操作が抽象化されるので 要素や操作が抽象化されるので コードが読みやすくなる コードが読みやすくなる コードが読みやすくなる コードが読みやすくなる コードが読みやすくなる コードが読みやすくなる 同じ操作を繰り返し利用できる 同じ操作を繰り返し利用できる 同じ操作を繰り返し利用できる 同じ操作を繰り返し利用できる 同じ操作を繰り返し利用できる 同じ操作を繰り返し利用できる デザインの変更に強くなる デザインの変更に強くなる デザインの変更に強くなる デザインの変更に強くなる デザインの変更に強くなる デザインの変更に強くなる                  

Slide 9

Slide 9 text

ページ数が少ないころはよかった ページ数が少ないころはよかった ページ数が少ないころはよかった ページ数が少ないころはよかった ページ数が少ないころはよかった ページ数が少ないころはよかった

Slide 10

Slide 10 text

ページが9999 枚になったら? ページが9999 枚になったら? ページが9999 枚になったら? ページが9999 枚になったら? ページが9999 枚になったら? ページが9999 枚になったら?

Slide 11

Slide 11 text

PageObject も9999 個作る????? PageObject も9999 個作る????? PageObject も9999 個作る????? PageObject も9999 個作る????? PageObject も9999 個作る????? PageObject も9999 個作る????? const const page0001 page0001 = = { {... ...} } const const page0002 page0002 = = { {... ...} } const const page0003 page0003 = = { {... ...} } const const page0004 page0004 = = { {... ...} } const const page0005 page0005 = = { {... ...} } const const page0006 page0006 = = { {... ...} } const const page0007 page0007 = = { {... ...} } const const page0008 page0008 = = { {... ...} } const const page0009 page0009 = = { {... ...} } const const page0010 page0010 = = { {... ...} } const const page0011 page0011 = = { {... ...} } const const page0012 page0012 = = { {... ...} }

Slide 12

Slide 12 text

9999 行のimport 文を書く?????? 9999 行のimport 文を書く?????? 9999 行のimport 文を書く?????? 9999 行のimport 文を書く?????? 9999 行のimport 文を書く?????? 9999 行のimport 文を書く?????? import import Page0001 Page0001 from from './page0001' './page0001' import import Page0002 Page0002 from from './page0002' './page0002' import import Page0003 Page0003 from from './page0003' './page0003' import import Page0004 Page0004 from from './page0004' './page0004' import import Page0005 Page0005 from from './page0005' './page0005' import import Page0006 Page0006 from from './page0006' './page0006' import import Page0007 Page0007 from from './page0007' './page0007' import import Page0008 Page0008 from from './page0008' './page0008' import import Page0009 Page0009 from from './page0009' './page0009' import import Page0010 Page0010 from from './page0010' './page0010' import import Page0011 Page0011 from from './page0011' './page0011' import import Page0012 Page0012 from from './page0012' './page0012' import import Page0013 Page0013 from from './page0013' './page0013'

Slide 13

Slide 13 text

PageObjectPattern の弱点: PageObjectPattern の弱点: PageObjectPattern の弱点: PageObjectPattern の弱点: PageObjectPattern の弱点: PageObjectPattern の弱点: メンテナンスコストが線形に増大する メンテナンスコストが線形に増大する メンテナンスコストが線形に増大する メンテナンスコストが線形に増大する メンテナンスコストが線形に増大する メンテナンスコストが線形に増大する ※このグラフはただのイメージです ※このグラフはただのイメージです ※このグラフはただのイメージです ※このグラフはただのイメージです ※このグラフはただのイメージです ※このグラフはただのイメージです

Slide 14

Slide 14 text

どうやって解決したか どうやって解決したか どうやって解決したか どうやって解決したか どうやって解決したか どうやって解決したか 14 / 23

Slide 15

Slide 15 text

Page Object Page Object Page Object Page Object Page Object Page Object やめました やめました やめました やめました やめました やめました 15 / 23

Slide 16

Slide 16 text

代わりに 代わりに 代わりに 代わりに 代わりに 代わりに コンポーネントの抽象化 コンポーネントの抽象化 コンポーネントの抽象化 コンポーネントの抽象化 コンポーネントの抽象化 コンポーネントの抽象化 16 / 23

Slide 17

Slide 17 text

ページの数が爆発的に増えたからといって ページの数が爆発的に増えたからといって ページの数が爆発的に増えたからといって ページの数が爆発的に増えたからといって ページの数が爆発的に増えたからといって ページの数が爆発的に増えたからといって コンポーネントの種類も爆発的に増えるわけではない コンポーネントの種類も爆発的に増えるわけではない コンポーネントの種類も爆発的に増えるわけではない コンポーネントの種類も爆発的に増えるわけではない コンポーネントの種類も爆発的に増えるわけではない コンポーネントの種類も爆発的に増えるわけではない コンポーネント = ページを構成する部品 コンポーネント = ページを構成する部品 コンポーネント = ページを構成する部品 コンポーネント = ページを構成する部品 コンポーネント = ページを構成する部品 コンポーネント = ページを構成する部品

Slide 18

Slide 18 text

コンポーネントを抽象化した コンポーネントを抽象化した コンポーネントを抽象化した コンポーネントを抽象化した コンポーネントを抽象化した コンポーネントを抽象化した 要素そのもののセレクタを定義するのではなく、 要素そのもののセレクタを定義するのではなく、 要素そのもののセレクタを定義するのではなく、 要素そのもののセレクタを定義するのではなく、 要素そのもののセレクタを定義するのではなく、 要素そのもののセレクタを定義するのではなく、 セレクタを返す関数を定義する セレクタを返す関数を定義する セレクタを返す関数を定義する セレクタを返す関数を定義する セレクタを返す関数を定義する セレクタを返す関数を定義する const const button button = = label label => => locate locate( (`button= `button=${ ${label label} }` `) ) // 'Submit' というテキストを持つボタンをクリックする // 'Submit' というテキストを持つボタンをクリックする I I. .click click( (button button( ('Submit' 'Submit') )) )

Slide 19

Slide 19 text

コンポーネントを抽象化した コンポーネントを抽象化した コンポーネントを抽象化した コンポーネントを抽象化した コンポーネントを抽象化した コンポーネントを抽象化した たとえばBootstrap の入力フォーム たとえばBootstrap の入力フォーム たとえばBootstrap の入力フォーム たとえばBootstrap の入力フォーム たとえばBootstrap の入力フォーム たとえばBootstrap の入力フォーム <
> < >Email address Email address > < >
>

Slide 20

Slide 20 text

コンポーネントを抽象化した コンポーネントを抽象化した コンポーネントを抽象化した コンポーネントを抽象化した コンポーネントを抽象化した コンポーネントを抽象化した label を引数に取り、対応するinput を返す関数を定義した label を引数に取り、対応するinput を返す関数を定義した label を引数に取り、対応するinput を返す関数を定義した label を引数に取り、対応するinput を返す関数を定義した label を引数に取り、対応するinput を返す関数を定義した label を引数に取り、対応するinput を返す関数を定義した const const field field = = label label => => { { return return locate locate( ('div.form-group' 'div.form-group') ) //
//
. .withText withText( (label label) ) // label に指定したテキストを持つ // label に指定したテキストを持つ . .find find( ('input' 'input') ) // input 要素を選択 // input 要素を選択 } } I I. .fillField fillField( (field field( ('Email address' 'Email address') ), , '[email protected]' '[email protected]') ) 同じコンポーネントを使っていれば汎用的に使いまわせる 同じコンポーネントを使っていれば汎用的に使いまわせる 同じコンポーネントを使っていれば汎用的に使いまわせる 同じコンポーネントを使っていれば汎用的に使いまわせる 同じコンポーネントを使っていれば汎用的に使いまわせる 同じコンポーネントを使っていれば汎用的に使いまわせる

Slide 21

Slide 21 text

9999 個のPageObject を作るのではなく 9999 個のPageObject を作るのではなく 9999 個のPageObject を作るのではなく 9999 個のPageObject を作るのではなく 9999 個のPageObject を作るのではなく 9999 個のPageObject を作るのではなく // Don't do this // Don't do this const const page0001 page0001 = = { {... ...} } const const page0002 page0002 = = { {... ...} } const const page0003 page0003 = = { {... ...} } const const page0004 page0004 = = { {... ...} } const const page0005 page0005 = = { {... ...} } const const page0006 page0006 = = { {... ...} } const const page0007 page0007 = = { {... ...} } const const page0008 page0008 = = { {... ...} } const const page0009 page0009 = = { {... ...} } const const page0010 page0010 = = { {... ...} } const const page0011 page0011 = = { {... ...} }

Slide 22

Slide 22 text

コンポーネントを抽象化したロケータを コンポーネントを抽象化したロケータを コンポーネントを抽象化したロケータを コンポーネントを抽象化したロケータを コンポーネントを抽象化したロケータを コンポーネントを抽象化したロケータを 一つ作りましょう 一つ作りましょう 一つ作りましょう 一つ作りましょう 一つ作りましょう 一つ作りましょう Bootstrap, Vuetify, AdminLTE, ...etc Bootstrap, Vuetify, AdminLTE, ...etc Bootstrap, Vuetify, AdminLTE, ...etc Bootstrap, Vuetify, AdminLTE, ...etc Bootstrap, Vuetify, AdminLTE, ...etc Bootstrap, Vuetify, AdminLTE, ...etc const const bootstrapComponents bootstrapComponents = = { { button button: : label label => => locate locate( ('button' 'button') ). .withText withText( (button button) ), , field field: : label label => => locate locate( ('div.form-group' 'div.form-group') ). .withText withText( (label label) ) . .find find( ('input' 'input') ), , // and something // and something } } I I. .click click( (bootstrapComponents bootstrapComponents. .button button( ('Thank you for Listening!' 'Thank you for Listening!') )) )

Slide 23

Slide 23 text

ご清聴ありがとうございました ご清聴ありがとうございました ご清聴ありがとうございました ご清聴ありがとうございました ご清聴ありがとうございました ご清聴ありがとうございました Thank you for listening! Thank you for listening! Thank you for listening! Thank you for listening! Thank you for listening! Thank you for listening!