nightwatch系列教程02——開發者指南:使用Nightwatch

本章內容翻譯自http://nightwatchjs.org/guide#using-nightwatchjavascript

編寫測試

在頁面上使用推薦的CSS選擇器,nightwatch讓編寫自動化測試變得很簡單。
在你的項目中建立一個獨立的文件夾,好比:tests。這裏面的每一個文件都會被nightwatch的測試運行器加載運行。一個基礎的測試文件長這樣:css

module.exports = {
  'Demo test Google' : function (browser) {
    browser
      .url('http://www.google.com')
      .waitForElementVisible('body', 1000)
      .setValue('input[type=text]', 'nightwatch')
      .waitForElementVisible('button[name=btnG]', 1000)
      .click('button[name=btnG]')
      .pause(1000)
      .assert.containsText('#main', 'Night Watch')
      .end();
  }
};

爲了讓Selenium會話能夠正常關閉,當你想結束測試的時候,記住要調用 .end() 方法java

若是須要的話,一個測試文件也能夠包含多個步驟:git

module.exports = {
  'step one' : function (browser) {
    browser
      .url('http://www.google.com')
      .waitForElementVisible('body', 1000)
      .setValue('input[type=text]', 'nightwatch')
      .waitForElementVisible('button[name=btnG]', 1000)
  },

  'step two' : function (browser) {
    browser
      .click('button[name=btnG]')
      .pause(1000)
      .assert.containsText('#main', 'Night Watch')
      .end();
  }
};

測試文件也能夠按照這種格式來寫:github

this.demoTestGoogle = function (browser) {
  browser
    .url('http://www.google.com')
    .waitForElementVisible('body', 1000)
    .setValue('input[type=text]', 'nightwatch')
    .waitForElementVisible('button[name=btnG]', 1000)
    .click('button[name=btnG]')
    .pause(1000)
    .assert.containsText('#main', 'The Night Watch')
    .end();
};

使用XPath選擇器

Nightwatch 一樣也支持 xpath 選擇器。經過下面的例子能夠看到,使用 useXpath() 就能夠切換成 xpath 做爲你的元素定位策略。切換回 css 選擇器,調用 useCss() 便可。json

若是你想將 xpath 做爲你的默認選擇器的話,在你的test setting中,設置屬性 「use_xpath」: true 便可。api

this.demoTestGoogle = function (browser) {
  browser
    .useXpath() // every selector now must be xpath
    .click("//tr[@data-recordid]/span[text()='Search Text']")
    .useCss() // we're back to CSS now
    .setValue('input[type=text]', 'nightwatch')
};

BDD Expect 斷言

Nightwatch從版本v0.7開始引入了一個新的BDD風格的斷言庫,它極大地提升了斷言的靈活性和可讀性。服務器

expect斷言使用來自 Chai 框架的Expect api的子集,此時僅可用於元素。 這是一個例子:框架

module.exports = {
  'Demo test Google' : function (client) {
    client
      .url('http://google.no')
      .pause(1000);

    // 指望body元素1000ms後顯示
    client.expect.element('body').to.be.present.before(1000);

    // 指望id爲lst-ib的元素擁有display的css屬性
    client.expect.element('#lst-ib').to.have.css('display');

    // 指望body元素的class屬性中包含vasq
    client.expect.element('body').to.have.attribute('class')
    .which.contains('vasq');

    // 指望id爲lst-ib的元素是一個input
    client.expect.element('#lst-ib').to.be.an('input');

    // 指望id爲lst-ib的元素可見
    client.expect.element('#lst-ib').to.be.visible;

    client.end();
  }
};

expect接口爲定義斷言提供了更加靈活和流暢的語言,與現有的斷言接口相比有了顯着的改進。 惟一的缺點是再也不可能連接斷言,而且此時尚不支持自定義消息。異步

有關可用expect斷言的完整列表,請參閱 API 文檔。

使用 before[Each] and after[Each] 鉤子

Nightwatch 爲測試文件提供了標準的 before/afterbeforeEach/afterEach 鉤子。
before 和 after 鉤子分別會在測試套件(test suite)執行以前和以後執行,而beforeEach 和 afterEach 則會在每一個測試用例/步驟(test step)以前和以後執行。

全部鉤子函數都有一個Nightwatch的實例做爲參數。
例子:

module.exports = {
  before : function(browser) {
    console.log('Setting up...');
  },

  after : function(browser) {
    console.log('Closing down...');
  },

  beforeEach : function(browser) {

  },

  afterEach : function() {

  },

  'step one' : function (browser) {
    browser
     // ...
  },

  'step two' : function (browser) {
    browser
    // ...
      .end();
  }
};

在這裏例子中,各個方法的調用順序:before(), beforeEach(), "step one", afterEach(), beforeEach(), "step two", afterEach(), after()

出於向後兼容性緣由,afterEach 鉤子只能以異步的形式接收browser參數,像這樣子:
afterEach(browser, done) { .. }

異步的 before[Each] 和 after[Each]

全部的 before[Each]after[Each] 均可以用來進行異步的操做,這時須要接收一個回調函數做爲第二個參數。

當一個異步操做結束的時候,done函數必須做爲最後一步被調用。不然將會致使timeout的錯誤。

一個包含 beforeEach 和 afterEach 的例子

module.exports = {
  beforeEach: function(browser, done) {
    // performing an async operation
    setTimeout(function() {
      // finished async duties
      done();
    }, 100);
  },

  afterEach: function(browser, done) {
    // performing an async operation
    setTimeout(function() {
      // finished async duties
      done();
    }, 200);
  }
};

控制 done函數的調用超時

默認狀況下done的超時時間是10秒(單元測試是2s)。但某些狀況下這是不夠的,爲了不timeout錯誤,你能夠在外部的全局設置文件中,經過定義一個asyncHookTimeout的屬性(以毫秒爲單位)增長這個時長。你能夠參考這個外部全局變量的配置例子:globalsModule

指定特定的測試失敗

故意的讓一個測試失敗能夠經過給done傳遞一個Error參數來實現。

module.exports = {
  afterEach: function(browser, done) {
    // performing an async operation
    performAsync(function(err) {
      if (err) {
        done(err);
      }
      // ...
    });
  }
};

外部的全局變量

大多數狀況下,經過globals_path屬性中指定一個外部blobal文件來定義全局變量,會比在nightwatch.json中定義更有用。你能夠根據須要覆蓋每一個環境的全局變量。假設你在本地運行測試,而且還在遠程服務器上運行。大多數時候你須要一些不一樣的設置。

全局鉤子

在測試範圍以外,全局也可使用與測試套件相同的一組鉤子。在全局鉤子的狀況下,beforeEachafterEach 引用測試套件(即測試文件,test suite),並在測試套件以前和以後運行。

全局變量

有一些測試配置的全局變量能夠控制測試的執行。這是一個 globalsModule
的例子。

例子:

module.exports = {
  'default' : {
    isLocal : true,
  },

  'integration' : {
    isLocal : false
  },

  // 外部的before鉤子在整個測試的一開始運行,在建立Selenuim會話以前
  before: function(done) {
    // 只在本地運行
    if (this.isLocal) {
      // 啓動本地服務器
      App.startServer(function() {
        // server listening
        done();
      });
    } else {
      done();
    }
  },

  // 外部的after鉤子在整個測試的最後運行,在關閉Selenuim會話以後
  after: function(done) {
    // 只在本地運行
    if (this.isLocal) {
      // 關閉本地服務器
      App.stopServer(function() {
        // shutting down
        done();
      });
    } else {
      done();
    }
  },

  // 這會在每一個測試文件執行以前運行
  beforeEach: function(browser, done) {
    // 獲取會話信息
    browser.status(function(result) {
      console.log(result.value);
      done();
    });
  },

  // 這會在每一個測試文件結束以後執行
  afterEach: function(browser, done) {
    console.log(browser.currentTest);
    done();
  }
};

github

本文發表在個人我的博客中,歡迎圍觀,發現其餘乾貨~博客地址 https://jerryyuanj.github.io/

相關文章
相關標籤/搜索