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/

相关文章
相关标签/搜索