blog
blog copied to clipboard
从零开始做Vue前端架构(7)e2e测试
前言
吐槽
e2e测试在前端测试中,也许是最不被看重的一项吧。 小公司就不说了,即使是大厂,也极少有e2e测试。因为它需要花费的精力,相比得到的回报而言,可以说是相差悬殊,说白了,就是吃力不讨好- -|| e2e测试其实就是模拟用户行为,我们得根据业务写各种各样的不同操作。而几乎所有的项目,业务都是会变的。所以,因为业务变了,模拟用户行为也会随之改变。最后,就各种改,即改业务代码,又改测试代码,结果,无端端多出一大堆工作量,而且,很大的可能,下一轮迭代还得改,我上次就是这么死的。
燃鹅
但并不是所有的项目都不适合e2e测试的。比如,一个大项目,已经上线多年了,需求内容等基本都成形了。这种情况,就比较适合上e2e了。 项目大的缺点就是,修改的时候,一不小心就会牵一发而动全身。当年刚初来乍到的时候,就经常不小心改了公共样式,或者公共js,然后导致多个页面发生了变化,从而产生bug。因此,这种时候就很需要e2e测试了。
运用场景
总的来说,e2e的运用场景就是:上线久、业务稳、体量大的项目啦~(千万不要在刚启动或迭代很快的项目上e2e,切记,切记)
nightmare
nightmare是高阶浏览器自动测试库。
对比phantom
nightmare相比phantom而言,api更加简洁方便,比如引用的比较多的就是,同样是实现一个向yahoo自动提交关键词并搜索的功能:
- PhantomJS实现
phantom.create(function (ph) {
ph.createPage(function (page) {
page.open('http://yahoo.com', function (status) {
page.evaluate(function () {
var el =
document.querySelector('input[title="Search"]');
el.value = 'github nightmare';
}, function (result) {
page.evaluate(function () {
var el = document.querySelector('.searchsubmit');
var event = document.createEvent('MouseEvent');
event.initEvent('click', true, false);
el.dispatchEvent(event);
}, function (result) {
ph.exit();
});
});
});
});
});
- nightmare实现
yield Nightmare()
.goto('http://yahoo.com')
.type('input[title="Search"]', 'github nightmare')
.click('.searchsubmit');
是不是感觉世界突然变得很美好?
工具
另外,官方文档还推荐了两个很棒的工具:
配置
安装包
npm i -D nightmare
因为nightmare是基于electron的,安装的时候还会安装electron相关的东西,所以安装会比较慢,这个时候,可以打开网易云音乐来首歌。
牛刀小试
我们先用其他网站来做个小测试,比如github
。
在test
文件夹中,和unit
文件夹同级,新建一个e2e
文件夹,然后在e2e
文件夹下新建一个叫test.js
的文件,内容为:
const Nightmare = require('nightmare')
const chai = require('chai')
const expect = chai.expect
describe('test CodeLittlePrince results', () => {
it('should find the CodeLittlePrince\'s blog github link first', function(done) {
// 设定整个模拟的时长,超过则GG
this.timeout('60s')
const nightmare = Nightmare({
show: true
})
nightmare
.goto('https://github.com/login')
.wait('input[name="login"]')
.type('input[name="login"]', '[email protected]')
.type('input[name="password"]', '******') // 用户名和密码自行修改
.click('input[name="commit"]')
.wait('input[placeholder="Search GitHub"]')
.type('input[placeholder="Search GitHub"]', 'CodeLittlePrince/blog \u000d')
.wait('a[href="/CodeLittlePrince/blog"]')
.click('a[href="/CodeLittlePrince/blog"]')
// .evaluate(() => document.querySelector('#links .result__a').href)
// evaluate的作用就是将值return,给expect用
.evaluate(() => location.href)
.end()
.then(link => {
expect(link).to.equal('https://github.com/CodeLittlePrince/blog')
done()
})
})
})
然后修改package.json
的scripts:
"test:e2e": "mocha ./test/e2e/test.js"
最后运行看效果:
感觉棒棒的~
正式配置
因为运行过我的项目的同学知道,我只有三个页面,所以,可交互太少,所以我牛刀小试
让同学们可以更加直观的感受到nightmare
的方便。
接下来我们就来正式地配置吧。
文件组织
还是刚才的test/e2e
文件夹下,删除text.js
文件,创建index.js
作为入口文件:
/**
* e2e测试文件的入口文件
*/
// 测试页面的路由和文案是否正确
require('./specs/page.spec.js')
然后,创建specs
文件夹,然后在该文件夹下创建文件page.spec.js
:
const Nightmare = require('nightmare')
const chai = require('chai')
const expect = chai.expect
const nightmare = Nightmare({
show: true
})
describe('pages', () => {
it('page ', function(done) {
// 设定整个模拟的时长,超过则GG
this.timeout('30s')
nightmare
.viewport(1200, 600)
.goto('http://0.0.0.0:9999')
.wait('h1')
.click('a[href="#/pageA"]')
.wait(() => {
return location.hash === '#/pageA'
})
.click('a[href="#/pageB"]')
.wait(() => {
return location.hash === '#/pageB'
})
.evaluate(() => location.hash)
.end()
.then(hash => {
expect(hash).to.equal('#/pageB')
done()
})
})
})
修改下package.json
的scripts:
"test:e2e": "mocha ./test/e2e/index.js"
运行
- 先运行:
npm run dev
- 再运行:
npm run test:e2e
结果
➜ construct git:(master) ✗ npm run test:e2e
> [email protected] test:e2e /Users/Terry/WFE/vue-study/construct
> mocha ./test/e2e/index.js
pages
✓ page (1431ms)
1 passing (1s)
评价
感觉测试流程,这样有点鸡肋,因为得先run dev
,说不定有需要还需要run mock
,最后再run test:e2e
,略繁琐。当然,这些都可以被优化成一步。
不过,个人感觉,e2e在联调以后,进入开发环境,或者测试环境以后测也可以。或者说,在测试环境测就好了,测试环境和线上环境比较接近,效果更好。本身e2e测试就是测试开发工程师写的,所以,在测试环境测也合理。不然,本地要测一遍,开发环境又测,测试环境又测,多累呐。
最后,也希望各位有什么好的意见或者建议,可以在评论区留言,讨论讨论呐~
预告
有同学反应我的vue项目没有加入vuex,额,好吧,下一篇我们加一下vuex,也出一篇文章,以免我自己偷偷加,发生断片,让同学们迷糊。
再之后呢,我们就会把这个项目利用yeoman
做成脚手架啦!
e2e参考项目实在是太少,也希望大家能够推荐一些文章或者项目,谢谢啦!