- Published on
操作模拟测试和单元测试
- Authors
- Name
- Hansuku
NightWatch 的 e2e 测试
安装
npm i -D nightwatch
如果使用 Vue cli3 构建的项目可以在 vue ui
界面中自动安装 一旦我们启用这个测试文件,nightwatch 会打开 Selenium 会话 这里我们拿百度和马天宇开刀,聪明的同学一眼就能看会
module.exports = {
'default e2e tests': browser => {
browser
// 打开百度
.url('https://www.baidu.com')
// 等待百度页面渲染完成,我们以#wrapper元素为基准,最多等待 5 秒
.waitForElementVisible('#wrapper', 5000)
// 点击百度的输入框
.click('#kw',()=>{})
// 给输入框赋值 搜索该死的温柔
.setValue('#kw', '该死的温柔', ()=>{})
// 点击搜索
.click('#su',()=>{})
// 等待搜索返回的结果页面显示,我们以#content_left作为基准
.waitForElementVisible('#content_left',5000)
// 确定有返回来的第一个大标题
.assert.elementPresent('.c-gap-bottom-small:nth-of-type(1)')
// 确认第一个大标题是我们预期的内容
.assert.containsText('.c-gap-bottom-small:nth-of-type(1)', '该死的温柔付费试听_高音质歌曲_网易云音乐')
// 测试完成
.end()
}
}
nightwatch 还是很好理解的,用过 jquery 或者 用过 python 爬虫的同学基本只要找指令就可以上手,下面是 nightwatch 需要注意的几个点
- nightwatch 可以完全独立于项目运作,意味着你只要在任何一个地方创建一个 js 脚本,然后全局 nightwatch 安装,就可以测试任何一个拥有 web 服务的页面,但更加规范、工程化尽量在自己每个项目的每个模块文件中存留和植入脚本
- nightwatch 的 API 准则是 WebDriver ,核心依赖是 Selenium
- 默认情况下测试是使用的
ChromeDriver
即在谷歌浏览器上测试,除此之外他还支持GeckoDriver
(火狐浏览器)Microsoft WebDriver
(微软的 Microsoft Edge 不过即将要废弃了,因为 MS 的内核要换成 Chromium 了)以及SafariDriver
(这个应该都认得)
不同浏览器的 WebDriver 安装
- GeckoDriver
npm install geckodriver --save-dev
- ChromeDriver
npm install chromedriver --save-dev
- Microsoft WebDriver 需要注意的是 MS 只能在 windows 运行
C:\> DISM.exe / Online / Add-Capability /CapabilityName:Microsoft.WebDriver ~~~~0.0.1.0
- SafariDriver MacOS 中自带 Safari 的 Drivier 二进制文件,所以只需要启用即可(可能需要
sudo
)safaridriver --enable
Mocha+Chai 的单元测试
本质上 Mocha 和 NightWatch 达到的目的都差不多,通过你流程线路去完成一系列操作,在我看来二者区别在于,NightWatch 针对已经可以有了 WebService ,可以被浏览器运行的网页测试,而 Mocha 可以直接针对你的源代码模块测试,比如直接打开.vue .jsx .js
文件测试,所以 Mocha 更适合在功能还没有完成,但我们已经完成部分模块的时候进行单元测试。
- simple demo
// HelloWorld.vue
<template>
<div>
<span>{{ msg }}</span>
</div>
</template>
<script>
export default {
data() {
return {
msg: 'hello!'
}
},
created(){
this.msg = 'bye!'
}
}
</script>
// example.spec.js
import { expect } from 'chai'
import HelloWorld from '@/components/HelloWorld.vue'
describe('HelloWorld', () => {
it('has a created hook', () => {
expect(typeof HelloWorld.created).to.eql('function')
})
})
上面我们构建了一个很简单的 vue 文件,注入了 created
生命周期,然后在测试用例中,我们断言 created
的类型为 function
- demo:是否正确渲染 vue 实例
// HelloWorld.vue
<template>
<div>
<span>{{ msg }}</span>
</div>
</template>
<script>
export default {
data() {
return {
msg: 'Hello World!'
}
},
mounted(){
this.msg = 'Hello mounted'
}
}
</script>
// example.spec.js
import Vue from 'vue'
import { expect } from 'chai'
import HelloWorld from '@/components/HelloWorld.vue'
describe('render msg test', () => {
it('should render correct msg', () => {
// 调用 vue 创建组件构造器
let Constructor = Vue.extend(HelloWorld)
// 激活构造器
const vm = new Constructor()
// 断言组件激活时 msg 是 Hello World!
expect(vm.msg).to.equal('Hello World!')
// 获取 vm 挂载时对象
let vmm = vm.$mount()
// 断言 vm 挂载时 msg 是 Hello mounted
expect(vmm.msg).to.equal('Hello mounted')
})
})
最佳实践
首先我们使用自动化最核心的目的是保证项目质量,但保证项目质量不单单是依靠测试就可以完成,所以我认为从开发者角度来看一个合理的三部曲应该是
- 拿到需求,理清思路(画流程线路图/UML)
- 根据思路来编码,在编码过程中我们可以结合代码和流程线路图发现一些边界情况来补足
- 基础、公共模块单元测试,完整功能 e2e 测试
先从画图说起,推荐使用 ProcessOn,可能很多人会认为画图是多余、浪费时间的,但作为团队内著名的 BugMaker 我认为,在做一个稍微复杂的需求的之前如果能够把思路理清、考虑到不同情况,你写出来的东西会和直接上手撸代码是两种质量的,并且这个流程图画出来以后还可以交到产品(二次确认、压榨需求)、测试(通过流程补足他们的测试完整性),某些团队可能依靠产品的文字来表述需求,但文字绝对没有流程图来的直观,写代码的时候不可能盯着一坨文字去写。
当我们根据流程图编码的时候,也不是完全死板的依靠流程图去写,流程图说什么是什么这种是非常糟糕的,不论是产品的文字表述、流程图总归都会有一些没有考虑到的情况,这个时候需要的是严谨的思维和敏锐的认知感,现在遇到不能快速定位的 bug 大部分都属于逻辑疏漏,那我一个功能点几千行代码,定位问题的时间就会被一再拉长。如果有一份流程图,是否可以通过观察流程图来快速定位?
之前 Leader 有提到“白盒测试”的概念,我把这种概念套在工程师身上,就是四个字:内外兼修。对内,是工程师的编码能力,对外,是工程师的工具和工程运用能力。