Nightwatch.js是一个测试web app和web 站点的自动化测试框架, 使用Node.js编写, 基于Selenium WebDriver API.
它是一个完整的浏览器端真实用户场景测试解决方案, 致力于简化继续集成和编写自动化测试。
Nightwatch got its name from the famous painting The Night Watch by Dutch painter Rembrandt van Rijn. The masterpiece is prominently displayed in the Rijksmuseum, in Amsterdam - The Netherlands.
Selenium 是一个直接运行在浏览器中的非常流行的综合测试工具集, 最初为java 语言编写, 现在已经支持许多语言。
Selenium的主要项目:
* Selenium IDE
* Selenium Remote Control
* Selenium WebDriver
* Selenium Grid
Nightwatch uses the Selenium WebDriver, specifically the WebDriver Wire Protocol to perform the browser automation related tasks.
Nightwatch 使用Selenium WebDriver, 特别是WebDriver Wire Protocol 来执行浏览器自动化测试相关任务。
Nightwatch works by sending HTTP requests to the Selenium server with the right parameters and interpreting the response. The restful API protocol is defined by the Selenium JsonWireProtocol. See below for an example workflow for browser initialization.
Nightwatch 发送通过 HTTP 请求发送响应的参数到 Selenium 服务器,并解析服务器响应。restful API 文档见Selenium JsonWireProtocol 。浏览器初始化流程见下图。
大部分情况下, Nightwatch 执行一条命令或断言,至少要发送2个请求到 Selenium 服务器。 第一个用来定位元素,可以用 CSS 选择器或者Xpath 表达式。 第二个用来在选中的元素上执行命令或断言操作。
From nodejs.org:
“Node.js is a platform built on Chrome’s JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.”
主流操作系统的安装包都可以在nodejs.org上找到。
使用 npm 安装最新的 Nightwatch, 在命令行运行:
npm install -g nightwatch
Selenium WebDriver server 是一个简单的 Java servlet 程序,分别运行在本地机器上和你要进行测试的浏览器上。(todo 真的是浏览器上?)
Download Selenium
Download the latest version of the selenium-server-standalone-{VERSION}.jar file from the Selenium downloads page and place it on the computer with the browser you want to test. In most cases this will be on your local machine and typically inside your project’s source folder.
到Selenium downloads page下载最新版的selenium-server-standalone-{VERSION}.jar 包, (todo)具体放在哪里, 等我试一试再说。
也可以通过 npm 安装 selenium server:
npm install selenium-server
A good practice is to create a separate subfolder (e.g. bin) and place it there as you might have to download other driver binaries if you want to test multiple browsers.
Running Selenium Automatically
如果服务器和Nightwatch 运行在同一台机器上, Nightwatch Test Runner可以启动和停止Selenium 服务器。
Running Selenium Manually
To run the selenium server manually, from the directory with the jar run the following:
要手动启动 server 服务器, 在 jar 包所在目录执行:
java -jar selenium-server-standalone-{VERSION}.jar
更多关于运行 Selenium 服务器的信息参考:
http://code.google.com/p/selenium/wiki/RemoteWebDriverServer
要获取帮助信息, 执行:
java -jar selenium-server-standalone-{VERSION}.jar -help
测试需要一个配置文件, 默认会使用当前目录下的 nightwatch.json 文件。nightwatch.json 详细配置如下:
{
"src_folders" : ["tests"],
"output_folder" : "reports",
"custom_commands_path" : "",
"custom_assertions_path" : "",
"page_objects_path" : "",
"globals_path" : "",
"selenium" : { "start_process" : false, "server_path" : "", "log_path" : "", "host" : "127.0.0.1", "port" : 4444, "cli_args" : { "webdriver.chrome.driver" : "", "webdriver.ie.driver" : "" } },
"test_settings" : { "default" : { "launch_url" : "http://localhost", "selenium_port" : 4444, "selenium_host" : "localhost", "silent": true, "screenshots" : { "enabled" : false, "path" : "" }, "desiredCapabilities": { "browserName": "firefox", "javascriptEnabled": true, "acceptSslCerts": true } }, "chrome" : { "desiredCapabilities": { "browserName": "chrome", "javascriptEnabled": true, "acceptSslCerts": true } } } }
Name | type | default | description |
---|---|---|---|
src_folders | string|array | none | 测试代码目录(不包含子目录) |
output_folder (optional) | string | tests_output | 生成的测试报告存放目录 |
custom_commands_path (optional) | string|array | none | Location(s) where custom commands will be loaded from. |
custom_assertions_path (optional) | string|array | none | 自定义断言路径 |
page_objects_path (Optional since v6.0.1) | string|array | none | Location(s) where page object files will be loaded from. |
globals_path (optional) | string | none | 外部模块路径,为测试一共全局变量. 也可在test_settings中重写 |
selenium (optional) | object | Selenium Server相关的设置 | |
test_settings (optional) | object | 与测试相关的测试,下面有详细描述 | |
live_output (optional) | boolean | false | 是否缓存并持续输出结果 |
disable_colors (optional) | boolean | false | 控制命令行输出是否带有高亮颜色 |
parallel_process_delay (optional) | integer | 10 | 在并行模式下启动子进程的时间,单位毫秒 |
test_workers | boolean|object | false | 是否为运行单个文件测试启动并行模式,如果设置为true,会进入并行模式,并自动设置线程数。如果设置为对象,要指定enable和workers参数,workers接受数值和’auto’。 例如:”test_workers” : {“enabled” : true, “workers” : “auto”} |
test_runner (optional) | string|object | “default” | 用什么工具运行测试。值可以是”default”或”mocha”. 例如:”test_runner” : {“type” : “mocha”, “options” : {“ui” : “tdd”}} |
如下是 selenium 的配置选项。Nightwatch可以自动管理 selenium 服务进程,以便你专注于测试工作。
如果要启用 selenium自启动,设置 start_process 为true 并设置 server_path 值为 selenium jar包路径。
Name | type | default | description |
---|---|---|---|
start_process | boolean | false | 是否启用 selenium自启动 |
start_session | boolean | true | 是否自动启动 Selenium session. |
server_path | string | none | selenium jar 包路径。如果设置了 start_process 字段,必须设置此字段。例如: node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.0.jar |
log_path | string|boolean | none | selenium 生成的 output.log 文件存放位置,默认为当前目录下。设置false可以禁用 Selenium 日志。 |
host | string | 127.0.0.1 | 设置 selenium 监听地址。不常用到,除非指定了 start_process 为true。 |
port | integer | 4444 | 设置 selenium 监听端口 |
cli_args | object | none | 一系列传递给 selenium 的命令行参数。 有许多选项可以设置, 例如: |
webdriver.firefox.profile: 默认情况下会为每个会话创建一个firefox配置文件,如果想要使用现有配置文件,在这里指定文件名。firefox驱动参数的完整列表见这里 。 | |||
webdriver.chrome.driver: Nightwatch 也可以在 Chrome 上运行测试,如果要在 chrome 上运行测试需要下载 ChromeDriver binary 并为此字段设置 ChromeDriver 路径。同时要在 desiredCapabilities 对象配置中指定 browserName值为 “chrome”。 更多信息参考ChromeDriver website。 | |||
webdriver.ie.driver: Nightwatch同时也支持Internet Explorer,要在IE中运行测试,需要下载 IE Driver binary 并为此字段设置 IE Driver 路径。同时要在 desiredCapabilities 对象配置中指定 browserName值为 “internet explorer”。 |
下面是一些Nightwatch 实例的配置信息。可以配置多个不同的配置对象,模拟多种测试环境。:
{
...
"test_settings" : {
"default" : {
...
},
"integration" : {
...
}
}
}
只有”default”配置是必须的,其他配置可以按需要覆盖default中的配置信息。
测试环境可以通过 -env 参数传递给 nightwatch:
nightwatch --env integration
Name | type | default | description |
---|---|---|---|
launch_url | string | none | 测试时要加载的首页url, 如果有多个测试环境,可以分别指定url。 |
selenium_host | string | localhost | 指定 selenium server 接受的 hostname/IP。 |
selenium_port | string | 4444 | 指定 selenium server 接受的端口。 |
silent | boolean | true | 是否显示 selenium 命令日志。 |
output | boolean | rue | 是否在命令行显示完整输出。 |
disable_colors | boolean | false | 命令行输出是否高亮。 |
firefox_profile | string|boolean | none | 已经弃用 |
chrome_driver | string | none | 已经弃用 |
ie_driver | string | none | 已经弃用 |
screenshots | object | none | 当发生错误时 Selenium 会生成屏幕截图。如果 on_failure 设置为 true, 发生错误或没有通过测试时也生成屏幕截图。 |
从 v0.7.5 版本开始,可以为”on_error”字段设置false来禁止错误时生成截图。 | |||
例如:“screenshots”:{“enabled”:true,”on_failure”:true,”on_error”: false,”path”: “”} | |||
username | string | none | 万一 selenium 需要凭证,该字段用来生成 Authorization header。值可以是系统变量,例如:”username” : “${SAUCE_USERNAME}” |
access_key | string | none | 与 username 一样用于生成 Authorization header。像 username 一样,值也可以是系统变量。 |
proxy | string | none | 使用代理访问 selenium server。支持 http, https, socks(v5), socks5, sock4, 和 pac。使用node-proxy-agent。Example: http://user:pass@host:port |
desiredCapabilities | object | 在新建 session 之前传递给 Selenium WebDriver,可以用来指定浏览器名称和其他功能。例如:“desiredCapabilities” : {“browserName” : “firefox”, “acceptSslCerts” :true}。 完整的功能列表在这里。 | |
globals | object | 在测试代码中可以访问的全局变量,并且每次切换测试环境时可以重写该值。例如: *”globals” :{“myGlobal” : “some_global”} | |
exclude | array | 不包含的文件夹,接受字符串或模式字符串(relative to the main source folder)。例如:”exclude” : [“excluded-folder”] 或 :”exclude” : [“test-folder/*-smoke.js”] | |
filter | string | 接受字符串或模式字符串,与之不匹配的文件会被忽略。 | |
log_screenshot_data | boolean | false | 是否在日志(verbose模式)中记录屏幕截图的base64编码信息。 |
use_xpath | boolean | false | 是否用 xpath 做为默认的元素选择策略。 |
cli_args | object | none | 作用与 selenium 配置中的 cli_args 相同。 你可以在不同的测试环境配置中覆盖 selenium 中的配置。 |
end_session_on_fail | boolean | true | 在测试终止的时候,自动关闭会话,通常会在断言失败后触发。 |
skip_testcases_on_fail | boolean | true | 是否在任意测试用例测试失败后,跳过剩余的测试用例。 |
output_folder | string|boolean | 生成的测试报告存放目录, 该值覆盖 Basic settings 中的配置, 也可以设置为 false 不生成报告。 | |
persist_globals | boolean | false | Weather or not to persist use the same object instance for holding globals between testsuite runs or a (deep) copy of it. |
通过css选择器在页面中定位元素,Nightwatch 使得编写 End-to-End 自动测试非常简单。
在你的项目中新建一个文件夹,比如tests,其中的文件会被 NightwatchCreate 加载并运行测试,一个最基本的测试如下所示:
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();
};
Nightwatch 也支持 xpath。 调用 useXpath() 使用 xpath 规则选取元素。要退回 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')
};
从 Nightwatch0.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 接口为断言提供了灵活流畅的短语,比之前的接口有显著的改善。 唯一的缺点是没法链式调用断言,并且自定义消息当前也不支持。
except 完整的 api 点这里。
Nightwatch 为测试提供了 befoare/after, beforeEach/afterEach 钩子。
before 和 after 钩子会在每个测试套件运行前后执行。beforeEach 和 afterEach 则会在每个测试用例(测试步骤)执行前后执行。
所有钩子函数都接收一个 NightWatch 实例做为参数。
Example:
module.exports = {
before : function(browser) {
console.log('Setting up...');
},
after : function(browser) {
console.log('Closing down...');
},
beforeEach : function(browser) {
},
afterEach : function(browser) {
},
"step one" : function (browser) {
browser
// ...
},
"step two" : function (browser) {
browser
// ...
.end();
}
};
上例中方法的调用顺序如下:
before(), beforeEach(), “step one”, afterEach(), beforeEach(), “step two”, afterEach(), after()