E2E测试

E2E(end to end)测试是指端到端测试又叫功能测试,站在用户视角,使用各种功能、各种交互,是用户的真实使用场景的仿真。在产品高速迭代的现在,有个自动化测试,是重构、迭代的重要保障。对web前端来说,主要的测试就是,表单、动画、页面跳转、dom渲染、Ajax等是否按照期望。

E2E测试驱动重构

重构代码的目的是什么?是为了使代码质量更高、性能更好、可读性和拓展性更强。在重构时如何保证修改后正常功能不受影响?E2E测试正是保证功能的最高层测试,不关注代码实现细节,专注于代码能否实现对应的功能,相比于单元测试、集成测试更灵活,你可以彻底改变编码的语法、架构甚至编程范式而不用重新写测试用例。

Nightwatch

知道nightwatch是因为vue-cli工具安装的时候会询问是否需要安装nightwatch。本身vue项目也是使用nightwatch来e2e测试的。nightwatch是一个使用selenium或者webdriver或者phantomjs的nodejs编写的e2e自动测试框架,可以很方便的写出测试用例来模仿用户的操作来自动验证功能的实现。selenium是一个强大浏览器测试平台,支持firefox、chrome、edge等浏览器的模拟测试,其原理是打开浏览器时,把自己的JavaScript文件嵌入网页中。然后selenium的网页通过frame嵌入目标网页。这样,就可以使用selenium的JavaScript对象来控制目标网页。

Nightwatch安装

通过npm安装nightwatch。

$ npm install [-g] nightwatch
复制代码

根据需要安装Selenium-server或者其他Webdriver,比手动去下载jar文件要方便很多。安装哪些Webdriver取决于你想要测试哪些浏览器,如果只测试Chrome甚至可以不装Selenium-server

$ npm install selenium-server
$ npm install chromedriver
复制代码

Nightwatch的配置

nightwatch的使用很简单,一个nightwatch.json或者nightwatch.config.js(后者优先级高)配置文件,使用runner会自动找同级的这两个文件来获取配置信息。也可以手动使用--config来制定配置文件的相对路径。

{"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" : "","port" : 4444,"cli_args" : {"webdriver.chrome.driver" : "","webdriver.gecko.driver" : "","webdriver.edge.driver" : ""}},"test_settings" : {"default" : {"launch_url" : "http://localhost","selenium_port"  : 4444,"selenium_host"  : "localhost","silent": true,"screenshots" : {"enabled" : false,"path" : ""},"desiredCapabilities": {"browserName": "firefox","marionette": true}},"chrome" : {"desiredCapabilities": {"browserName": "chrome"}},"edge" : {"desiredCapabilities": {"browserName": "MicrosoftEdge"}}}
}
复制代码

json配置文件大概就是上面这样,分为基本配置、selenium配置和测试配置三个部分。基本配置依次为测试用例源文件路径、输出路径、基础指令路径、全局配置路径等。selenium设置包括是否开启、路径、端口等,cli_args指定将要运行的webdriver。test_settings制定测试时各个环境的设置,默认是default,通过--env加环境名可以指定配置的任意环境。只要把测试用例放在对应的文件夹使用module.exports暴露一个对象,其中key是测试名,value是一个接受browser实例的函数,在函数中进行断言,nightwatch会自动依次调用文件夹中的测试用例。一个简易的Chrome headless模式的nightwatch.conf.js配置如下:

{'src_folders': ['test/e2e/specs'],'output_folder': 'test/e2e/reports','globals_path': 'test/e2e/global.js','selenium': {'start_process': true,'server_path': require('selenium-server').path,'port': port,'cli_args': {'webdriver.chrome.driver': require('chromedriver').path}},'test_settings': {'default': {'selenium_port': port,'selenium_host': 'localhost','silent': true,'globals': {'productListUrl': 'http://localhost:' + 9003 + '/productlist.html',}},'chrome': {'desiredCapabilities': {'browserName': 'chrome','javascriptEnabled': true,'acceptSslCerts': true,'chromeOptions': {'args': ['--headless','--disable-gpu'],'binary': '/opt/google/chrome/google-chrome'}}},'globals': {'productListUrl': 'http://localhost:' + 9003 + '/productlist.html',}}
}
复制代码

API

Nightwatch的API分为四个部分

1.Expect

在browser实例上以.expect.element开头的BDD(行为驱动测试)风格的接口,0.7及以上版本nightwatch可用。通过.element方法传入一个selector(参考querySelector或者jq的语法)获取到dom实例,通过.text、.value、.attribute等方法获取到实例属性。还有一些语意明确的修饰:

  • to
  • be
  • been
  • is
  • that
  • which
  • and
  • has
  • with
  • at
  • does
  • of 再加上比较判断:
.equal(value)/.contain(value)/.match(regex).selected.present
复制代码

还有时间修饰.before(ms)(表示一段时间之内)、.after(ms)(表示一段时间之后)。就像造句一样:某某元素的某某属性(在某某时间)(不)等于什么值,这就是BDD风格的测试代码。例如:

this.demoTest = function (browser) {browser.expect.element('body').to.have.attribute('data-attr');browser.expect.element('body').to.not.have.attribute('data-attr');browser.expect.element('body').to.not.have.attribute('data-attr', 'Testing if body does not have data-attr');browser.expect.element('body').to.have.attribute('data-attr').before(100);browser.expect.element('body').to.have.attribute('data-attr').equals('some attribute');browser.expect.element('body').to.have.attribute('data-attr').not.equals('other attribute');browser.expect.element('body').to.have.attribute('data-attr').which.contains('something');browser.expect.element('body').to.have.attribute('data-attr').which.matches(/^something\ else/);
};
复制代码

2.Assert

以.assert/.verify开头的两套相同的方法库,区别是assert如果断言失败则退出整个测试用例所有步,verify则打印后继续进行。

this.demoTest = function (browser) {browser.verify.title("Nightwatch.js");browser.assert.title("Nightwatch.js");
};
复制代码

有如下判断方法:

.attributeContains(selector, attribute, expected[, message])
检查指定元素(selector)的指定属性(attribute)是否包含有期待的值(expected)打印出指定信息(可选填的message)其他方法讲解类似,不一一赘述.attributeEquals(selector, attribute, expected[, message])
检查元素指定属性是否等于预期.containText(selector, expectedText[, message])
包含有指定的文本.cssClassPresent(selector, className[, message])
检查元素指定class是否存在.cssClassNotPresent(selector, className[, message])
检查元素指定class是否不存在.cssProperty(selector, cssProperty, expected[, message])
检查元素指定css属性的值是否等于预期.elementPresent(selector[, message)
检查指定元素是否存在于DOM中.elementNotPresent(selector[, message)
检查指定元素是否不存在于DOM中.hidden(selector[, message)
检查指定元素是否不可见.title(expected[, message])
检查页面标题是否等于预期.urlContains(expectedText[, message])
检查当前URL是否包含预期的值.urlEquals(expected[, message])
检查当前URL是否等于预期的值.value(selector, expectedText[, message])
检查指定元素的value是否等于预期.valueContains(selector, expectedText[, message])
检查指定元素的value是否包含预期的值.visible(selector[, message)
检查指定元素是否可见
复制代码

3.Commands

很多命令的读写,可以操作BOM、DOM对象:

.clearValue(selector[, message])
清空input、textarea的值.click(selector[, callback])
callback为执行完命令后需要执行的回调.closeWindow([callback]).deleteCookie(cookieName[, callback]).deleteCookies([callback]).end([callback])
结束会话(关闭窗口).getAttribute(selector, attribute, callback).getCookie(cookieName, callback).getCookies(callback).getCssProperty(selector, cssProperty, callback).getElementSize(selector, callback).getLocation(selector, callback).getLocationInView(selector, callback).getLog(typeString, callback)
获取selenium的log,其中type为string或者function.getLogTypes(callback).getTagName(selector, callback).getText(selector, callback).getTitle(callback).getValue(selector, callback).init([url])
url方法的别名,如果不传url则跳转到配置中的launch_url.injectScript(scriptUrl[, id, callback])
注入script.isLogAvailable(typeString, callback)
typeString为string或者function,用来测试log的type是否可用.isVisible(selector, callback).maximizeWindow([callback])
最大化当前窗口.moveToElement(selector, xoffset, yoffset[, callback])
移动鼠标到相对于指定元素的指定位置.pause(ms[, callback])
暂停指定的时间,如果没有时间,则无限暂停.perform(callback)
一个简单的命令,允许在回调中访问api.resizeWindow(width, height[, callback])
调整窗口的尺寸.saveScreenshot(fileName, callback).setCookie(cookie[, callback]).setValue(selector, inputValue[, callback]).setWindowPosition(offsetX, offsetY[, callback]).submitForm(selector[, callback]).switchWindow(handleOrName[, callback]).urlHash(hash).useCss()
设置当前选择器模式为CSS.useXpath()
设置当前选择器模式为Xpath.waitForElementNotPresent(selector, time[, abortOnFailure, callback, message])
指定元素指定时间内是否不存在.waitForElementNotVisible(selector, time[, abortOnFailure, callback, message])
指定元素指定时间内是否不可见.waitForElementPresent(selector, time[, abortOnFailure, callback, message]).waitForElementVisible(selector, time[, abortOnFailure, callback, message])
复制代码

简单的例子:

this.demoTest = function (browser) {browser.click("#main ul li a.first", function(response) {this.assert.ok(browser === this, "Check if the context is right.");this.assert.ok(typeof response == "object", "We got a response object.");});
};
复制代码

4.webdriver protocol

可以操作一些更底层的东西,比如:

  • Sessions
  • Navigation
  • Command Contexts
  • Elements
  • Element State
  • Element Interaction
  • Element Location
  • Document Handling
  • Cookies
  • User Actions
  • User Prompts
  • Screen Capture
  • Mobile Related

简单的例子:

module.exports = {'demo Test' : function(browser) {browser.element('css selector', 'body', function(res) {console.log(res)});}
};
复制代码

拓展

也可以单独使用chromedriver等进行单一平台测试,效率更高,测试更快。只需要npm安装chromedriver或者其他webdriver,不需要selenium,在selenium设置中把selenium进程设置为false,测试环境配置中做出相应的改变。在golobal_path设置的配置文件中,利用nightwatch测试的全局before和after钩子中开、关服务器就好:

var chromedriver = require('chromedriver');function startChromeDriver() {chromedriver.start();
}function stopChromeDriver() {chromedriver.stop();
}module.exports = {before : function(done) {startChromeDriver.call(this);done();},after : function(done) {stopChromeDriver.call(this);done();}
};
复制代码

配置尤雨溪大神的nightwatch-helpers食用更佳,补了一些api。Assertions:

  • count(selector, count)
  • attributePresent(selector, attr)
  • evaluate(fn, [args], [message])
  • checked(selector, expected)
  • focused(selector, expected)
  • hasHTML(selector, html)
  • notVisible(selector)

Commands:

  • dblClick(selector)
  • waitFor(duration)
  • trigger(selector, event[, keyCode])
  • enterValue(selector, value)

只需要在图中位置配置一下即可

其他

推荐使用Headless测试即不打开浏览器可视界面以便能跑在服务器上。比如Phantomjs可以模拟webkit内核浏览器的行为,在Nightwatch中配置一下Phantomjs环境即可,启动nightwatch时使用--env加上配置里的环境名激活对应的环境。如今(59版本以上)Phantomjs已经停止维护,使用Chrome自带的headless模式是更好的选择。也可以使用Puppeteer来做E2E测试,好处是只依赖一个Puppeteer,并且API相对简单。

使用nightwatch进行E2E测试中文教程相关推荐

  1. 使用Nightwatch进行E2E测试

    本文在线预览 E2E测试 不同于行为驱动测试(BDD)和单元测试独立运行并使用模拟/存根,端到端测试将试着尽可能从用户的视角,对真实系统的访问行为进行仿真.对Web应用来说,这意味着需要打开浏览器.加 ...

  2. Vue + nightwatch + Chrome76进行e2e测试的正确配置(二)

    在这个问题困扰了我好几个小时,因为在Windows下确实没有问题.直到我看到了这条issue: Strangely, seeing this happen on RHEL (start_server= ...

  3. 自动化测试(二)02——单元测试类工具-Karma、Jasmine、Mocha、Jest、AVA E2E测试类工具-cypress、nightmare、nightwatch、testcafe

    自动化测试(二)02--单元测试类工具-Karma.Jasmine.Mocha.Jest.AVA & E2E测试类工具-cypress.nightmare.nightwatch.testcaf ...

  4. Vue + nightwatch + Chrome76进行e2e测试的正确配置(一)

    2019.08.19 修正文章中的错误 除了单元测试之外,前端还有一个额外的测试:e2e测试,也就是端到端测试,用来模拟用户操作.对于Vue来说,推荐的e2e测试框架有nightwatch和cypre ...

  5. 前端e2e测试使用nightwatch简单示例

    nightwatch 使用 花了挺久弄明白selenium和nightwatch.踩了挺多坑的,在网上找的使用资料做起来总是出错,于是去看了下官网的资料.selenium有中文文档,但我也没看明白,因 ...

  6. e2e 测试 出现的错误

    每次开始学习vue的新知识时,总在环境这一块出现很多坑.这次我来记录一下,我在搭建vue e2e测试框架是踏过的坑吧. 我们都只知道,使用vue init webpack 项目名字<项目名字不能 ...

  7. e2e测试框架之Cypress

    谈起web自动化测试,大家首先想到的是Selenium!随着近几年前端技术的发展,出现了不少前端测试框架,这些测试框架大多并不依赖于Selenium,这一点跟后端测试框架有很大不同,如Robot Fr ...

  8. ERPLAB中文教程:创建与查看EventList

    目录 创建EventList 本分享为脑机学习者Rose整理发表于公众号:脑机接口社区 QQ交流群:941473018 主要内容包括: 介绍ERPLAB中常见的几个概念: 介绍如何创建EventLis ...

  9. ERPLAB中文教程:ERPLAB安装与添加通道

    目录 安装ERPLAB 测试 本分享为脑机学习者Rose整理发表于公众号:脑机接口社区 .QQ交流群:941473018 ERPLAB是免费开源的Matlab软件包,用于分析ERP等脑电数据.ERPL ...

  10. Python-EEG工具库MNE中文教程(13)-“bad“通道介绍

    目录 标记坏频道/标记不良通道(marking bad channels) 本分享为脑机学习者Rose整理发表于公众号:脑机接口社区 .QQ交流群:903290195 本教程主要介绍手动标记坏通道以及 ...

最新文章

  1. c++重定向后恢复_【STM32CubeIDE】重定向printf
  2. .NET开源工作流驰ccflow从表数据数据源导入设置
  3. SciTE 2.21 汉化版
  4. Zookeeper Api(java)入门与应用
  5. 团队项目第二阶段冲刺站立会议01
  6. 使用System Center DPM 2012 SP1保护企业关键数据(二)备份及恢复AD
  7. 【网络安全】Metasploit生成的Shellcode的导入函数解析以及执行流程分析(2)
  8. java中JTextPane使输出字符到指定的宽度换行,并将垂直滚动条的位置移动到输出的最后位置...
  9. mssql 计划怎每隔n秒_前端:调你一个接口6秒还配资深工程师?后端:有24部分需要处理!...
  10. 设计模式六大原则(5)——迪米特原则
  11. Unity配置JAVA环境变量
  12. live2d内嵌html,live2d web端加载moc3模型
  13. npy文件的保存与读取
  14. 西瓜创客的python_西瓜创客Python客户端
  15. 使用PicGo快速搭建图床
  16. 股票振幅榜查询易语言代码
  17. SpringSecurity 安全框架
  18. security基于数据库的认证
  19. AD转换中知道数字量计算模拟量或温度
  20. 圆柱底面周长面积c语言,编写一个程序,从键盘输入圆的半径r,圆柱的高h,分别计算出圆周长cl、圆面积cs和圆柱的体积cv,输出计算结果时要求保留小数点后4位...

热门文章

  1. 免费讲座:从草根到巨人——互联网时代的LAMP开源架构
  2. Tensorflow2.5安装
  3. RMI:Java中的分布式计算框架
  4. relu函数_激活函数解析:Sigmoid, tanh, Softmax, ReLU, Leaky ReLU
  5. Linux中grep命令查找文件,Linux中使用grep命令搜索文件名及文件内容的方法
  6. matlab2016限制内存,matlab
  7. 力扣-268 丢失的数字
  8. WARNING:root:could not open file ‘/etc/apt/sources.list.d
  9. Android ViewPager 滑动监听事件
  10. JavaWeb — session+实战项目