编写测试

官方推荐首选使用CSS选择器模型来定位页面上的元素,Nightwatch会让编写E2E自动化测试非常容易。

在项目中为测试文件创建一个单独的文件夹。例如:tests文件夹,这样它里面的每一个文件都会加载执行,一个基本的测试是这样的:

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();
  }
};

当你想要关闭的测试时,请记住调用.end()方法,这样可以Selenium会话正确地关闭。

如果你想让一个测试文件中包含多个测试步骤,你可以这样写:

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();
  }
};

也可以使用这种格式写:

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选择器。如果想把定位策略从css选择器切换到xpath选择器,你需要调用useXpath()方法,切换回CSS调用useCss()方法。如果你想把xpath作为默认,可以在test settings(通常是nightwatch.conf.js文件)中设置"use_xpath": true。

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 期望断言

Nightwatch在v0.7版本之后引入了新的BDD方式的断言库(什么是BDD可以查百科这里不多介绍),它极大地提高了断言的灵活性和可读性。

expect断言是使用Chai框架中的Expect一个子集,请看这里的例子:

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

    // expect element  to be present in 1000ms
    client.expect.element('body').to.be.present.before(1000);

    // expect element <#lst-ib> to have css property 'display'
    client.expect.element('#lst-ib').to.have.css('display');

    // expect element  to have attribute 'class' which contains text 'vasq'
    client.expect.element('body').to.have.attribute('class').which.contains('vasq');

    // expect element <#lst-ib> to be an input tag
    client.expect.element('#lst-ib').to.be.an('input');

    // expect element <#lst-ib> to be visible
    client.expect.element('#lst-ib').to.be.visible;

    client.end();
  }
};

expect接口提供一个更加灵活和流畅的语言,在现有的assert接口上有了显著的改进。惟一的缺点是不能再对断言进行链锁了,此时还不支持自定义消息。

对于expect断言的完整列表,请参考API docs

使用before[Each] and after[Each]

Nightwatch提供了标准的before / after 和 beforeEach / afterEach 钩子在测试代码中使用。

before 和 after 会在test suit的开始之前和结束之后运行。

beforeEach 和 afterEach 会在每个testcase(test step)开始之前和结束之后运行。

例子:

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钩子只能在它的异步形式中接收brower对象——afterEach(brower, done){..}

异步before[Each] and after[Each]

所有的before[Each]after[Each]方法都可以执行异步操作,在这种情况下,他们将作为第二参数传递的回调。

在异步操作完成时,在最后一步必须调用done方法,不调用它将会导致超时错误。

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来控制调用超时

默认情况下,完成的调用超时设置为10秒(单元测试2秒)。在某些情况下,这可能是不够的,为了避免了超时错误,你可以通过在外部全局文件中定义一个asyncHookTimeout属性(以毫秒为单位)来控制超时时间 (请参阅下面的外部全局变量的详细信息)。

例如,请参考所提供的globalsModule一个样例示例。

明确失败的测试

简单的调用done的Error参数可以让一个test hook有意去失败。例如:

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

外部全局变量

大多数情况下,在外部文件中定义全局变量更有用,在globals_path属性中指定,而不是在nightwatch.json中定义。

你可以根据需要覆盖每个环境的全局变量,假设你的测试在本地运行,并且在远程服务器上运行。大多数时候,你需要一些不同的设置。

全局Hooks

在每组测试套件的全局范围内和范围之外可以使用同一套hooks。更多细节,请参见下面的示例。在全局钩子的情况下,beforeEach和afterEach 引用了一个测试套件(即测试文件),在测试套件之前和之后运行。

全局设置

有许多全局变量在进行测试设置,并且可以控制测试执行。在globalsModule样本中有详细信息。例如:

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

  'integration' : {
    isLocal : false
  },

  // External before hook is ran at the beginning of the tests run, before creating the Selenium session
  before: function(done) {
    // run this only for the local-env
    if (this.isLocal) {
      // start the local server
      App.startServer(function() {
        // server listening
        done();
      });
    } else {
      done();
    }
  },

  // External after hook is ran at the very end of the tests run, after closing the Selenium session
  after: function(done) {
    // run this only for the local-env
    if (this.isLocal) {
      // start the local server
      App.stopServer(function() {
        // shutting down
        done();
      });
    } else {
      done();
    }
  },

  // This will be run before each test suite is started
  beforeEach: function(browser, done) {
    // getting the session info
    browser.status(function(result) {
      console.log(result.value);
      done();
    });
  },

  // This will be run after each test suite is finished
  afterEach: function(browser, done) {
    console.log(browser.currentTest);
    done();
  }
};

results matching ""

    No results matching ""