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相对简朴。
欢迎来我博客