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"]', '1006312908@qq.com') .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 > vue-construct@1.0.0 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测试就是测试开发工程师写的,所以,在测试环境测也合理。不然,本地要测一遍,开发环境又测,测试环境又测,多累呐。
最后,也希望各位有什么好的意见或者建议,可以在评论区留言,讨论讨论呐~