LoginSignup
8
2

More than 5 years have passed since last update.

Nightwatch.jsでPageObjectを試しました。

Posted at

お疲れ様です。@naokiurです。

Selenideを使ってPageObjectをやったことはありましたが、
Vue.jsを使っている兼ね合いで、
Nightwatch.jsでPageObjectを試しました。

環境

  • MacBook Pro (Retina 13-inch、Early 2015)
  • OS X El Capitan 10.13.6
  • node v8.12.0
  • npm 6.4.1

実施したこと

簡単な、 入力して内容を表示するみたいな画面を用意して、
それに対してテストコードを書きました。

上のテキストボックスに値を入れて、
sendをクリックすると、
下のテキストボックスに反映される、というものです。

try-coding-nightwatch.gif

自分で言うのもアレですが、
なんとも陳腐な画面です。

画面とテストコードは以下です。

テスト対象画面

TestTarget.vue
<template>
  <div>
    <section>
      <input type="text" name="inputData" v-model="inputData" placeholder="please enter some test!" />
    </section>
    <section>
      <input type="button" value="send" @click="send" />
    </section>
    <section>
      <input type="text" name="resultData" :value="result" />
    </section>
  </div>
</template>

<script>
  export default {
    name: 'testTarget',
    data () {
      return {
        inputData: '',
        result: 'before'
      }
    },
    methods: {
      send: function () {
        this.result = this.inputData
      }
    }
  }
</script>

<style scoped>

</style>

テストコード

test.js
module.exports = {
  'input test': function (browser) {
    const targetPage = browser.page.testTargetPage()

    targetPage.navigate()
      .assert.visible('@inputData')
      .setValue('@inputData', 'test')
      .send()
      .assert.value('@resultData', 'test')

    browser.end()
  } 
}

testTargetPage.js
const pageCommands = {
    send: function () {
        return this.waitForElementVisible('@sendButton', 1000)
            .click('@sendButton') 
    }
}

module.exports = {
    commands: [pageCommands],
    url: function () {
        return this.api.globals.devServerURL
    },
    elements: {
        inputData: {
            selector: 'input[name=inputData]'
        },
        sendButton: {
            selector: 'input[type=button]'
        },
        resultData: {
            selector: 'input[name=resultData]'
        }
    }
}
nightwatch.conf.js
require('babel-register')
var config = require('../../config')

module.exports = {
  src_folders: ['test/e2e/specs'],
  output_folder: 'test/e2e/reports',
  custom_assertions_path: ['test/e2e/custom-assertions'],
  page_objects_path: ['test/e2e/pageObjects'],

  selenium: {
    start_process: true,
    server_path: require('selenium-server').path,
    host: '127.0.0.1',
    port: 4444,
    cli_args: {
      'webdriver.chrome.driver': require('chromedriver').path
    }
  },

  test_settings: {
    default: {
      selenium_port: 4444,
      selenium_host: 'localhost',
      silent: true,
      globals: {
        devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
      }
    },

    chrome: {
      desiredCapabilities: {
        browserName: 'chrome',
        javascriptEnabled: true,
        acceptSslCerts: true
      }
    },

    firefox: {
      desiredCapabilities: {
        browserName: 'firefox',
        javascriptEnabled: true,
        acceptSslCerts: true
      }
    }
  }
}

ディレクトリ構成

project_root
    |- src
        |- page
            |- TestTarget.vue
    |- test
        |- e2e
            |- pageObjects
                |- testTargetPage.js
            |- specs
                |- test.js
            |- nightwatch.conf.js

ハマったところ

  • .assert.visible('@inputData')が失敗する!
    • navigate()を忘れていて、そもそもアクセスしていなかった
  • 公式の通りに、testTargetPage.jsにcommandを書いたけれど、this.waitForElementVisible is not functionが発生する!

結果

  • PageObjectパターンを反映させることにより、テストコードをたくさん書いたあと、DOMの構成が変わっても、PageObjectだけ書き換えればよくなりました。
  • Commandを作成して置くことにより、テストコードがスッキリしました。
    • サンプルの画面だと、シンプルすぎて良さがわかりにくいかもしれませんが、もっと色々やる画面ならば、良さが分かる、と期待しています。

参考にさせて頂きました

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2