サーチ…


備考

NightwatchはMeteorアプリケーションの受け入れとエンドツーエンドのテストをv0.5日から提供しており、PHPからSpark to BlazeとReactへの移行を管理しています。すべての主要なContinuous Integrationプラットフォームをサポートします。その他のヘルプについては、以下を参照してください。

Nightwatch APIドキュメント
Nightwatch.js Googleグループ

アプリケーションの表面積

最も基本的なレベルでは、受け入れテストは本質的にクローズドシステムの入力と出力のテストに関係するブラックボックステストです。したがって、受け入れテストには、リソースの特定、データの読み取り、データの書き込みという3つの重要な機能があります。ブラウザーやWebアプリケーションに関しては、これらの3つの機能は基本的に次のようになっています。

  1. Webページまたはアプリケーションビューを読み込む
  2. ユーザーインターフェイス要素(DOMなど)を検査する
  3. イベントのトリガー/ユーザーとの対話のシミュレート

これをアプリケーションの表面領域と呼びます。表面積は、ユーザーが見たり、経験しているものです。それはブラックボックスシステムの外部です。また、ユーザーはWebブラウザを使用してビデオ画面上の最新のWebアプリケーションとやりとりするため、表面のカバレッジはユニバーサルリソースロケータ(URL)とビューポートによって定義されます。そして、私たちの最初のウォークスルーは、次のようなものから始まります。

module.exports = {
  "Hello World" : function (client) {
    client
      // the location of our Meteor app
      .url("http://localhost:3000")

      // the size of the viewport 
      .resizeWindow(1024, 768)

      // test app output
      .verify.elementPresent('h1')
      .verify.containsText('h1', "Welcome to Meteor!")
      .verify.containsText('p', "You've pressed the button 0 times")
      .verify.elementPresent('button')

      // simulate user input
      .click('button').pause(500)

      // test app output again, to make sure input worked
      .verify.containsText('p', "button 1 times")

      // saving a copy of our viewport pixel grid
      .saveScreenshot('tests/nightwatch/screenshots/homepage.png')
      .end();
  }
};

カスタムコマンド

Nightwatchは、キーストローク、マウスクリック、その他の入力をシミュレートできるカスタムコマンドの作成をサポートしています。カスタムコマンドは他のNightwatchコマンドと連鎖することができます:

module.exports = {
  "Login App" : function (client) {
    client
      .url("http://localhost:3000")
      .login("[email protected]", "janedoe123")
      .end();
  }
};

これを有効にするには、. ./tests/nightwatch/commands/login./tests/nightwatch/commands/loginようにコマンドを定義します。

exports.command = function(username, password) {

  this
    .verify.elementPresent('#login')

      // we clear the input in case there's any data remaining from previous visits
      .clearValue("#emailInput")
      .clearValue("#passwordInput")

      // we simulate key presses
      .setValue("#emailInput", username)
      .setValue("#passwordInput", password)

    // and we simulate a mouse click
    .click("#signInToAppButton").pause(1000)

  return this; // allows the command to be chained.
};

これをすべてidするには、ログインページにid属性を追加する必要があります。あるレベルでは、おおよそ以下のようなものが必要になります。

<template name="login">
  <div id="login">
    <input id="emailInput" name="email" type="email" />
    <input id="passwordInput" name="password" type="password" />
    <button id="#signInToAppButton">Sign In</button>
  </div>
</template>

クライアント上の流星オブジェクトの検査

Nightwatchはブラウザコンソールにアクセスできるため、 .execute() APIを使用してクライアント側オブジェクトを検査することができます。次の例では、Sessionオブジェクトで特定のセッション変数をチェックしています。まず、. ./tests/nightwatch/api/meteor/checkSessionファイルを作成します。ここでは次のコマンドを使用します。

// syncrhonous version; only works for checking javascript objects on client
exports.command = function(sessionVarName, expectedValue) {
  var client = this;
  this
    .execute(function(data){
      return Session.get(data);
    }, [sessionVarName], function(result){
      client.assert.ok(result.value);
      if(expectedValue){
        client.assert.equal(result.value, expectedValue);
      }
    })
    return this;
};

そうしてチェーンすることができます:

module.exports = {
  "Check Client Session" : function (client) {
    client
      .url("http://localhost:3000")
      .checkSession("currentUser", "Jane Doe")
      .end();
  }
};

フォームと入力タイプ

ファイルをアップロードするには、まず/ dataディレクトリを作成し、アップロードするファイルを追加する必要があります。

tests/nightwatch/data/IM-0001-1001.dcm

あなたのフォームには、ファイルタイプの入力が必要です。 (この入力が提供するスタイリングオプションが嫌いな人もいれば、この入力を非表示にし、ページ上の別のボタンをユーザの代わりにクリックすることもできます)。

<form id="myform">
    <input type="file" id="fileUpload">
    <input type="text" name="first_name">
    <input type="text" name="last_name">

    <input type="date" name="dob_month">
    <input type="date" name="dob_day">
    <input type="date" name="dob_year">

    <input type="radio" name="gender" value="M">
    <input type="radio" name="gender" value="F">
    <input type="radio" name="gender" value="O">

    <input type="select" name="hs_graduation_year">
    <input type="text" name="city">
    <input type="select" name="state">

    <input type="submit" name="submit" value="Submit">
</form>

テストでは、setValue()を使用してローカルファイルアセットへのパスを解決する必要があります。

module.exports = {
  "Upload Study" : function (client) {
    console.log(require('path').resolve(__dirname +  '/../data' ));

    var stringArray = "Chicago";

    client
      .url(client.globals.url)
      .verify.elementPresent("form#myform")

      // input[type="file"]
      .verify.elementPresent("input#fileUpload")
      .setValue('input#fileUpload', require('path').resolve(__dirname + '/../data/IM-0001-1001.dcm'))

      // input[type="text"]
      .setValue('input[name="first_name"]', 'First')
      .setValue('input[name="last_name"]', 'Last')

      // input[type="date"]
      .click('select[name="dob_month"] option[value="3"]')
      .click('select[name="dob_day"] option[value="18"]')
      .click('select[name="dob_year"] option[value="1987"]')

      // input[type="radio"]
      .click('input[name="gender"][value="M"]')

      // input[type="number"]
      .click('select[name="hs_graduation_year"] option[value="2002"]')

      // input[type="text"]
      // sometimes Nightwatch will send text faster than the browser can handle
      // which will cause skipping of letters.  In such cases, we need to slow
      // Nightwatch down; which we do by splitting our input into an array
      // and adding short 50ms pauses between each letter
      for(var i=0; i < userIdArray.length; i++) {
        client.setValue('input[name="city"]', stringArray[i]).pause(50)
      }

      // input[type="select"]
      // after an array input above, we need to resume our method chain...
      client.click('select[name="state"] option[value="CA"]')

      // input[type="number"]
      .setValue('input[name="zip"]', '01234')

      //input [ type="submit" ]
      .click('button[type="submit"]')
      .end();
  }
};

この例を掘り下げるためのDaniel Rinehartの功績。

コンポーネントとページオブジェクト

ページオブジェクトはカスタムコマンドに似ています。特定のUIコンポーネントに関連付けられているカスタムコマンドのコレクションである点が異なります。これは、Reactなどの最新のコンポーネントベースの設計では非常にうまく機能します。

module.exports = {
  url: 'http://localhost:3000/login',
  commands: [{
  login: function(email, password) {
    return this
      .clearValue('input[name="emailAddress"]')
      .clearValue('input[name="password"]')

      .setValue('input[name="emailAddress"]', email)
      .setValue('input[name="password"]', password)

      .verify.elementPresent('#loginButton')
      .click("#loginButton");
  },
  clear: function() {
    return this
      .waitForElementVisible('@emailInput')
      .clearValue('@emailInput')
      .clearValue('@passInput')
      .waitForElementVisible('@loginButton')
      .click('@loginButton')
  },
  checkElementsRendered: function(){
    return this
      .verify.elementPresent("#loginPage")
      .verify.elementPresent('input[name="emailAddress"]')
      .verify.elementPresent('input[name="password"]')
  },
  pause: function(time, client) {
    client.pause(time);
    return this;
  },
  saveScreenshot: function(path, client){
    client.saveScreenshot(path);
    return this;
  }
}],
  elements: {
    emailInput: {
      selector: 'input[name=email]'
    },
    passInput: {
      selector: 'input[name=password]'
    },
    loginButton: {
      selector: 'button[type=submit]'
    }
  }
};

コンポーネントのテストでPageObjectパターンを使用する唯一の注意点は、ネイティブのNightwatch verify.elementPresent提供するメソッド連鎖フローをverify.elementPresentすることです。代わりに、ページオブジェクトを変数に割り当て、ページごとに新しいメソッドチェーンをインスタンス化する必要があります。コードの再利用をテストするための一貫した信頼性の高いパターンを支払うための妥当な価格。

module.exports = {
  tags: ['accounts', 'passwords', 'users', 'entry'],
  'User can sign up.': function (client) {

    const signupPage = client.page.signupPage();
    const indexPage = client.page.indexPage();

    client.page.signupPage()
      .navigate()
      .checkElementsRendered()
      .signup('Alice', 'Doe', '[email protected]', 'alicedoe')
      .pause(1500, client);

    indexPage.expect.element('#indexPage').to.be.present;
    indexPage.expect.element('#authenticatedUsername').text.to.contain('Alice Doe');
  },
}


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow