写测试
使用首选的CSS选择器模型在页面上定位元素,Nightwatch使编写自动端到端测试变得非常容易。
为项目中的测试创建一个单独的文件夹,例如:tests。其中的每个文件都将由Nightwatch测试运行器作为测试加载。基本测试将如下所示:
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();
}
};
注:代码中“name=btnG”的描述应该是旧的描述,新的应该是“name=btnK”,另外由于使用环境的环境不同,使用css选择器的属性也有所不同,请以实际情况为准
当您想要关闭测试时,请记住始终调用.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选择器。要切换到xpath而不是css选择器作为定位策略,在测试中调用方法useXpath()
,如下例所示。要切换回CSS,请调用useCss()
。
要始终使用xpath,请在测试设置中将属性“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风格的断言库,它极大地提高了断言的灵活性和可读性。
expect断言使用来自Chai框架的Expect api的子集,此时仅可用于元素。这是一个例子:
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接口为定义断言提供了更加灵活和流畅的语言,与现有的断言接口相比有了显着的改进。唯一的缺点是不再可能链接断言,此时尚不支持自定义消息。
有关可用期望断言的完整列表,请参阅API文档。
在[Every]之前和[Each]之后使用
Nightwatch提供在测试中使用的标准之前/之后以及之前/之后的每个挂钩。 之前和之后将分别在执行测试套件之前和之后运行,而beforeEach和afterEach分别在每个测试用例之前和之后运行(测试步骤)。
所有方法都将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
挂钩只能以其异步形式接收浏览器对象 - afterEach(browser,done){..}
所有的before[Each]和after[Each]方法也可以执行异步操作,在这种情况下,它们需要将回调作为第二个参数传递。
必须在异步操作完成时调用done函数作为最后一步。不调用它将导致超时错误。
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);
}
};
控制完成的调用超时
默认情况下,完成调用超时设置为10秒(单元测试为2秒)。在某些情况下,这可能不足以避免超时错误,您可以通过在外部全局文件中定义asyncHookTimeout
属性(以毫秒为单位)来增加此超时(有关外部全局变量的详细信息,请参阅下文)。
有关示例,请参阅提供的globalsModule示例。
显然未通过测试
通过简单地使用Error
参数调用done
,可以在测试挂钩中故意进行测试失败:
module.exports = {
afterEach: function(browser, done) {
// performing an async operation
performAsync(function(err) {
if (err) {
done(err);
}
// ...
});
}
};
External Globals
大多数情况下,在globals_path
属性中指定的外部文件中定义全局变量更有用,而不是在nightwatch.json
中定义它们。
您可以根据需要覆盖每个环境的全局变量。假设您在本地运行测试,并且还在远程登台服务器上运行。大多数情况下,您需要一些不同的设置。
Global Hooks
在测试范围之外,全局也可以使用与测试套件相同的一组钩子。有关详细信息,请参阅以下示例。在全局钩子的情况下,beforeEach和afterEach引用测试套件(即测试文件),并在测试套件之前和之后运行。
Global Settings
有许多全局变量保持测试设置并可以控制测试执行。这些在提供的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();
}
};