前端单元测试怎么写(以Vue为例)

爱被打了一巴掌 2023-02-21 11:54 78阅读 0赞

单元测试是什么

对软件中的最小可测试单元(一个方法)进行测试

单元测试的意义

1、分模块开发,方便定位到哪个模块出现问题
2、保证了代码质量
3、驱动开发(先写单元测试,通过再写代码)

单元测试两种类型

TDD(测试驱动开发,从需求角度出发)
我需要的结果是什么?如果不是即为错误
针对于数据,面向的是最终的值,适用于开发人员
开发流程:需求分析->编写单元测试->编写代码使单元测试通过->重构

BDD(行为驱动开发,从具体功能角度出发)
结果应该是什么?如果不是即为错误
面向的是最终的产出效果,适用于需求客户人员
开发流程:从业务角度定义目标->找到实现目标的方法->编写单元测试->实现行为->检查产品

单元测试核心内容

测试框架
帮助测试得以运行
Jest-基于Jasmine,对react友好
Jasmine-BDD风格,自带assert和mock(大集成)
Mocha-全面适合node和浏览器两端
Qunit-出自jquery,后来独立出来

断言库(assert)
帮助检查结果
chai-支持所有风格,全面
Assert-node环境直接使用

Mock库
帮助屏蔽方法、数据及相关依赖,避免外部数据对测试产生影响
sinon

test runner
提供运行环境,使得方法能够运行
karma

覆盖率工具
测试比例,明确测试了多少内容
istanbul

单元测试组成部分

在这里插入图片描述

测试人员与前端单元测试工作区别

测试用例(测试人员编写)
为了某个特殊目标而编织的一系列测试输入,执行以及输出结果,来测试是否满足需求
单元测试(前端编写)

以Vue为实例编写单元测试

1、脚手架安装项目,选择单元测试
在这里插入图片描述
2、生成目录如下
在这里插入图片描述
karma.conf.js配置文件说明

  1. var webpackConfig = require('../../build/webpack.test.conf')
  2. module.exports = function karmaConfig (config) {
  3. config.set({
  4. //模拟环境
  5. browsers: ['PhantomJS'],//无头浏览器,不属于任何厂家,单纯的一个javascript执行环境
  6. //所用到的各种库,mocha框架,sinon-chai断言库
  7. frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'],
  8. //覆盖率暴露到哪里
  9. reporters: ['spec', 'coverage'],
  10. //需要加载到浏览器的文件
  11. files: ['./index.js'],
  12. //使用前的处理
  13. preprocessors: {
  14. './index.js': ['webpack', 'sourcemap']
  15. },
  16. webpack: webpackConfig,
  17. webpackMiddleware: {
  18. noInfo: true
  19. },
  20. //指定报告输出的类型和目录
  21. coverageReporter: {
  22. dir: './coverage',
  23. reporters: [
  24. { type: 'lcov', subdir: '.' },
  25. { type: 'text-summary' }
  26. ]
  27. }
  28. })
  29. }

index.js文件说明

  1. import Vue from 'vue'
  2. Vue.config.productionTip = false
  3. //require.context将指定路径下所有符合规则的文件都引入
  4. const testsContext = require.context('./specs', true, /\.spec$/)
  5. testsContext.keys().forEach(testsContext)
  6. //业务代码引入
  7. const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/)
  8. srcContext.keys().forEach(srcContext)

3、编写单元测试
.spec.js文件下编写单元测试

  1. import Vue from 'vue'
  2. import HelloWorld from '@/components/HelloWorld'
  3. import axios from 'axios'
  4. import { expect } from 'chai'
  5. //整个组件测试描述
  6. describe('HelloWorld.vue', () => {
  7. //拿到当前组件的构造函数
  8. const Constructor = Vue.extend(HelloWorld)
  9. //挂载,模拟渲染过程
  10. const vm = new Constructor().$mount()
  11. //每一个it就是对于一个方法的单元测试
  12. //描述测试
  13. it('should render correct contents', () => {
  14. expect(vm.$el.querySelector('.hello h1').textContent)
  15. .to.equal('Welcome to Your Vue.js App')
  16. })
  17. //检测一个方法
  18. it('m1 should add two arguments', () => {
  19. const m1 = vm.m1
  20. expect(m1(2, 3)).to.equal(5)
  21. })
  22. //检测数据更新
  23. it('should change correct content', () => {
  24. vm.m2();
  25. //需要等到页面加载完毕,再去进行数据更改
  26. Vue.nextTick(()=>{
  27. expect(vm.$el.querySelector('.hello h1').textContent)
  28. .to.equal('123')
  29. })
  30. })
  31. //检测异步方法
  32. it('async m3 should return 6', () => {
  33. vm.m3(2, 4, (num) => {
  34. expect(num).to.equal(6)
  35. })
  36. })
  37. //检测接口请求
  38. it('api request', () => {
  39. //屏蔽真正的请求
  40. let axiosstub = sinon.stub(axios,'get')
  41. //提供模拟真正请求的数据
  42. let callback = sinon.spy(() => {
  43. return 5
  44. })
  45. const getmes = vm.getmes
  46. const finalData = getmes(callback)
  47. expect(finalData).to.equal(4)
  48. })
  49. })

组件内编写方法

  1. <script>
  2. import axios from 'axios'
  3. export default {
  4. name: 'HelloWorld',
  5. data () {
  6. return {
  7. msg: 'Welcome to Your Vue.js App'
  8. }
  9. },
  10. methods:{
  11. m1(a,b){
  12. return a+b
  13. },
  14. m2(){
  15. this.msg = 123
  16. },
  17. m3(a, b, cb){ //入侵一个cb
  18. setTimeout(()=>{
  19. cb(a + b)
  20. }, 2000)
  21. },
  22. getmes(cb){
  23. axios.get('/aaa/bbb')
  24. let res = cb()
  25. res-=1
  26. return res
  27. }
  28. }
  29. }
  30. </script>

4、npm run unit进行检测
在这里插入图片描述

注意

如果选择了jest,配置文件里需要修改,否则无法启动命令,其他操作相同。
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,78人围观)

还没有评论,来说两句吧...

相关阅读