読者です 読者をやめる 読者になる 読者になる

nightmare.js で E2E テストをする足がかりを探る

はじめに

弊社で稼働中のプラットフォームでは、rspec によるテストを流していますが、End to End テストと呼ばれているレベルのテストはまだ動いていません。 そこで、nightmare.js を使って、E2E テストをしつつ、稼働中の 154 サイトすべてのスクリーンショットを撮ってみたいと思います。

ディレクトリを作って package.json を生成する

適当にディレクトリを作ります

mkdir myfirste2etest && cd myfirste2etest

node の バージョンを指定して npm init します。今回は現時点の stable である v4.0.0 を利用しました。

nvm use v4.0.0
npm init

いろいろ尋ねられるので以下のように答えました。

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (myfirste2etest)
version: (1.0.0) 0.0.1
description: My First End to End Test
entry point: (index.js)
test command:
git repository:
keywords: nightmare.js
author: okamoto-skiyaki
license: (ISC)
About to write to /Users/motchang/src/myfirste2etest/package.json:

{
  "name": "myfirste2etest",
  "version": "0.0.1",
  "description": "My First End to End Test",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "nightmare.js"
  ],
  "author": "okamoto-skiyaki",
  "license": "ISC"
}


Is this ok? (yes) yes

ここで一応 git init しておきます。.gitignore の生成に gibo を使用してみました。便利!

参考:気付いたら.gitignoreはgiboで自動生成する時代になっていた

git init
brew install gibo
gibo node osx emacs > .gitignore
git add .
git commit -m 'initial commit'

nightmare.js, そして普段 coffee script で開発を行っているので、coffee script も入れます。 また、運用中のサイト情報が mysql にありますので、mysql もついでに入れてしまいます。

npm install --save-dev nightmare
npm install --save-dev coffee-script
npm install --save-dev mysql

スクリーンショット保存用のディレクトリを作る

mkdir screenshots

カカカッっとスクリプトを書く

MySQL からドメインの一覧を取得し、MSIE を名乗った時と iPhone を名乗った時のスクリーンショットを撮ってみました。

Nightmare = require('nightmare')
nightmare = Nightmare({show: true})

MySQL = require('mysql')

browsers = [
  {name: 'msie', ua: 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko', width: 1920, height: 1080},
  {name: 'iphone6', ua: 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_0 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13A344 Safari/601.12', width: 375, height: 627}
]

connection = MySQL.createConnection({
  host: process.env.MYSQL_HOST || 'localhost',
  user: process.env.MYSQL_USER || 'root',
  password: process.env.MYSQL_PASSWORD || '',
  database: process.env.MYSQL_DATABASE || 'test',
  port: process.env.MYSQL_PORT || 3306
})
connection.connect()

connection.query('SELECT * FROM sites WHERE closed_flag = 0;',
  (err, rows) ->
    if (err != null)
      console.log(err)
      throw err
    for row in rows
      url = "#{row.site_protocol}://#{row.site_domain}"
      for browser in browsers
        nightmare
          .viewport(browser.width, browser.height)
          .useragent(browser.ua)
          .goto(url)
          .wait()
          .wait(1000)
          .screenshot("screenshots/#{row.site_domain}_#{browser.name}.png")
          .end()
    nightmare.run()
)

connection.end()

以下のようにスクリーンショットの一覧が完成します。

f:id:system-skiyaki:20160229235206p:plain

f:id:system-skiyaki:20160229235234p:plain

f:id:system-skiyaki:20160229234753p:plain

本当はページ全体のスクリーンショットを撮ろうと考えていたのですが、付け焼き刃の nightmare 能力ではなんともなりませんでした…。それっぽいコメント を見つけたのですが、上手くいかず。これからの課題にしたいと思います。