環境:Windows10, Nightwatchのバージョン:1.7.11
Nightwatchとは
NightwatchというjavascriptのE2Eのテストフレームワークを導入してみます。
Nightwatch公式サイト
https://nightwatchjs.org/
Nightwatchとは、日本語で宿直とかいう意味ですね。夜、見回りをする警備員さんのことです。
E2E はEnd to Endの略です。
 End to End は何かといいますと、ここでの意味は、ユーザーがする動作のようなテストを行うことですね。
例えば、ログインのページだと
「ユーザーがログインIDとパスワードを入力欄に入力し、ログインボタンをポチっと押すと、ログイン後のページに遷移して『ようこそ 〇〇様』と表示する。」
という流れをテストすることです。
ユニットテストがプログラムのメソッド単位でテストを行うことに対比して言われることが多いでしょう。
さて、先の例で行きますと
 「ユーザーがログインIDとパスワードを入力欄に入力し、ログインボタンをポチっと押すと、ログイン後のページに遷移して『ようこそ 〇〇様』と表示する。」
このテストを人間がいちいち行うのはまったくもって手間ですよね!
しかも、複数ブラウザで行うとかなると、手間×4ぐらいあります。
なので、ここは自動化しようというわけです。
余談ですが、弊社ではこのテストをGhost Inspectorというツールを使ってやっていました。が、 Ghost Inspector はソースコードの品質を高めるために役に立っているかというと、そうではなく、サービスの死活監視的に用いられているので、今回改めてもうちょっとjavascriptのプログラム的なテストフレームワークを導入してみようかなと思った次第です。(意識高く!(`・ω・´))
表題は導入してみる、となっていますが、本サービスに導入するかどうかは今の時点で未定です。(笑) ただ、開発環境としては作ってみたというところですね。
私自身はjavascript界からちょっと離れていました。
(こいつ、いつもこれ言ってんな…。(´ω`))
初心者なので、間違っているところ等ありましたら教えてください。
ではいよいよ、Window10にNightwatchをインストールします。
手順① Nightwatch をインストールするディレクトリを作る
まっさらな洗い立てのシーツのようなディレクトリを作ります。
ここでは、
D:\study\nightwatch
に作りました。
手順② Nightwatch自体をインストール
コマンドプロンプトを開いて、そのディレクトリ内に移動し、
npm install nightwatch
とやります。
すると下記の図のようにいろいろメッセージが表示されてインストールができます。

もし、npmがわからない、npmが動作しない場合は、node.jsとnpmをインストールして使えるようにしてください。
npmとはパッケージマネージャーと呼ばれるツールで、こういうフレームワークをインストールする場合などに使います。ナウなjs界では欠かせない存在なので、躊躇せずにインストールしてみてください。
これで、Nightwatch自体がインストールされました。
手順③ ChromeのWebdriverをインストール
同じディレクトリで
npm install chromedriver --save-dev
とやります。すると、下記のように表示されて、インストールが終わります。

これは何をインストールするのかというと、ChromeのWebdriverをインストールしています。手っ取り早く言うと、これがChromeを動作させてして、テストの時に使ってくれるわけです。
手順④ Selenium Serverインストール
次に同じディレクトリで、次のようにやります。
npm install selenium-server --save-de

すると、上記のようにメッセージが表示されて、インストールができます。
今回は、Selenium Serverというのをインストールしました。 Selenium Server は何かというと、③のChrome DriverはChromeを動作させますが、ほかのブラウザなどを動作させたりします。(現時点ではいらないのかもしれない)
これで、インストールするものは一通り終わりです。
手順⑤設定などを準備する
まだ設定などが必要です。さっきから使っている
D:\study\nightwatch
の中に、node_modulesというディレクトリができていて、ここにウジャッといろいろなモノが入っています。その中のnightwatchというディレクトリに、examplesというディレクトリがあって、そこにサンプルが入っています。ありがたや~
D:\study\nightwatch\node_modules\nightwatch\examples\tests
testというディレクトリの中の、ecosia.js というファイルをコピーして、nightwatchディレクトリの中に、test というディレクトリを作って、そこに貼り付けます。
このようになっているはずです!

ecosia.jsを参考までに貼っておきます。ちな、ecosiaはドイツの検索エンジン?らしいです。
describe('Ecosia.org Demo', function() {
  before(browser => browser.url('https://www.ecosia.org/'));
  test('Demo test ecosia.org', function (browser) {
    browser
      .waitForElementVisible('body')
      .assert.titleContains('Ecosia')
      .assert.visible('input[type=search]')
      .setValue('input[type=search]', 'nightwatch')
      .assert.visible('button[type=submit]')
      .click('button[type=submit]')
      .assert.containsText('.mainline-results', 'Nightwatch.js');
  });
  after(browser => browser.end());
});これがテストスクリプトです。解説すると、
というサイトを開き、タイトルが ’Ecosia’ で、検索ボックスにnightwatchと入れて検索して、クリックすると、Nightwatch.js という文字列が含まれるページが出てくる、というテストですね。
次の2つのファイルをD:\study\nightwatch に追加します。
global.js
const chromedriver = require('chromedriver');
module.exports = {
    before: function (done) {
        chromedriver.start();
        done();
    },
    after: function (done) {
        chromedriver.stop();
        done();
    }
};使うWebdriverなどを指定しています。
nightwatch.conf.js
// Autogenerated by Nightwatch
// Refer to the online docs for more details: https://nightwatchjs.org/gettingstarted/configuration/
const Services = {}; loadServices();
module.exports = {
  // An array of folders (excluding subfolders) where your tests are located;
  // if this is not specified, the test source must be passed as the second argument to the test runner.
  src_folders: ["test"],
  // See https://nightwatchjs.org/guide/working-with-page-objects/
  //page_objects_path: 'page-objects',
  // See https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-commands
  custom_commands_path:  '',
  // See https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-assertions
  custom_assertions_path: '',
  // See https://nightwatchjs.org/guide/#external-globals
  globals_path : './globals.js',
  webdriver: {},
  test_settings: {
    default: {
      disable_error_log: false,
      launch_url: 'https://nightwatchjs.org',
      screenshots: {
        enabled: false,
        path: 'screens',
        on_failure: true
      },
      desiredCapabilities: {
        browserName : 'firefox'
      },
      webdriver: {
        start_process: true,
        server_path: (Services.geckodriver ? Services.geckodriver.path : '')
      }
    },
    
    firefox: {
      desiredCapabilities : {
        browserName : 'firefox',
        alwaysMatch: {
          acceptInsecureCerts: true,
          'moz:firefoxOptions': {
            args: [
              // '-headless',
              // '-verbose'
            ]
          }
        }
      },
      webdriver: {
        start_process: true,
        port: 4444,
        server_path: (Services.geckodriver ? Services.geckodriver.path : ''),
        cli_args: [
          // very verbose geckodriver logs
          // '-vv'
        ]
      }
    },
    chrome: {
      desiredCapabilities : {
        browserName : 'chrome',
        'goog:chromeOptions' : {
          // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/
          //
          // This tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78)
          w3c: false,
          args: [
            //'--no-sandbox',
            //'--ignore-certificate-errors',
            //'--allow-insecure-localhost',
            //'--headless'
          ]
        }
      },
      webdriver: {
        start_process: true,
        port: 9515,
        server_path: (Services.chromedriver ? Services.chromedriver.path : ''),
        cli_args: [
          // --verbose
        ]
      }
    },
    edge: {
      desiredCapabilities : {
        browserName : 'MicrosoftEdge',
        'ms:edgeOptions' : {
          w3c: false,
          // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options
          args: [
            //'--headless'
          ]
        }
      },
      webdriver: {
        start_process: true,
        // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/
        //  and set the location below:
        server_path: '',
        cli_args: [
          // --verbose
        ]
      }
    },
    //////////////////////////////////////////////////////////////////////////////////
    // Configuration for when using the browserstack.com cloud service               |
    //                                                                               |
    // Please set the username and access key by setting the environment variables:  |
    // - BROWSERSTACK_USER                                                           |
    // - BROWSERSTACK_KEY                                                            |
    // .env files are supported                                                      |
    //////////////////////////////////////////////////////////////////////////////////
    browserstack: {
      selenium: {
        host: 'hub-cloud.browserstack.com',
        port: 443
      },
      // More info on configuring capabilities can be found on:
      // https://www.browserstack.com/automate/capabilities?tag=selenium-4
      desiredCapabilities: {
        'bstack:options' : {
          userName: '${BROWSERSTACK_USER}',
          accessKey: '${BROWSERSTACK_KEY}',
        }
      },
      disable_error_log: true,
      webdriver: {
        timeout_options: {
          timeout: 15000,
          retry_attempts: 3
        },
        keep_alive: true,
        start_process: false
      }
    },
    'browserstack.local': {
      extends: 'browserstack',
      desiredCapabilities: {
        'browserstack.local': true
      }
    },
    'browserstack.chrome': {
      extends: 'browserstack',
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions : {
          w3c: false
        }
      }
    },
    'browserstack.firefox': {
      extends: 'browserstack',
      desiredCapabilities: {
        browserName: 'firefox'
      }
    },
    'browserstack.ie': {
      extends: 'browserstack',
      desiredCapabilities: {
        browserName: 'internet explorer',
        browserVersion: '11.0'
      }
    },
    'browserstack.safari': {
      extends: 'browserstack',
      desiredCapabilities: {
        browserName: 'safari'
      }
    },
    'browserstack.local_chrome': {
      extends: 'browserstack.local',
      desiredCapabilities: {
        browserName: 'chrome'
      }
    },
    'browserstack.local_firefox': {
      extends: 'browserstack.local',
      desiredCapabilities: {
        browserName: 'firefox'
      }
    },
    //////////////////////////////////////////////////////////////////////////////////
    // Configuration for when using the Selenium service, either locally or remote,  |
    //  like Selenium Grid                                                           |
    //////////////////////////////////////////////////////////////////////////////////
    selenium_server: {
      // Selenium Server is running locally and is managed by Nightwatch
      selenium: {
        start_process: true,
        port: 4444,
        server_path: (Services.seleniumServer ? Services.seleniumServer.path : ''),
        cli_args: {
          'webdriver.gecko.driver': (Services.geckodriver ? Services.geckodriver.path : ''),
          'webdriver.chrome.driver': (Services.chromedriver ? Services.chromedriver.path : '')
        }
      }
    },
    'selenium.chrome': {
      extends: 'selenium_server',
      desiredCapabilities: {
        browserName: 'chrome',
        chromeOptions : {
          w3c: false
        }
      }
    },
    'selenium.firefox': {
      extends: 'selenium_server',
      desiredCapabilities: {
        browserName: 'firefox',
        'moz:firefoxOptions': {
          args: [
            // '-headless',
            // '-verbose'
          ]
        }
      }
    }
  }
};
function loadServices() {
  try {
    Services.seleniumServer = require('selenium-server');
  } catch (err) {}
  try {
    Services.chromedriver = require('chromedriver');
  } catch (err) {}
  try {
    Services.geckodriver = require('geckodriver');
  } catch (err) {}
}
テストのプログラムはtestディレクトリにあるよ、などが書いてあります。
手順⑦テストを実行
ハァハァ、いよいよ…。テスト実行です。D:\study\nightwatchで
.\node_modules.bin\nightwatch -v
とやります。
おおっ!

OK. 5 assertions passed. (1.818s
と表示されましたね!!
そして、皆さんの目の前で、ブラウザっぽい画面が一瞬開いて検索っぽいことをやっているのが見えたでしょうか?
今回は基本のキでインストールして動作させるところだけで終わってしまいました。
