Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PageObjectPattern使うのやめた話

tsuemura
April 19, 2019

 PageObjectPattern使うのやめた話

2019/4/19 Selenium Conf Tokyo 2019 Lightning Talk

tsuemura

April 19, 2019
Tweet

More Decks by tsuemura

Other Decks in Technology

Transcript

  1. 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.

    View Slide

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


















    View Slide

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

    View Slide

  4. スライドに出てくるサンプルコードは
    スライドに出てくるサンプルコードは
    スライドに出てくるサンプルコードは
    スライドに出てくるサンプルコードは
    スライドに出てくるサンプルコードは
    スライドに出てくるサンプルコードは
    CodeceptJS
    で書かれています
    CodeceptJS
    で書かれています
    CodeceptJS
    で書かれています
    CodeceptJS
    で書かれています
    CodeceptJS
    で書かれています
    CodeceptJS
    で書かれています
    https://codecept.io
    https://codecept.io
    https://codecept.io
    https://codecept.io
    https://codecept.io
    https://codecept.io
    (
    なるべくフレームワーク特有の機能は使わず説明します)
    (
    なるべくフレームワーク特有の機能は使わず説明します)
    (
    なるべくフレームワーク特有の機能は使わず説明します)
    (
    なるべくフレームワーク特有の機能は使わず説明します)
    (
    なるべくフレームワーク特有の機能は使わず説明します)
    (
    なるべくフレームワーク特有の機能は使わず説明します)

    View Slide

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

    View Slide

  6. Page Object Pattern

    Page Object Pattern

    Page Object Pattern

    Page Object Pattern

    Page Object Pattern

    Page Object Pattern

    知らない人?
    知らない人?
    知らない人?
    知らない人?
    知らない人?
    知らない人?

    View Slide

  7. 一応解説: 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')
    )

    View Slide

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


















    View Slide

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

    View Slide

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

    View Slide

  11. 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 =
    = {
    {...
    ...}
    }

    View Slide

  12. 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'

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  19. コンポーネントを抽象化した
    コンポーネントを抽象化した
    コンポーネントを抽象化した
    コンポーネントを抽象化した
    コンポーネントを抽象化した
    コンポーネントを抽象化した
    たとえばBootstrap
    の入力フォーム
    たとえばBootstrap
    の入力フォーム
    たとえばBootstrap
    の入力フォーム
    たとえばBootstrap
    の入力フォーム
    たとえばBootstrap
    の入力フォーム
    たとえばBootstrap
    の入力フォーム
    <
    div class
    class=
    ="
    "form-group
    form-group"
    ">
    >
    <
    label>
    >Email address
    Email address
    label>
    >
    <
    input type
    type=
    ="
    "email
    email"
    " class
    class=
    ="
    "form-control
    form-control"
    "
    placeholder
    placeholder=
    ="
    "Enter email
    Enter email"
    ">
    >

    div>
    >

    View Slide

  20. コンポーネントを抽象化した
    コンポーネントを抽象化した
    コンポーネントを抽象化した
    コンポーネントを抽象化した
    コンポーネントを抽象化した
    コンポーネントを抽象化した
    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]')
    )
    同じコンポーネントを使っていれば汎用的に使いまわせる
    同じコンポーネントを使っていれば汎用的に使いまわせる
    同じコンポーネントを使っていれば汎用的に使いまわせる
    同じコンポーネントを使っていれば汎用的に使いまわせる
    同じコンポーネントを使っていれば汎用的に使いまわせる
    同じコンポーネントを使っていれば汎用的に使いまわせる

    View Slide

  21. 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 =
    = {
    {...
    ...}
    }

    View Slide

  22. コンポーネントを抽象化したロケータを
    コンポーネントを抽象化したロケータを
    コンポーネントを抽象化したロケータを
    コンポーネントを抽象化したロケータを
    コンポーネントを抽象化したロケータを
    コンポーネントを抽象化したロケータを
    一つ作りましょう
    一つ作りましょう
    一つ作りましょう
    一つ作りましょう
    一つ作りましょう
    一つ作りましょう
    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!')
    ))
    )

    View Slide

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

    View Slide