nightwatch编写测试

使用describe()接口

从1.3版开始,Nightwatch 原生支持使用流行的 BDD 接口编写测试。无需进一步配置。也可以一起运行用 BDD describe 和 Exports 接口编写的测试。
Nightwatch 中的 BDD(行为驱动开发) 接口提供了常用的describe(), context(), test(), it(), specify(), before(), after(), beforeEach(), afterEach()功能。
Nightwatch 不支持嵌套describe/context声明。仅支持顶层,它定义了测试套件的名称。
例子:


describe('Ecosia', function() {

  // 也可使用 test() and specify() 

  it('demo test', function(browser) {
    browser
      .url('https://www.ecosia.org/')
      .setValue('input[type=search]', 'nightwatch')
      .click('button[type=submit]')
      .assert.containsText('.mainline-results', 'Nightwatch.js')
      .end();
  });

});

除了通用的BDD语法,nightwatch还提供了一些定义自己的行为方式
测试用例特定功能


describe('homepage test with describe', function() {
  // 特定功能的测试用例
  this.desiredCapabilities = {
    browserName: 'firefox'
  };

  it('...', function() {...});
});

测试用例特定标签


describe('homepage test with describe', function() {
  // 定义使用bdd的标签
  this.tags = ['login', 'authentication''];

  it('...', function() {...});
});

测试用例特定重试


describe('homepage test with describe', function() {
  // 当前测试重试失败所使用的时间
   this.retries(3);

   // 在断言失败或错误的情况下重试当前测试的次数
   this.suiteRetries(2);

   it('...', function() {...});
});

完整的BDD语法

describe('homepage test with describe', function() {
  // 所有配置项均可通过this.settings获取
  // console.log('Settings', this.settings);

  // 测试用例指定功能
  // this.desiredCapabilities = {};

  // 若当前测试为单元/集成测试则开启(即不会创建Webdriver会话)
  // this.unitTest = false

  // 若希望浏览器窗口在测试失败或出错时仍开启,则设置为false(通常用于debug)
  // this.endSessionOnFail = true

  // 若你希望在当前测试失败或出错时继续指向后续测试,则设置为false
  // this.skipTestcasesOnFail = true

  // 是否跳过此测试
  // this.disabled = false

  // this.retries(3);
  // this.suiteRetries(2);

  // 控制断言或元素命令超时时间
  // this.timeout(1000)

  // 控制重试的间隔
  // this.retryInterval(100);

  before(function(browser) {
    this.homepage = browser.page.home();
  });

  it('startHomepage', () => {
    this.homepage.navigate();
    this.homepage.expect.section('@indexContainer').to.be.not.visible;
  });


  // Run only this testcase
  /
  it.only('startHomepage', () => {
    this.homepage.navigate();
  });
  / 

  // 跳过此测试用例: 等价于: test.skip(), it.skip(), and xit()
  xtest('async testcase', async browser => {
    const result = await browser.getText('#navigation');
    console.log('result', result.value)
  });

  test('version dropdown is enabled', browser => {
    const navigation = this.homepage.section.navigation;
    const navbarHeader = navigation.section.navbarHeader;

    navbarHeader.expect.element('@versionDropdown').to.be.enabled;
  });

  after(browser => browser.end());
});

使用“导出”接口

基础示例
该测试打开搜索引擎Ecosia.org.搜索“nightwatch”,然后验证搜索结果第一个是否为Nightwatch.js网站

module.exports = {
  'Demo test ecosia.org' : function(browser) {
    browser
      .url('https://www.ecosia.org/')
      .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')
      .end();
  }
};

将一个测试分为多个步骤:

module.exports = {
  'step one: navigate to ecosia.org': function(browser) {
    browser
      .url('https://www.ecosia.org')
      .waitForElementVisible('body')
      .assert.titleContains('Ecosia')
      .assert.visible('input[type=search]')
      .setValue('input[type=search]', 'nightwatch')
      .assert.visible('button[type=submit]');
  },

  'step two: click submit' : function (browser) {
    browser
      .click('button[type=submit]')
      .assert.containsText('.mainline-results', 'Nightwatch.js')
      .end();
  }
};

使用ES6 async/await

从v1.1开始可使用es6 async函数,此方式可使api命令返回promise对象,便于await操作符操作结果。从1.7开始可以使用链式api命令。

module.exports = {
  'demo test async': async function (browser) {
    // get the available window handles
    const result = await browser.windowHandles();
    console.log('result', result);

    // switch to the second window
    // await is not necessary here since we're not interested in the result
    browser.switchWindow(result.value[1]);
  }
};

回调和async测试用例
若回调返回promise,则仍可使用,promise的结果会作为命令的结果返回。如下实例:

module.exports = {
  'demo test async': async function (browser) {
    // get the available window handles
    const value = await browser.windowHandles(function(result) {
      // we only want the value, not the entire result object
      return Promise.resolve(result.value);
    });

    console.log('value', value);

    // switch to the second window
    browser.switchWindow(value[1]);
  }
};

断言

断言用于判断特色是否通过,与命令不同,断言可能使用一个或多个命令。

断言失败: 当断言失败,则会抛出AssertionError,单个测试中可能有多个断言,若一个断言失败,则该测试会终止并失败。若该测试包含多个步骤或多个测试用例,则剩下的步骤/测试用例均会呗跳过。

控制失败后的行为: 若希望一个断言失败后剩下的断言继续,可使用几种方式:

  1. 使用.verify而不是.assert- 断言失败会被记录但测试仍继续执行,且最终测试仍标记为失败。
  2. 使用元素选择器对象并设置abortOnFailurefalse。如:
    browser.setValue({selector: 'input[type=search]', abortOnFailure: false}, 'nightwatch')
    在配置文件中设置"skip_testcases_on_fail"false也可使余下的测试步骤/用例继续

断言失败后终止会话 通常,断言失败后会终止会话并关闭浏览器,因此无法继续余下的测试用例。可通过设置"end_session_on_fail"false 来保持浏览器开启,通常在调试时很有用。

使用.expect()断言

expect断言使用Chai Framework中的Expect api,可用于元素、cookie、page title 和url
元素 expect 示例: expect.element([…])使用

module.exports = {
  'Demo test Ecosia.org': function (browser) {
    browser.url('https://www.ecosia.org/');

    // expect element header to be present in 1000ms
    browser.expect.element('header').to.be.present.before(1000);

    // expect element header to have css property 'display'
    browser.expect.element('header').to.have.css('display');

    // expect element header to have attribute 'class' which contains text 'index-header'
    browser.expect.element('header').to.have.attribute('class').which.contains('index-header');

    // expect element .search-form to be an input tag
    browser.expect.element('.search-form').to.be.a('form');

    // expect element header to be visible
    browser.expect.element('header').to.be.visible;

    browser.end();
  }
};

expect指定元素个数: 如下示例,期望此页面有指定的元素个数,使用expect.elements([...]).count

module.exports = {
  'demo test ecosia.org'(browser) {
    browser
      .url('https://www.ecosia.org/')
      .expect.elements('section').count.to.equal(5);
  },

  after(browser) {
    browser.end();
  }
};

编写单元测试

nightwatch从0.9版本开始改进了单元测试,并与Mocha的Exports接口兼容。

单元测试模式: Nightwatch 会自动尝试连接到 WebDriver 服务器并创建会话。运行单元测试时,需要禁用此功能,并且需要让运行者知道它正在单元测试模式下运行。可通过以下两种方式完成:

  1. 在nightwatch.conf,js中设置unit_tests_mode=true
  2. 为每个测试添加@unitTest属性:如果希望某个测试为单元测试则设置@unitTest属性为true
const assert = require('assert');

module.exports = {
  '@unitTest': true,

  'demo UnitTest' : function (done) {
    assert.equal('TEST', 'TEST');
    setTimeout(function() {
      done();
    }, 10);
  }
};

断言框架
对于单元测试,browser对象不会作为参数传递给测试用例。传递的唯一参数是done用于异步测试的回调。如下为nightwatch模块红单元测试的utils.js的子集:

var assert = require('assert');
var common = require('../../common.js');
var Utils = common.require('util/utils.js');

module.exports = {
  'test Utils' : {
    testFormatElapsedTime : function() {

      var resultMs = Utils.formatElapsedTime(999);
      assert.equal(resultMs, '999ms');

      var resultSec = Utils.formatElapsedTime(1999);
      assert.equal(resultSec, '1.999s');

      var resultMin = Utils.formatElapsedTime(122299, true);
      assert.equal(resultMin, '2m 2s / 122299ms');
    },

    testMakeFnAsync : function() {
      function asyncFn(cb) {
        cb();
      }

      function syncFn() {}

      var convertedFn = Utils.makeFnAsync(1, syncFn);
      var called = false;
      convertedFn(function() {
        called = true;
      });

      assert.equal(Utils.makeFnAsync(1, asyncFn), asyncFn);
      assert.ok(called);
    }
  }
};

异步单元测试

异步测试完成的标志为可选的done回调,若显示done,则此回调在异步操作完成后必须调用
如下为一个单元测试示例:检查当你没有在设置的时间(10ms)内调用done回调时,nightwatch是否抛出错误

module.exports = {
  const assert = require('assert');

  module.exports = {
    'demo UnitTest' : function (done) {
      assert.equal('TEST', 'TEST');

      setTimeout(function() {        done();
      }, 10);
    }
  };
};

合并单元测试和e2e测试配置

如下为合并的nightwatch.json配置文件,注意excludefilter属性的使用。exclude值为空表示重置它的值且仅依赖于filter

{
  "src_folders" : ["./examples/tests", "./examples/unittests"],
  "output_folder" : "./examples/reports",


  "webdriver" : {
    "start_process": true,
    "server_path": "node_modules/.bin/chromedriver",
    "port": 9515
  },

  "test_settings" : {
    "default" : {
      "launch_url" : "http://localhost",
      "desiredCapabilities": {
        "browserName": "chrome"
      },
      "exclude" : "./examples/unittests/"
    },

    "unittests" : {
      "unit_tests_mode" : true,
      "filter" : "./examples/unittests/",
      "exclude" : ""
    }
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值