Selenium + Nightwatch 自动化测试环境搭建
首先要安装 Java 7 或更高 ,(http://www.oracle.com/technetwork/java/javase/downloads/index.html) 并且
java
命令可正常执行才能测试噢~~ 最简单的判断方法就是打开自己的终端,输入java
并回车,看看是不是有 Java 运行。如果有命令不存在之类的提示,请重新安装 Java 运行环境 (Node.JS , 而且要确保
npm
命令可用,我想应该其实不用提醒的 ~
https://nodejs.org/en/download/
开始搭建
1. 创建项目
我们来找个地方新建一个目录,起名为 "my-test-toolkit",然后在目录内使用终端运行 npm init -y
生成项目配置文件package.json。
2. 安装工具
然后我们将安装 Selenium 与 Nightwatch。
安装 selenium-standalone:
npm install selenium-standalone --save-dev
安装 Nightwatch:
npm install nightwatch --save-dev
项目配置
我们先开始配置 Nightwatch,之前提到这是一款 Test Runner 来着,它负责读取我们的测试脚本,为我们提供 API 来操作浏览器,帮我们控制 Selenium。
一. 配置 Nightwatch
首先,在项目根目录建立文件 "nightwatch.json",这个文件用来存放 Nightwatch 的配置信息。创建完毕之后,在文件内写入以下内容:
{
"src_folders": ["tests"],
"output_folder": "reports",
"custom_commands_path": "",
"custom_assertions_path": "",
"page_objects_path": "",
"globals_path": "", "selenium": {
"start_process": true,
"server_path": "",
"log_path": "",
"host": "127.0.0.1",
"port": 4444,
"cli_args": {
"webdriver.chrome.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
}
}
}
}
nightwatch.json 的文件名是 不可以 修改的,因为 Nightwatch 每次启动的时候都是从它读取配置喔!这里的配置项很多,不过先不管它,我们接着创建文件。如果您希望查看 Nightwatch 的详细配置,请点 这里。
接着在项目根目录下创建文件 "nightwatch.conf.js" ,同样此文件名也是不可以修改的,因为 Nightwatch 每次启动也会从它这里读取配置喔~ (´・_・`)
创建完毕后,打开文件,并写入如下内容:const path = require('path') module.exports = (function (settings) {
return settings;
})(require('./nightwatch.json')) /*
* Nightwatch 会从 nightwatch.json 中读取配置。
* 不过如果存在 nightwatch.conf.js,将会变为首先从后者中读取配置。
* nightwatch.conf.js 存在的意义是使用 JavaScript 动态生成配置信息。
* 如果配置信息是不需要代码修改的,直接使用 nightwatch.json 就可以啦。
*/再次在项目根目录建立文件 "startup.js",然后在文件内部写入:
require('nightwatch/bin/runner.js')
这个文件就是我们测试的入口文件,以后我们要执行测试就要运行这个文件,命令为
node ./startup
。入口文件的名字是可以按照喜好更改的,只要运行它就好啦。不过每次输入node ./startup
太麻烦了,所以我们将这条命令写入 npm scripts 中 ~~~ 打开 "package.json",在 JSON 对象中建立 "script" 属性,并写入内容:{
...
"scripts": {
"start": "node ./startup.js"
},
...
}
以后每次运行测试只要在项目根目录中执行 npm start
就好了!(・∀・)
Nightwatch 的配置暂时告一段落(其实马上就会回来………),接下来我们来处理 Selenium.
二. 配置 Selenium
Selenium 是自动化测试环境,它提供了测试服务器、启动浏览器、网页自动操作等功能,同时暴露 API 给 Nightwatch 供我们使用。
我们接下来将要告诉 Nightwatch 我们的 Selenium 安装在哪里,启动浏览器的 Driver 程序在哪里,然后建立 Selenium 的安装脚本与手工启动脚本,以便不时之需 ~~
Driver 是让 Selenium 打开系统上已安装的浏览器的程序。
1. 建立 Selenium 的配置信息。
在项目根目录下建立文件夹 "build",并在其中创建文件 "selenium-conf.js",并写入如下信息:const process = require('process') module.exports = {
// Selenium 的版本配置信息。请在下方链接查询最新版本。升级版本只需修改版本号即可。
// https://selenium-release.storage.googleapis.com/index.html
selenium: {
version: '2.53.1',
baseURL: 'https://selenium-release.storage.googleapis.com'
}, // Driver 用来启动系统中安装的浏览器,Selenium 默认使用 Firefox,如果不需要使用其他浏览器,则不需要额外安装 Driver。
// 在此我们安装 Chrome 的 driver 以便使用 Chrome 进行测试。
driver: {
chrome: {
// Chrome 浏览器启动 Driver,请在下方链接查询最新版本。
// https://chromedriver.storage.googleapis.com/index.html
version: '2.22',
arch: process.arch,
baseURL: 'https://chromedriver.storage.googleapis.com'
}
}
}本配置信息包含 Selenium 本体配置与 Driver 配置。我们将在稍后动态载入这些配置。 本文件的目的是为了更好管理 Selenium 的版本。
2. 告诉 Nightwatch,我的 Selenium 与 Driver 在哪里。
再次打开项目根目录下的 "nightwatch.conf.js" 文件,并这样编辑:const seleniumConfig = require('./build/selenium-conf')
const path = require('path') module.exports = (function (settings) { // 告诉 Nightwatch 我的 Selenium 在哪里。
settings.selenium.server_path = `${path.resolve()}/node_modules/selenium-standalone/.selenium/selenium-server/${seleniumConfig.selenium.version}-server.jar` // 设置 Chrome Driver, 让 Selenium 有打开 Chrome 浏览器的能力。
settings.selenium.cli_args['webdriver.chrome.driver'] = `${path.resolve()}/node_modules/selenium-standalone/.selenium/chromedriver/${seleniumConfig.driver.chrome.version}-${seleniumConfig.driver.chrome.arch}-chromedriver` return settings;
})(require('./nightwatch.json'))
我们新加了两行配置,它们的作用如注释所示。
同样的,如果您希望查看更多的配置项,请点击 这里。
3. 建立 Selenium 安装脚本,一键安装 Selenium。
还记得上一章我们提过 selenium-standalone 只是用来安装和管理 Selenium 的工具么?所以现在是时候用它来安装 Selenium 了。我们将通过调取 selenium-standalone 的内置方法来实现自动安装。在 "build" 文件夹中建立文件 "selenium-setup.js",并写入如下信息:const selenium = require('selenium-standalone')
const seleniumConfig = require('./selenium-conf.js') selenium.install({
version: seleniumConfig.selenium.version,
baseURL: seleniumConfig.selenium.baseURL,
drivers: seleniumConfig.driver,
logger: function (message) { console.log(message) },
progressCb: function (totalLength, progressLength, chunkLength) {}
}, function (err) {
if (err) throw new Error(`Selenium 安装错误: ${err}`)
console.log('Selenium 安装完成.')
})同样为了方便,我们将安装命令写入 npm scripts 中:
{
...
"scripts": {
"start": "node ./startup.js",
"selenium-setup": "node ./build/selenium-setup.js"
},
...
}然后在项目根目录执行
npm run selenium-setup
安装 Selenium.当提示安装完成后,一切就绪!(・∀・)
Selenium 与其 Driver 会安装到 "node_modules/selenium-standalone/.selenium" 中。
4. 想要手工启动 Selenium?
默认情况下,Selenium 是由 Nightwatch 启动的,不需要手工干预,不过如果想要手工启动当然是可以的啦。在 build 文件夹中建立文件 "selenium-start.js",并写入如下信息:
const selenium = require('selenium-standalone')
const seleniumConfig = require('./selenium-conf.js') selenium.start({
drivers: seleniumConfig.driver
}, function (err, child) {
if (err) throw new Error(`Selenium 启动失败: ${err}`)
console.log(`Selenium 已手工启动,进程 PID: ${child.pid}`)
console.log('当不再需要运行 Selenium 时可关闭此 PID 进程.')
})然后同样添加启动命令至 npm scripts 中:
{
...
"scripts": {
"start": "node ./startup.js",
"selenium-setup": "node ./build/selenium-setup.js",
"selenium-start": "node ./build/selenium-start.js"
},
...
}以后使用命令
npm run selenium-start
就可以手工启动 Selenium 了。
搭建完了!
至此,我们的配置与安装工作已经完成,项目结构应该为:
>
| -- build
| | -- selenium-conf.js # Selenium 版本信息配置。
| | -- selenium-setup.js # Selenium 安装命令脚本。
| | -- selenium-start.js # Selenium 启动命令脚本。
|
| -- nightwatch.conf.js # Nightwatch 动态配置文件。
| -- nightwatch.json # Nightwatch 配置文件。
| -- package.json # 项目信息配置文件。
| -- startup.js # 测试启动入口文件。
“不过我好像看到 "nightwatch.json" 的配置很复杂,而我们确没怎么动它?”
嗯~~ 到目前位置确实没有太多需要改动的,不过还是要注意一个配置项:
请注意 "desiredCapabilities" 下的 "browserName" 项,这是测试时将使用的浏览器,您可以修改为
chrome
、internet explorer
、phantomjs
,本文在介绍时只安装了 Chrome 的 Driver,如果您需要使用其他浏览器,要安装相应的 Driver 才可以正常使用。默认浏览器为 Firefox,如果您使用 Firefox 的话,不需要额外进行 Driver 的配置。
所以,如果您需要使用 Chrome 的话请将 "browserName" 修改为 "chrome" 喔!
Driver 的文档可参考这里。
如果您在搭建过程中遇到困难,您可以从 Github 获取在下已经搭建好的 Start Kit.
开始编写测试用例
创建目录存放测试用例
在项目根目录新建一个名为 "tests" 的目录,然后这里就用来存放我们即将编写的测试用例文件。
那么这个文件夹能不能指向到其他地方去呢?当然可以,不过要修改一个小地方。还记得 " nightwatch.json " 文件么?打开看看,第一项是不是叫
src_folders
,然后值为["tests"]
?
我相信您已经懂了,这里就是定义测试用例存放目录的地方,然后改成自己想要的目录吧!您可以在目录中存放多个测试用例文件,且命名随意,Nightwatch 将读取目录中所有的 JS 文件,如果符合测试用例格式,将会自动执行。
编写一个简单的测试用例
在 "tests" 目录中建立一个测试用例文件 "demo.js",然后我们来写一个没什么用的小 demo!
这个 Demo 将打开 Bing,搜索 "what is microsoft",然后保存成截图后退出。
OK,打开 "demo.js",添加以下内容:
module.exports = {
'Find the answer.': function (client) {
// TODO...
}
}module.exports 导出一个对象,对象的 Key 即为测试用例名称,您可以编写多个测试用例,Nightwatch 将依次执行。
您可以在测试用例中导入其他模块并直接使用在测试逻辑中,这也是比 Phantom.JS 优秀的地方。
先写到这里,您可能会对
cilent
感到陌生,所以还是要简单介绍一下。
client
是代码运行时 Nightwatch 提供的对象,所有对浏览器进行的操作都将使用此对象调取,比如client.click("CSS Selector")
、client.getCookie(function () {...})
,我们第一章说过的 "可以简单理解为 Selenium 的控制软件" 就是通过它体现的喔!client 的所有 API 详情见 这里。
大致了解这东西的意思之后,就可以接着完善测试逻辑了:
module.exports = {
'Find the answer.': function (client) {
// 定义 Bing 页面中的节点.
const searchInput = '#sb_form_q'
const searchBtn = '#sb_form_go'
const question = 'what is microsoft' // 启动浏览器并打开 bing.com.
client.url('http://bing.com').maximizeWindow() // 确保 "body" 和输入框可以使用.
client.expect.element('body').to.be.present
client.expect.element(searchInput).to.be.visible
client.pause(2000) // 稍等两秒. // 输入 "what is microsoft" 然后搜索.
client.setValue(searchInput, question)
client.click(searchBtn)
client.pause(2000) // 截一张图然后保存到 "reports/answer.png".
client.expect.element('body').to.be.present
client.saveScreenshot('reports/answers.png')
client.end()
}
}来关注一下
expect
,是不是看起来很像自然语言?这些语句就是测试结果的验证语句,就是我们希望得到的结果。比如client.expect.element('body').to.be.present.before(3000)
,意思就是 "希望 body 元素能在 3000 毫秒内初始化完毕"。Nightwatch 支持 BDD-Style 与 Assert 断言两种风格,文档可见 这里。
关于 Assert、BDD、TDD 的更多内容请参照其他文章。
是不是确实没什么用?毕竟是个简单的 Demo 而已,哈哈。那么添加一个稍微复杂点的测试用例。
编写另一个简单的测试用例
这个 demo 将打开 Bilibili 直播 ,然后执行:
打开首页并等待加载完毕;
检查登陆按钮是否存在;
点击登陆按钮;
填写用户名与密码;
点击登陆;
等待页面加载;
通过 Cookie 检查是否已登陆;
确保登陆后的用户导航面板存在;
鼠标移至头像处打开导航面板;
点击退出登陆;
等待页面刷新后检查 Cookie 是否已退出登陆;
结束测试。
其实就是第一章的那个 Demo 图干的事情了 (・∀・)这个 demo 不再啰嗦,直接放出代码:
// Account setting.
const accountConfig = {
username: 'USERNAME',
password: 'PASSWORD',
uid: '10000'
} module.exports = {
'Bilibili Live Login Test': function (client) {
client.url('http://live.bilibili.com').maximizeWindow() // Page Init.
client.expect.element('body').to.be.present.before(3000)
client.expect.element('.top-nav-login-btn.last').to.be.visible // Login.
client.click('.top-nav-login-btn.last')
client.waitForElementVisible('#bilibili-quick-login', 2000)
client.frame(0)
client.pause(2000)
client.setValue('#login-username', accountConfig.username)
client.setValue('#login-passwd', accountConfig.password)
client.click('#login-submit') // Wait and check page has been reloaded.
client.frameParent()
client.pause(4000)
client.expect.element('body').to.be.present.before(3000) // Check cookies to ensure we are signed in.
client.getCookies(function (result) {
result.value.forEach((value, index, array) => {
if (value.name === 'DedeUserID') client.assert.equal(parseInt(value.value, 10), accountConfig.uid)
})
}) // Move to User Avatar.
client.expect.element('.user-avatar-link').to.be.visible
client.moveToElement('.user-avatar-link', 5, 5)
client.pause(800)
client.expect.element('#top-nav-user-panel').to.be.visible // Logout.
client.click('#top-nav-logout-link')
client.pause(5000)
client.expect.element('body').to.be.present.before(3000) // Check cookies again to ensure we are off.
client.getCookies(function (result) {
var logout = true
result.value.forEach((value, index, array) => {
if (value.name === 'LIVE_LOGIN_DATA') logout = false
})
client.assert.equal(logout, true)
}) client.pause(1000)
client.end()
}
}您可以新建一个文件,或者在之前的文件中继续编写。
运行测试用例
回到项目根目录,执行
npm start
,然后就可以看到浏览器自己测试了!
运行效果如下:测试运行完毕之后,测试结果将打印在终端里,同时会生成到 reports 文件夹中。
您可以在 nightwatch.json 中修改 "output_folder" 来更换报告生成目录。
需要注意的地方
您可能在使用中会遇到例如 “明明看到节点缺获取不到”、“鼠标功能好像时好时坏” 等问题,在此给您一些建议:
由于现在很多网站使用诸如 Angular、Vue 等框架构建,其节点可能为组件动态渲染,所以 Selenium 在执行测试时可能获取的 Dom 树为旧数据从而导致找不到节点,因此您可以执行等待语句确保节点出现后再进行测试。不过可能不是 100% 成功,这也是这套测试系统的短板之一。
如果您在进行模拟鼠标的测试,您的鼠标指针可能会干扰您的测试,因此建议运行测试后将您的指针移动至屏幕外部,以避免干扰到浏览器测试。
测试很可能因为页面加载时间问题导致测试失败,不过这也是 E2E 测试的特征所在,您可以修改您的测试逻辑,或致力缩短加载时间。
大功告成!
现在您已经拥有您自己的测试工具并且成功编写了两个测试用例!此处您应该为自己鼓掌!
您现在已经可以将 E2E 测试纳入您的开发流程之中,在下相信这将对您的开发有不小的帮助。如果您有兴趣,您也可以考虑 单元测试的可能性。如果您没能成功构建您的项目,您可以从这里获取代码。
同时像之前提到的,如果您在使用 Vue 构建您的项目,您可以使用 Vue-cli 来生成已经包含 Selenium 与 Nightwatch 的 Vue 种子项目,您可以在
test/e2e
中编写您的测试用例。
Selenium + Nightwatch 自动化测试环境搭建的更多相关文章
- selenium + python 自动化测试环境搭建
selenium + python 自动化测试 —— 环境搭建 关于 selenium Selenium 是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操 ...
- Selenium终极自动化测试环境搭建(二)Selenium+Eclipse+Python
Selenium终极自动化测试环境搭建(二)Selenium+Eclipse+Python 前面举例了Selenium+Eclipse+Junit+TestNG自动化测试环境的搭建,在前一篇的基础上, ...
- Selenium终极自动化测试环境搭建(一) Selenium+Eclipse+Junit+TestNG
Selenium终极自动化测试环境搭建(一)Selenium+Eclipse+Junit+TestNG 第一步 安装JDK JDk1.7. 下载地址:http://www.oracle.com/tec ...
- Selenium终极自动化测试环境搭建(二):Selenium+Eclipse+Python
前面举例了Selenium+Eclipse+Junit+TestNG自动化测试环境的搭建,在前一篇的基础上,下面再举例Selenium+Eclipse+Python测试环境搭建. 第一步:安装Pyth ...
- Selenium+Python自动化测试环境搭建和搭建过程遇到的问题解决
环境搭建: 第一步:安装Python 网址:https://www.python.org/ 按照如图提示安装,并且配置环境变量(安装时候选中pip会自动安装Python的包管理工具 pip,推荐选择 ...
- Python+Selenium UI自动化测试环境搭建及使用
一什么是Selenium ? Selenium 是一个浏览器自动化测试框架,它主要用于web应用程序的自动化测试,其主要特点如下:开源.免费:多平台.浏览器.多语言支持:对web页面有良好的支持:AP ...
- selenium + python自动化测试环境搭建
selenium的在python平台的搭建: 搭建平台windows 准备工具如下: --------------------------------------------------------- ...
- 【转】Windows下selenium+python自动化测试环境搭建
原文链接:http://www.cnblogs.com/test-of-philosophy/articles/4322918.html 搭建平台:windows 1.安装python,下载地址:ht ...
- 【python】selenium+python自动化测试环境搭建
参考资料: http://www.cnblogs.com/fnng/archive/2013/05/29/3106515.html http://www.easonhan.info/python/20 ...
随机推荐
- [转]zsh快捷键记录
转自: http://wdxtub.com/2016/02/18/oh-my-zsh/ 使用技巧 连按两次Tab会列出所有的补全列表并直接开始选择,补全项可以使用 ctrl+n/p/f/b上下左右切换 ...
- WebApplicationContextUtils源码
package org.springframework.web.context.support; import javax.servlet.ServletContext; import javax.s ...
- poj1006 中国剩余定理&&中国剩余定理解析
poj 1006 题的思路不是很难的,可以转化数学式: 现设 num 是下一个相同日子距离开始的天数 p,e,i,d 如题中所设! 那么就可以得到三个式子:( num + d ) % 23 == p: ...
- iOS开发,最新判断是否是手机号的正则表达式
最近项目里需要判断是否为手机号并发送验证码的功能,一下是实现方法.不过这个方法还是有些不足,只能判断输入的11位数的号段是否正确,无法判断手机号是否存在.不过勉强可以使用! + (NSString * ...
- HDU——1233还是畅通工程(克鲁斯卡尔+优先队列)
还是畅通工程 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- 刷题总结——Tree2cycle(hdu4714 树形dp)
题目: A tree with N nodes and N-1 edges is given. To connect or disconnect one edge, we need 1 unit of ...
- Golang指针
学过C语言的老司机都知道,指针就是一个变量,用于存储另一个变量的内存地址. 那么什么是变量呢?在现代计算机体系结构中所有的需要执行的信息代码都需要存储在内存中,为了管理存储在内存的数据,内存是划分为不 ...
- python中的daemon守护进程实现方法
原文参考:http://blog.csdn.net/tao_627/article/details/49532021 守护进程是生存期长的一种进程.它们独立于控制终端并且周期性的执行某种任务或等待处理 ...
- 不同狀況下的 bq25896 register
no charger時的 bq25896 register [bq25890 reg@] [0x0]=0x7f [0x1]=0x6 [0x2]=0x91 [0x3]=0x1a [0x4]=0x8 [0 ...
- Python入门--18--异常与try,except语句
Python标准异常总结 AssertionError 断言语句(assert)失败 AttributeError 尝试访问未知的对象属性 EOFError 用户输入文件末尾标志EOF(Ctrl+d) ...