【重点】Selenium + Nightwatch 自动化测试环境搭建

开始搭建

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

1.首先,在项目根目录建立文件 "nightwatch.json",这个文件用来存放 Nightwatch 的配置信息。创建完毕之后,在文件内写入以下内容:

  1. {

  2. "src_folders": ["tests"],

  3. "output_folder": "reports",

  4. "custom_commands_path": "",

  5. "custom_assertions_path": "",

  6. "page_objects_path": "",

  7. "globals_path": "",

  8. "selenium": {

  9. "start_process": true,

  10. "server_path": "",

  11. "log_path": "",

  12. "host": "127.0.0.1",

  13. "port": 4444,

  14. "cli_args": {

  15. "webdriver.chrome.driver": ""

  16. }

  17. },

  18. "test_settings": {

  19. "default": {

  20. "launch_url": "http://localhost",

  21. "selenium_port": 4444,

  22. "selenium_host": "localhost",

  23. "silent": true,

  24. "screenshots": {

  25. "enabled": false,

  26. "path": ""

  27. },

  28. "desiredCapabilities": {

  29. "browserName": "firefox",

  30. "javascriptEnabled": true,

  31. "acceptSslCerts": true

  32. }

  33. },

  34. "chrome" : {

  35. "desiredCapabilities": {

  36. "browserName": "chrome",

  37. "javascriptEnabled": true,

  38. "acceptSslCerts": true

  39. }

  40. }

  41. }

  42. }

nightwatch.json 的文件名是 不可以 修改的,因为 Nightwatch 每次启动的时候都是从它读取配置喔!这里的配置项很多,不过先不管它,我们接着创建文件。如果您希望查看 Nightwatch 的详细配置

2.接着在项目根目录下创建文件 "nightwatch.conf.js" ,同样此文件名也是不可以修改的,因为 Nightwatch 每次启动也会从它这里读取配置喔~ (´・_・`)
创建完毕后,打开文件,并写入如下内容:

  1. const path = require('path')

  2. module.exports = (function (settings) {

  3. return settings;

  4. })(require('./nightwatch.json'))

  5. /*

  6. * Nightwatch 会从 nightwatch.json 中读取配置。

  7. * 不过如果存在 nightwatch.conf.js,将会变为首先从后者中读取配置。

  8. * nightwatch.conf.js 存在的意义是使用 JavaScript 动态生成配置信息。

  9. * 如果配置信息是不需要代码修改的,直接使用 nightwatch.json 就可以啦。

  10. */

3.再次在项目根目录建立文件 "startup.js",然后在文件内部写入:

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

这个文件就是我们测试的入口文件,以后我们要执行测试就要运行这个文件,命令为 node ./startup。入口文件的名字是可以按照喜好更改的,只要运行它就好啦。不过每次输入 node ./startup 太麻烦了,所以我们将这条命令写入 npm scripts 中 ~~~ 打开 "package.json",在 JSON 对象中建立 "script" 属性,并写入内容:

  1. {

  2. ...

  3. "scripts": {

  4. "start": "node ./startup.js"

  5. },

  6. ...

  7. }

以后每次运行测试只要在项目根目录中执行 npm start 就好了!(・∀・)
Nightwatch 的配置暂时告一段落(其实马上就会回来………),接下来我们来处理 Selenium.

二. 配置 Selenium

Selenium 是自动化测试环境,它提供了测试服务器、启动浏览器、网页自动操作等功能,同时暴露 API 给 Nightwatch 供我们使用。

我们接下来将要告诉 Nightwatch 我们的 Selenium 安装在哪里,启动浏览器的 Driver 程序在哪里,然后建立 Selenium 的安装脚本与手工启动脚本,以便不时之需 ~~

Driver 是让 Selenium 打开系统上已安装的浏览器的程序。

1. 建立 Selenium 的配置信息。
在项目根目录下建立文件夹 "build",并在其中创建文件 "selenium-conf.js",并写入如下信息:

  1. const process = require('process')

  2. module.exports = {

  3. // Selenium 的版本配置信息。请在下方链接查询最新版本。升级版本只需修改版本号即可。

  4. // https://selenium-release.storage.googleapis.com/index.html

  5. selenium: {

  6. version: '2.53.1',

  7. baseURL: 'https://selenium-release.storage.googleapis.com'

  8. },

  9. // Driver 用来启动系统中安装的浏览器,Selenium 默认使用 Firefox,如果不需要使用其他浏览器,则不需要额外安装 Driver。

  10. // 在此我们安装 Chrome 的 driver 以便使用 Chrome 进行测试。

  11. driver: {

  12. chrome: {

  13. // Chrome 浏览器启动 Driver,请在下方链接查询最新版本。

  14. // https://chromedriver.storage.googleapis.com/index.html

  15. version: '2.22',

  16. arch: process.arch,

  17. baseURL: 'https://chromedriver.storage.googleapis.com'

  18. }

  19. }

  20. }

本配置信息包含 Selenium 本体配置与 Driver 配置。我们将在稍后动态载入这些配置。 本文件的目的是为了更好管理 Selenium 的版本。

2. 告诉 Nightwatch,我的 Selenium 与 Driver 在哪里。
再次打开项目根目录下的 "nightwatch.conf.js" 文件,并这样编辑:

  1. const seleniumConfig = require('./build/selenium-conf')

  2. const path = require('path')

  3. module.exports = (function (settings) {

  4. // 告诉 Nightwatch 我的 Selenium 在哪里。

  5. settings.selenium.server_path = `${path.resolve()}/node_modules/selenium-standalone/.selenium/selenium-server/${seleniumConfig.selenium.version}-server.jar`

  6. // 设置 Chrome Driver, 让 Selenium 有打开 Chrome 浏览器的能力。

  7. settings.selenium.cli_args['webdriver.chrome.driver'] = `${path.resolve()}/node_modules/selenium-standalone/.selenium/chromedriver/${seleniumConfig.driver.chrome.version}-${seleniumConfig.driver.chrome.arch}-chromedriver`

  8. return settings;

  9. })(require('./nightwatch.json'))

我们新加了两行配置,它们的作用如注释所示。

3. 建立 Selenium 安装脚本,一键安装 Selenium。
还记得上一章我们提过 selenium-standalone 只是用来安装和管理 Selenium 的工具么?所以现在是时候用它来安装 Selenium 了。我们将通过调取 selenium-standalone 的内置方法来实现自动安装。在 "build" 文件夹中建立文件 "selenium-setup.js",并写入如下信息:

  1. const selenium = require('selenium-standalone')

  2. const seleniumConfig = require('./selenium-conf.js')

  3. selenium.install({

  4. version: seleniumConfig.selenium.version,

  5. baseURL: seleniumConfig.selenium.baseURL,

  6. drivers: seleniumConfig.driver,

  7. logger: function (message) { console.log(message) },

  8. progressCb: function (totalLength, progressLength, chunkLength) {}

  9. }, function (err) {

  10. if (err) throw new Error(`Selenium 安装错误: ${err}`)

  11. console.log('Selenium 安装完成.')

  12. })

同样为了方便,我们将安装命令写入 npm scripts 中:

  1. {

  2. ...

  3. "scripts": {

  4. "start": "node ./startup.js",

  5. "selenium-setup": "node ./build/selenium-setup.js"

  6. },

  7. ...

  8. }

然后在项目根目录执行 npm run selenium-setup 安装 Selenium.

当提示安装完成后,一切就绪!(・∀・)

Selenium 与其 Driver 会安装到 "node_modules/selenium-standalone/.selenium" 中。

4. 想要手工启动 Selenium?
默认情况下,Selenium 是由 Nightwatch 启动的,不需要手工干预,不过如果想要手工启动当然是可以的啦。

在 build 文件夹中建立文件 "selenium-start.js",并写入如下信息:

  1. const selenium = require('selenium-standalone')

  2. const seleniumConfig = require('./selenium-conf.js')

  3. selenium.start({

  4. drivers: seleniumConfig.driver

  5. }, function (err, child) {

  6. if (err) throw new Error(`Selenium 启动失败: ${err}`)

  7. console.log(`Selenium 已手工启动,进程 PID: ${child.pid}`)

  8. console.log('当不再需要运行 Selenium 时可关闭此 PID 进程.')

  9. })

然后同样添加启动命令至 npm scripts 中:

  1. {

  2. ...

  3. "scripts": {

  4. "start": "node ./startup.js",

  5. "selenium-setup": "node ./build/selenium-setup.js",

  6. "selenium-start": "node ./build/selenium-start.js"

  7. },

  8. ...

  9. }

  • 以后使用命令 npm run selenium-start 就可以手工启动 Selenium 了。

搭建完了!

至此,我们的配置与安装工作已经完成,项目结构应该为:

  1. >

  2. | -- build

  3. | | -- selenium-conf.js # Selenium 版本信息配置。

  4. | | -- selenium-setup.js # Selenium 安装命令脚本。

  5. | | -- selenium-start.js # Selenium 启动命令脚本。

  6. |

  7. | -- nightwatch.conf.js # Nightwatch 动态配置文件。

  8. | -- nightwatch.json # Nightwatch 配置文件。

  9. | -- package.json # 项目信息配置文件。

  10. | -- 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",添加以下内容:

 
 
  1. module.exports = {

  2. 'Find the answer.': function (client) {

  3. // TODO...

  4. }

  5. }

module.exports 导出一个对象,对象的 Key 即为测试用例名称,您可以编写多个测试用例,Nightwatch 将依次执行。

您可以在测试用例中导入其他模块并直接使用在测试逻辑中,这也是比 Phantom.JS 优秀的地方。

先写到这里,您可能会对 cilent 感到陌生,所以还是要简单介绍一下。

client 是代码运行时 Nightwatch 提供的对象,所有对浏览器进行的操作都将使用此对象调取,比如 client.click("CSS Selector")、client.getCookie(function () {...}),我们第一章说过的 "可以简单理解为 Selenium 的控制软件" 就是通过它体现的喔!

client 的所有 API 

大致了解这东西的意思之后,就可以接着完善测试逻辑了:

 
 
  1. module.exports = {

  2. 'Find the answer.': function (client) {

  3. // 定义 Bing 页面中的节点.

  4. const searchInput = '#sb_form_q'

  5. const searchBtn = '#sb_form_go'

  6. const question = 'what is microsoft'

  7. // 启动浏览器并打开 bing.com.

  8. client.url('http://bing.com').maximizeWindow()

  9. // 确保 "body" 和输入框可以使用.

  10. client.expect.element('body').to.be.present

  11. client.expect.element(searchInput).to.be.visible

  12. client.pause(2000) // 稍等两秒.

  13. // 输入 "what is microsoft" 然后搜索.

  14. client.setValue(searchInput, question)

  15. client.click(searchBtn)

  16. client.pause(2000)

  17. // 截一张图然后保存到 "reports/answer.png".

  18. client.expect.element('body').to.be.present

  19. client.saveScreenshot('reports/answers.png')

  20. client.end()

  21. }

  22. }

来关注一下 expect ,是不是看起来很像自然语言?这些语句就是测试结果的验证语句,就是我们希望得到的结果。比如client.expect.element('body').to.be.present.before(3000),意思就是 "希望 body 元素能在 3000 毫秒内初始化完毕"。

Nightwatch 支持 BDD-Style 与 Assert 断言两种风格

关于 Assert、BDD、TDD 的更多内容请参照其他文章。

是不是确实没什么用?毕竟是个简单的 Demo 而已,哈哈。那么添加一个稍微复杂点的测试用例。

编写另一个简单的测试用例

  • 这个 demo 打开哔哩哔哩  ,然后执行:
  • 打开首页并等待加载完毕;
  • 检查登陆按钮是否存在;
  • 点击登陆按钮;
  • 填写用户名与密码;
  • 点击登陆;
  • 等待页面加载;
  • 通过 Cookie 检查是否已登陆;
  • 确保登陆后的用户导航面板存在;
  • 鼠标移至头像处打开导航面板;
  • 点击退出登陆;
  • 等待页面刷新后检查 Cookie 是否已退出登陆;
  • 结束测试。

其实就是第一章的那个 Demo 图干的事情了 (・∀・)这个 demo 不再啰嗦,直接放出代码:

 
 
  1. // Account setting.

  2. const accountConfig = {

  3. username: 'USERNAME',

  4. password: 'PASSWORD',

  5. uid: '10000'

  6. }

  7. module.exports = {

  8. 'Bilibili Live Login Test': function (client) {

  9. client.url('http://live.bilibili.com').maximizeWindow()

  10. // Page Init.

  11. client.expect.element('body').to.be.present.before(3000)

  12. client.expect.element('.top-nav-login-btn.last').to.be.visible

  13. // Login.

  14. client.click('.top-nav-login-btn.last')

  15. client.waitForElementVisible('#bilibili-quick-login', 2000)

  16. client.frame(0)

  17. client.pause(2000)

  18. client.setValue('#login-username', accountConfig.username)

  19. client.setValue('#login-passwd', accountConfig.password)

  20. client.click('#login-submit')

  21. // Wait and check page has been reloaded.

  22. client.frameParent()

  23. client.pause(4000)

  24. client.expect.element('body').to.be.present.before(3000)

  25. // Check cookies to ensure we are signed in.

  26. client.getCookies(function (result) {

  27. result.value.forEach((value, index, array) => {

  28. if (value.name === 'DedeUserID') client.assert.equal(parseInt(value.value, 10), accountConfig.uid)

  29. })

  30. })

  31. // Move to User Avatar.

  32. client.expect.element('.user-avatar-link').to.be.visible

  33. client.moveToElement('.user-avatar-link', 5, 5)

  34. client.pause(800)

  35. client.expect.element('#top-nav-user-panel').to.be.visible

  36. // Logout.

  37. client.click('#top-nav-logout-link')

  38. client.pause(5000)

  39. client.expect.element('body').to.be.present.before(3000)

  40. // Check cookies again to ensure we are off.

  41. client.getCookies(function (result) {

  42. var logout = true

  43. result.value.forEach((value, index, array) => {

  44. if (value.name === 'LIVE_LOGIN_DATA') logout = false

  45. })

  46. client.assert.equal(logout, true)

  47. })

  48. client.pause(1000)

  49. client.end()

  50. }

  51. }

您可以新建一个文件,或者在之前的文件中继续编写。

运行测试用例
回到项目根目录,执行 npm start,然后就可以看到浏览器自己测试了!
运行效果如下:

测试运行完毕之后,测试结果将打印在终端里,同时会生成到 reports 文件夹中。

您可以在 nightwatch.json 中修改 "output_folder" 来更换报告生成目录。

需要注意的地方
您可能在使用中会遇到例如 “明明看到节点缺获取不到”、“鼠标功能好像时好时坏” 等问题,在此给您一些建议:

由于现在很多网站使用诸如 Angular、Vue 等框架构建,其节点可能为组件动态渲染,所以 Selenium 在执行测试时可能获取的 Dom 树为旧数据从而导致找不到节点,因此您可以执行等待语句确保节点出现后再进行测试。不过可能不是 100% 成功,这也是这套测试系统的短板之一。

如果您在进行模拟鼠标的测试,您的鼠标指针可能会干扰您的测试,因此建议运行测试后将您的指针移动至屏幕外部,以避免干扰到浏览器测试。

测试很可能因为页面加载时间问题导致测试失败,不过这也是 E2E 测试的特征所在,您可以修改您的测试逻辑,或致力缩短加载时间。

大功告成!

现在您已经拥有您自己的测试工具并且成功编写了两个测试用例!此处您应该为自己鼓掌!
您现在已经可以将 E2E 测试纳入您的开发流程之中,在下相信这将对您的开发有不小的帮助。如果您有兴趣,您也可以考虑 单元测试的可能性。

同时像之前提到的,如果您在使用 Vue 构建您的项目,您可以使用 Vue-cli 来生成已经包含 Selenium 与 Nightwatch 的 Vue 种子项目,您可以在 test/e2e 中编写您的测试用例。

总结:

感谢每一个认真阅读我文章的人!!!

作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

  1. 文档获取方式:

  2. 加入我的软件测试交流群:680748947免费获取~(同行大佬一起学术交流,每晚都有大佬直播分享技术知识点)

这份文档,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!

以上均可以分享,只需要你搜索vx公众号:程序员雨果,即可免费领取

  • 19
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值