美文网首页
前端自动化测试

前端自动化测试

作者: 强某某 | 来源:发表于2020-06-19 14:21 被阅读0次

为什么要进行测试

  1. 测试可以确保得到预期的结果
  2. 作为现有代码⾏为的描述
  3. 促使开发者写可测试的代码,⼀般可测试的代码可读性也会⾼⼀点
  4. 如果依赖的组件有修改,受影响的组件能在测试中发现错误

测试分类

单元测试:指的是以原件的单元为单位,对软件进⾏测试。单元可以是⼀个函数,也可以是⼀个模块或⼀个组件,基本特征就是只要输⼊不变,必定返回同样的输出。⼀个软件越容易些单元测试,就表明它的模块化结构越好,给模块之间的耦合越弱。React的组件化和函数式编程,天⽣适合进⾏单元测试

功能测试:相当于是⿊盒测试,测试者不了解程序的内部情况,不需要具备编程语⾔的专⻔知识,只知道程序的输⼊、输出和功能,从⽤户的⻆度针对软件界⾯、功能和外部结构进⾏测试,不考虑内部的逻辑

集成测试:在单元测试的基础上,将所有模块按照设计要求组装成⼦系统或者系统,进⾏测试

冒烟测试:在正式全⾯的测试之前,对主要功能进⾏的与测试,确认主要功能是否满⾜需要,软件是否能正常运⾏

组件的单元测试有很多好处:

  • 提供描述组件⾏为的⽂档
  • 节省⼿动测试的时间
  • 减少研发新特性时产⽣的 bug
  • 改进设计
  • 促进重构
1.jpg

测试⼯具

2.jpg

单测

单元测试(unit testing),是指对软件中的最⼩可测试单元进⾏检查和验证。

在vue中,推荐⽤Mocha+chai 或者jest,咱们使⽤jest演示,语法基本⼀致

新建kaikeba.spec.js,.spec.js是命名规范,写下⼀下代码

function add(num1, num2) {
 return num1 + num2
}
describe('Kaikeba', () => {
 it('测试加法', () => {
 expect(add(1, 3)).toBe(3)
 expect(add(1, 3)).toBe(4)
 expect(add(-2, 3)).toBe(1)
 })
})

执⾏ npm run test:unit


3.jpg

api介绍

  • describe : 定义⼀个测试套件
  • it :定义⼀个测试⽤例
  • expect :断⾔的判断条件
  • toBe :断⾔的⽐较结果

测试Vue组件

<template>
 <div>
 <span>{{ message }}</span>
 <button @click="changeMsg">点击</button>
 </div>
</template> <script>
 export default {
 data () {
 return {
 message: 'vue-text'
 }
 },
 created () {
 this.message = '开课吧'
 },
 methods:{
 changeMsg(){
 this.message = '按钮点击'
 }
 }
 }
</script>
// 导⼊ Vue.js 和组件,进⾏测试
import Vue from 'vue'
import KaikebaComp from '@/components/Kaikeba.vue'
// 这⾥是⼀些 Jasmine 2.0 的测试,你也可以使⽤你喜欢的任何断⾔库或测试⼯具。
describe('KaikebaComp', () => {
 // 检查原始组件选项
 it('由created⽣命周期', () => {
 expect(typeof KaikebaComp.created).toBe('function')
 })
 // 评估原始组件选项中的函数的结果
 it('初始data是vue-text', () => {
 expect(typeof KaikebaComp.data).toBe('function')
 const defaultData = KaikebaComp.data()
 expect(defaultData.message).toBe('hello!')
 })
})
4.jpg

检查mounted之后

it('mount之后测data是开课吧', () => {
 const vm = new Vue(KaikebaComp).$mount()
 expect(vm.message).toBe('开课吧')
 })

用户点击

和写vue 没啥本质区别,只不过我们⽤测试的⻆度去写代码,vue提供了专⻔针对测试的 @vue/test-utils,可以区官网查看更多API

it('按钮点击后', () => {
 const wrapper = mount(KaikebaComp)
 wrapper.find('button').trigger('click')
 expect(wrapper.vm.message).toBe('按钮点击')
 // 测试html渲染结果
 expect(wrapper.find('span').html()).toBe('<span>按钮点击</span>')
 })

测试覆盖率

jest⾃带覆盖率,如果⽤的mocha,需要使⽤istanbul来统计覆盖率
package.json⾥修改jest配置

"jest": {
 "collectCoverage": true,
 "collectCoverageFrom": ["src/**/*.{js,vue}"],
 }

在此执⾏npm run test:unit

5.jpg

可以看到我们kaikeba.vue的覆盖率是100%,我们修改⼀下代码

<template>
 <div>
 <span>{{ message }}</span>
 <button @click="changeMsg">点击</button>
 </div>
</template> <script>
export default {
 data() {
 return {
 message: "vue-text",
 count: 0
 };
},
 created() {
 this.message = "开课吧";
 },
 methods: {
 changeMsg() {
 if (this.count > 1) {
 this.message = "count⼤于1";
 } else {
 this.message = "按钮点击";
 }
 },
 changeCount() {
 this.count += 1;
 }
 }
};
</script>
6.jpg

现在的代码,依然是测试没有报错,但是覆盖率只有66%了,⽽且没有覆盖的代码⾏数,都标记了出来

Jest详解

beforeAll(() => {
 console.log('global before all');
});
afterAll(() => {
 console.log('global after all');
});
beforeEach(() =>{
 console.log('global before each');
});
afterEach(() => {
 console.log('global after each');
});
describe('test1', () => {
 beforeAll(() => {
 console.log('test1 before all');
 });
 
 afterAll(() => {
 console.log('test1 after all');
 });
 
 beforeEach(() => {
 console.log('test1 before each');
 });
 
 afterEach(() => {
 console.log('test1 after each');
 });
 
 it('test sum', () => {
 expect(sum(2, 3)).toEqual(5);
 });
 
 it('test mutil', () => {
 expect(sum(2, 3)).toEqual(7);
 });
 
});

断言

  1. expect(value):要测试⼀个值进⾏断⾔的时候,要使⽤expect对值进⾏包裹
  2. toBe(value):使⽤Object.is来进⾏⽐较,如果进⾏浮点数的⽐较,要使⽤toBeCloseTo
  3. not:⽤来取反
  4. oEqual(value):⽤于对象的深⽐较
  5. toMatch(regexpOrString):⽤来检查字符串是否匹配,可以是正则表达式或者字符串
  6. toContain(item):⽤来判断item是否在⼀个数组中,也可以⽤于字符串的判断
  7. toBeNull(value):只匹配null
  8. toBeUndefined(value):只匹配undefined
  9. toBeDefined(value):与toBeUndefined相反
  10. toBeTruthy(value):匹配任何使if语句为真的值
  11. toBeFalsy(value):匹配任何使if语句为假的值
  12. toBeGreaterThan(number): ⼤于
  13. toBeGreaterThanOrEqual(number):⼤于等于
  14. toBeLessThan(number):⼩于
  15. toBeLessThanOrEqual(number):⼩于等于
  16. toBeInstanceOf(class):判断是不是class的实例
  17. anything(value):匹配除了null和undefined以外的所有值
  18. resolves:⽤来取出promise为fulfilled时包裹的值,⽀持链式调⽤
  19. rejects:⽤来取出promise为rejected时包裹的值,⽀持链式调⽤
  20. toHaveBeenCalled():⽤来判断mock function是否被调⽤过
  21. toHaveBeenCalledTimes(number):⽤来判断mock function被调⽤的次数
  22. assertions(number):验证在⼀个测试⽤例中有number个断⾔被调⽤
  23. extend(matchers):⾃定义⼀些断⾔

方法

  1. simulate(event, mock):模拟事件,⽤来触发事件,event为事件名称,mock为⼀个event object
  2. instance():返回组件的实例
  3. find(selector):根据选择器查找节点,selector可以是CSS中的选择器,或者是组件的构造函数,
    组件的display name等
  4. at(index):返回⼀个渲染过的对象
  5. get(index):返回⼀个react node,要测试它,需要重新渲染
  6. contains(nodeOrNodes):当前对象是否包含参数重点 node,参数类型为react对象或对象数组
  7. text():返回当前组件的⽂本内容
  8. html(): 返回当前组件的HTML代码形式
  9. props():返回根组件的所有属性
  10. prop(key):返回根组件的指定属性

E2E测试

借⽤浏览器的能⼒,站在⽤户测试⼈员的⻆度,输⼊框,点击按钮等,完全模拟⽤户,这个和具体的框架关系不⼤,完全模拟浏览器⾏为.

也被称为端到端测试,启动之后会启动一个类似于浏览器的窗口自动执行,因为需求变更等原因,E2E代码测试编码多,甚至可能为了测试一行代码需要写十行测试代码,针对多变的场景不适合,最多针对登录管理等功能固定的页面可以写一些E2E测试。

对比单元测试:单元测试针对vue甚至可以针对到单一组件,更具象,所以一般只是写单元测试。

修改e2e/spec/test.js

// https://docs.cypress.io/api/introduction/api.html
describe('端到端测试,抢测试⼈员的饭碗', () => {
 it('先访问⼀下', () => {
 cy.visit('/')
 // cy.contains('h1', 'Welcome to Your Vue.js App')
 cy.contains('#message', '开课吧')
 })
})
7.jpg

可以看到是打开了⼀个浏览器进⾏测试

测试⽤户点击

// https://docs.cypress.io/api/introduction/api.html
describe('端到端测试,抢测试⼈员的饭碗', () => {
 it('先访问⼀下', () => {
 cy.visit('/')
 // cy.contains('h1', 'Welcome to Your Vue.js App')
 cy.contains('#message', '开课吧')
 cy.get('button').click()
 cy.contains('#message', '按钮点击')
 })
})

TDD

所以TDD 就是测试驱动开发模式,就是我们开发⼀个新功能,先把测试写好,然后测试跑起来,会报错,我们再开始写代码,挨个的把测试跑绿,功能也就完成了

React 自动化测试

React中,也是使⽤jest来做⾃动化测试

https://jestjs.io/docs/en/tutorial-react

总结

测试会极大拖慢开发进度,但是如果测试一旦也写好。例如单元测试,在package.json文件中配置了,则每次保存或者构建之前都会执行一下测试的函数,例如写了add函数,多成员开发,B修改了该函数,则测试不通过,连项目都跑不起来,则保证了项目的健壮性。

代码地址:https://gitee.com/zengqiang_455/qianduanzidonghuaceshixiaodemo

相关文章

网友评论

      本文标题:前端自动化测试

      本文链接:https://www.haomeiwen.com/subject/waqxzhtx.html