NightWatchJS

关于Nightwatch?

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.

Overview of Selenium

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 来执行浏览器自动化测试相关任务。

Theory of Operation

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 表达式。 第二个用来在选中的元素上执行命令或断言操作。

Installation

安装Node.js

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上找到。

Install Nightwatch

使用 npm 安装最新的 Nightwatch, 在命令行运行:

npm install -g nightwatch

运行 Selenium 服务器

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

Configuration

测试需要一个配置文件, 默认会使用当前目录下的 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
      }
    }
  }
}

Basic settings

Nametypedefaultdescription
src_foldersstring|arraynone测试代码目录(不包含子目录)
output_folder (optional)stringtests_output生成的测试报告存放目录
custom_commands_path (optional)string|arraynoneLocation(s) where custom commands will be loaded from.
custom_assertions_path (optional)string|arraynone自定义断言路径
page_objects_path (Optional since v6.0.1)string|arraynoneLocation(s) where page object files will be loaded from.
globals_path (optional)stringnone外部模块路径,为测试一共全局变量. 也可在test_settings中重写
selenium (optional)objectSelenium Server相关的设置
test_settings (optional)object与测试相关的测试,下面有详细描述
live_output (optional)booleanfalse是否缓存并持续输出结果
disable_colors (optional)booleanfalse控制命令行输出是否带有高亮颜色
parallel_process_delay (optional)integer10在并行模式下启动子进程的时间,单位毫秒
test_workersboolean|objectfalse是否为运行单个文件测试启动并行模式,如果设置为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 settings

如下是 selenium 的配置选项。Nightwatch可以自动管理 selenium 服务进程,以便你专注于测试工作。
如果要启用 selenium自启动,设置 start_process 为true 并设置 server_path 值为 selenium jar包路径。

Nametypedefaultdescription
start_processbooleanfalse是否启用 selenium自启动
start_sessionbooleantrue是否自动启动 Selenium session.
server_pathstringnoneselenium jar 包路径。如果设置了 start_process 字段,必须设置此字段。例如: node_modules/selenium-server/lib/runner/selenium-server-standalone-2.53.0.jar
log_pathstring|booleannoneselenium 生成的 output.log 文件存放位置,默认为当前目录下。设置false可以禁用 Selenium 日志。
hoststring127.0.0.1设置 selenium 监听地址。不常用到,除非指定了 start_process 为true。
portinteger4444设置 selenium 监听端口
cli_argsobjectnone一系列传递给 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”。

Test settings

下面是一些Nightwatch 实例的配置信息。可以配置多个不同的配置对象,模拟多种测试环境。:

{
  ...
  "test_settings" : {
    "default" : {
      ...
    },
    "integration" : {
      ...
    }
  }
}

只有”default”配置是必须的,其他配置可以按需要覆盖default中的配置信息。
测试环境可以通过 -env 参数传递给 nightwatch:

nightwatch --env integration
Nametypedefaultdescription
launch_urlstringnone测试时要加载的首页url, 如果有多个测试环境,可以分别指定url。
selenium_hoststringlocalhost指定 selenium server 接受的 hostname/IP。
selenium_portstring4444指定 selenium server 接受的端口。
silentbooleantrue是否显示 selenium 命令日志。
outputbooleanrue是否在命令行显示完整输出。
disable_colorsbooleanfalse命令行输出是否高亮。
firefox_profilestring|booleannone已经弃用
chrome_driverstringnone已经弃用
ie_driverstringnone已经弃用
screenshotsobjectnone当发生错误时 Selenium 会生成屏幕截图。如果 on_failure 设置为 true, 发生错误或没有通过测试时也生成屏幕截图。
从 v0.7.5 版本开始,可以为”on_error”字段设置false来禁止错误时生成截图。
例如:“screenshots”:{“enabled”:true,”on_failure”:true,”on_error”: false,”path”: “”}
usernamestringnone万一 selenium 需要凭证,该字段用来生成 Authorization header。值可以是系统变量,例如:”username” : “${SAUCE_USERNAME}”
access_keystringnone与 username 一样用于生成 Authorization header。像 username 一样,值也可以是系统变量。
proxystringnone使用代理访问 selenium server。支持 http, https, socks(v5), socks5, sock4, 和 pac。使用node-proxy-agent。Example: http://user:pass@host:port
desiredCapabilitiesobject在新建 session 之前传递给 Selenium WebDriver,可以用来指定浏览器名称和其他功能。例如:“desiredCapabilities” : {“browserName” : “firefox”, “acceptSslCerts” :true}。 完整的功能列表在这里
globalsobject在测试代码中可以访问的全局变量,并且每次切换测试环境时可以重写该值。例如: *”globals” :{“myGlobal” : “some_global”}
excludearray不包含的文件夹,接受字符串或模式字符串(relative to the main source folder)。例如:”exclude” : [“excluded-folder”] 或 :”exclude” : [“test-folder/*-smoke.js”]
filterstring接受字符串或模式字符串,与之不匹配的文件会被忽略。
log_screenshot_databooleanfalse是否在日志(verbose模式)中记录屏幕截图的base64编码信息。
use_xpathbooleanfalse是否用 xpath 做为默认的元素选择策略。
cli_argsobjectnone作用与 selenium 配置中的 cli_args 相同。 你可以在不同的测试环境配置中覆盖 selenium 中的配置。
end_session_on_failbooleantrue在测试终止的时候,自动关闭会话,通常会在断言失败后触发。
skip_testcases_on_failbooleantrue是否在任意测试用例测试失败后,跳过剩余的测试用例。
output_folderstring|boolean生成的测试报告存放目录, 该值覆盖 Basic settings 中的配置, 也可以设置为 false 不生成报告。
persist_globalsbooleanfalseWeather or not to persist use the same object instance for holding globals between testsuite runs or a (deep) copy of it.

Using Nightwatch

Writing Tests

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

Using XPath selectors

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

BDD Expect Assertions

从 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 点这里

Using before[Each] and after[Each] hooks

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

Asynchronous before[Each] and after[Each]

所有的 before[Each] 和 after[Each] 钩子函数对异步操作同样适用,用于异步操作时会给函数传递第二个参数 callback .

done 方法必须在异步操作完成时之行,否则会抛出一个 timeOut 错误.

Example:

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 秒(2秒用来之行单元测试)。在某些情况下,10 秒钟不够而且会出现 timeOut 错误。 你可以在全局变量配置文件中自己设置 asyncHookTimeout 属性来指定该值,单位为毫秒。 例子

强制测试失败

要强制使测试失败, 需要在调用 done 方法时,传入一个 Error 对象。

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

用外部文件定义全局变量

大多数时候,使用外部文件定义全局变量是比较好的实践。为 globals_path 属性指定外部文件路径, 而不是在 nightwatch.json 配置中定义全局变量。

还可以在应用每个 environment 之前重写外部文件中的变量值。

全局钩子

之前提到的钩子函数在全局范围也同样适用,outside the scope of the test。下面的例子给出了详细信息。 在这种情况下,beforeEach 和 afterEach 作用于一个测试集(i.e. test file)。

全局设置

globals文件有许多属性用于控制测试流程。下面的例子给出了详细信息:

module.exports = {
  // this controls whether to abort the test execution when an assertion failed and skip the rest
  // it's being used in waitFor commands and expect assertions
  abortOnAssertionFailure : true,

  // this will overwrite the default polling interval (currently 500ms) for waitFor commands
  // and expect assertions that use retry
  waitForConditionPollInterval : 300,

  // default timeout value in milliseconds for waitFor commands and implicit waitFor value for
  // expect assertions
  waitForConditionTimeout : 5000,

  // this will cause waitFor commands on elements to throw an error if multiple
  // elements are found using the given locate strategy and selector
  throwOnMultipleElementsReturned : true,

  // controls the timeout time for async hooks. Expects the done() callback to be invoked within this time
  // or an error is thrown
  asyncHookTimeout : 10000,

  'default' : {
    myGlobal : function() {
      return 'I\'m a method';
    }
  },

  'test_env' : {
    myGlobal: 'test_global',
    beforeEach : function() {

    }
  },

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

运行测试

Test Runner

Nightwatch 包含了一个命令行工具,可以非常简单的运行测试并输出有用的信息。根据你安装的方式,有多种不同的命令形式。

Global

如果你是全局安装 Nightwatch (使用 -g 选项),nightwatch 在所有目录下都是可用的。

$ nightwatch [source] [options]

Project specific

如果 Nightwatch 是以工程的依赖形式安装, 要在 node_modules/.bin/ 目录下才能使用 nightwatch 命令。

Linux and MacOSX:

$ ./node_modules/.bin/nightwatch [source] [options]

Windows:
创建一个 nightwatch.js 文件并输入下面这行代码:

require('nightwatch/bin/runner.js');

然后执行:

C:\workspace\project> node nightwatch.js [source] [options]

Tests source
可选的 source 选项可以指定一个或多个文件,也可以直接指定一个文件夹,该选项独立于 src_folders 设置。

Example - single test:

$ nightwatch tests/one/firstTest.js

Example - 2 individual tests:

$ nightwatch tests/one/firstTest.js tests/secondTest.js

Example - 1 individual test and 1 folder:

$ nightwatch tests/one/test.js tests/utils

命令行选项

NameShortnamedefaultdescription
–config-c./nightwatch.jsonnightwatch.json 文件路径
–output-otests_outputJUnit 生成的报告保存路径.
–reporter-rjunit指定预定义的生成报告的工具,或是自定义用于生成报告的文件路径
–env-edefault指定测试环境,可以覆盖 nightwatch.json 中的值
–verbose是否在命令行输出详细信息
–version-v是否显示版本号
–test-t运行指定的测试文件,默认会运行跟目录下所有测试文件
–testcase与test选项一同使用,指定要运行的测试用例
–group-g运行指定组中(子目录)中的所有测试,测试文件按目录分组
–skipgroup-s跳过指定的一个或多个(以逗号分隔)测试组
–filter-f指定一个模式字符串用于过滤测试文件
–tag-a使用tag过滤测试模块,只有带有相应标签的测试模块才被执行
–skiptags指定跳过带有相应标签的模块,多个以逗号隔开
–retriesRetries failed or errored testcases up to the specified number of times. Retrying a testcase will also retry the beforeEach and afterEach hooks, if any.
–suiteRetriesRetries failed or errored testsuites (test modules) up to the specified number of times. Retrying a testsuite will also retry the before and after hooks (in addition to the global beforeEach and afterEach respectively), if any are defined on the testsuite.

测试集

Nightwatch 允许你以集合的形式组织测试脚本, 并按需运行这些测试集。要把测试文件放在同一文件夹下就可以将它们组合起来,文件夹的名称就是测试集的名称。

Example:

lib/
  ├── selenium-server-standalone.jar
custom-commands/
  ├── loginUser.js
  ├── attachPicture.js
tests/
  ├── logingroup
  |   ├── login_test.js
  |   └── otherlogin_test.js
  ├── addressbook
  |   ├── addressbook_test.js
  |   └── contact_test.js
  ├── chat
  |   ├── chatwindow_test.js
  |   ├── chatmessage_test.js
  |   └── otherchat_test.js
  └── smoketests
      ├── smoke_test.js
      └── othersmoke_test.js

如果只想测试 smoketests , 运行如下命令:

$ nightwatch --group smoketests

如果要跳过 smoketests, 运行如下命令:

$ nightwatch --skipgroup smoketests

要跳过多个测试集, 以逗号分隔:

$ nightwatch --skipgroup addressbook,chat

标签

你也可以选择用标签来管理要运行哪些测试, 那样的话,一个测试可能属于多个标签。例如:有一个 login 测试即属于 login 标签,又属于 sanity 标签。

module.exports = {
  '@tags': ['login', 'sanity'],
  'demo login test': function (client) {
     // test code
  }
};

使用 –flag 命令行选项决定运行那个标签下的测试:

$ nightwatch --tag login

指定多个标签:

$ nightwatch --tag login --tag something_else

要跳过指定标签, 使用 –skiptags 选项:

$ nightwatch --skiptags login

要跳过多个标签, 用逗号隔开:

$ nightwatch --skiptags login,something_else

禁用测试

要阻止某个模块执行测试, 只需要设置 disable 属性为true :

module.exports = {
  '@disabled': true, // This will prevent the test module from running.

  'sample test': function (client) {
    // test code
  }
};

在明确某些模块会测试失败时,这很有用。

禁用单独测试用例
禁用模块中单独的测试用例,目前还不支持。 但是有一个变通方法, 将测试方法转化为字符串,Nightwatch 就会忽略它。

module.exports = {
  'sample test': function (client) {
    // test code
  },

  // disabled
  'other sample test': ''+function (client) {
    // test code
  }
};

并行运行

从 v0.5 开始, Nightwatch 支持同时在多个环境中执行测试, 给 -e 参数指定多个值即可:

$ nightwatch -e default,chrome

终端输出

每个测试环境以一个子进程运行, 而输出信息会汇集到主进程。
为了使输出信息更易阅读, Nightwatch 默认会缓存所有输出,在最后再以每个环境为一组,一起输出这些信息。

如果你想要禁止缓存输出,在子进程的输出发送到 stdout 后立即可见。需要在 nightwatch.json 文件最外层(e.g selenium属性之后) 中设置 live_output 属性为true。

You can create a separate environment per browser (by chaining desiredCapabilities) and then run them in parallel. In addition, using the filter and exclude options tests can be split per environment in order to be ran in parallel.

Via Workers

从 v0.7 开始引入了一个新特性,

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值