vue组件测试用例实践一(搭建vue测试框架)

发表于:2017-7-24 11:27

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:wupengyu    来源:51Testing软件测试网采编

  思考组件测试的意义
  非组件不好测的原因
  前端自动化测试一直是被忽略的,当然很大部分原因可能是因为人手不足,但是当我们从技术的角度来看,更主要的是因为前端测试用例的复杂性。首先从样式上来说,首先是变化可能很频繁,而且样式测试本身意义就不是很大。其次,在传统的jquery框架中,其大部分方法是需要依赖上下文的,而且这样的方法可能有很多,每个页面都要单独的测试实在是费时费力,付出和收获实在不成正比。
  组件测试的必要
  在当前最火的两个前端框架中(vue&react)其最突出的且最优秀的特性当属组件化了,通过组件化做到代码分离,不至于每个页面都包含了冗长的js,使重构和debug都变得很容易。通过组件的重用减少代码量,大幅度的提升了开发效率。
  那么,问题来了,当我们写了一个公用组件的时候,可能会有很多个父组件都用到了这个组件,当我们因为某一个新需求或者重构的时候需要更改这组件的时候,如何保证所有用到这个组建的地方都不会出问题呢?作为一个懒懒的程序猿我是拒绝去one by one查看每一个页面的。而且这样很容易就忽略了某些细节的地方,实在是不靠谱。
  通过对公用组件的所有特性进行测试用了覆盖,只要测试用例写的足够合理且健壮,完全不必担心上面的问题。
  搭建vue组件测试框架
  概述
  参考vue官方的例子,先列出所用到的技术我们会用到:
      1.karma 该工具可用于测试所有主流Web浏览器,也可集成到CI(Continuous integration)工具,也可和其他代码编辑器一起使用。
      2.mocha 前端测试框架,支持node和浏览器端,断言库自由化,注意mocha只提供了测试套件,具体的断言工具还需要在挑选,这里我们选用chai
      3.chai 断言库,提供了should,expect,assert多种断言。
      4.istanbul javascript代码覆盖率工具,用来导出代码覆盖率数据。
  需要安装的包
      1.karma //test runner,提供测试所需的浏览器环境、监测代码改变自动重测、整合持续集成等功能
      2.phantomjs-prebuilt //phantomjs,在终端运行的浏览器虚拟机
      3.mocha //test framework,测试框架,运行测试
      4.chai //assertion framework, 断言库,提供多种断言,与测试框架配合使用
      5.sinon //测试辅助工具,提供 spy、stub、mock 三种测试手段,帮助捏造特定场景
      6.karma-webpack //karma 中的 webpack 插件
      7.karma-mocha //karma 中的 mocha 插件
      8.karma-sinon-chai //karma 中的 sinon-chai 插件
      9.sinon-chai //karma 中的 chai 插件
      10.karma-sourcemap-loader //karma 中的 sourcemap 插件
      11.karma-phantomjs-launcher //karma 中的 phantomjs 插件
      12.karma-spec-reporter //在终端输出测试结果
      13.babel-plugin-istanbul //babel插件,es6代码产生instanbul覆盖率
      14.karma-coverage //Karma插件,生成代码覆盖率
  开始
  目录结构
      vue-unit-test
          src
              components
                  Button.vue
              util.js
              main.js
          test
              unit-util.spec.js
                  Button.spec.js
                  index.js
          .babelrc
          karma.conf.js
          package.json
      其中test目录用来存放所有的测试相关代码,src作为待测试的目录包括js文件和vue组件。
  配置karma.conf.js文件
  karma.conf.js作为测试的入口文件可以说是整个测试框架的核心部分,我们主要要讲的也是关于这个文件的配置。首先在package.json文件中写入执行脚本
   "scripts": {
      
      "test": "BABEL_ENV=browse karma start karma.conf.js" // 指定karam运行的文件,其中"BABEL_ENV=browse"指定babel的env,在env===browse的情况下我们才会用bable加载istanbul插件,
    }
  karma.conf.js文件详解
  在当前目录下执行karma init命令,之后选择mocha,no require.js, 选择浏览器PhantomJS,默认目录"test/*/Spec.js"。随后会在当前目录下生成一个原始的karma.conf.js文件,我们会在这个文件的基础上进行配置。
  当然我们也可以不用karma init命令,直接在当前目录下新建karma.conf.js文件进行配置也是可以的。
  karma.conf.js
  module.exports = function(config) {
    config.set({
      frameworks: ['mocha', 'sinon-chai'],
      // 测试入口文件
      files: ['./test/unit/index.js'],
      // 用webpack解析,同时显示测试文件路径
      preprocessors: {
          './test/unit/index.js': ['webpack', 'sourcemap'],
      },
      // 设置测试覆盖率输出插件
      reporters: ['spec', 'coverage'],
      // karma-coverage配置,配置测试覆盖率的输出目录及格式
      coverageReporter: {
        dir: './coverage',
        reporters: [
          { type: 'lcov', subdir: '.'},
          { type: 'text-summary'},
        ]
      },
      colors: true,
      autoWatch: false,
       // 设置默认打开的浏览器
      browsers: ['PhantomJS'],
      //  设置运行完成是否自动退出
      singleRun: false,
      // 是否打印webpack打包信息
      webpackMiddleware: {
        noInfo: true
      },  
      // webpack 配置用来解析js文件和vue文件,如果有css请自行配置css-loader
      webpack: {
        module: {
          loaders: [
            {
              test: /\.js$/,
              loader: 'babel-loader',
              exclude: /node_modules/
            },
            {
              test: /\.vue$/,
              loaders: [{
                loader: 'vue-loader',
              }]
            },
          ]
        },
      }
    })
  }
  test/unit/index.js
  // load 所有的测试用例文件
  const testsContext = require.context('.', true, /\.spec$/)
  testsContext.keys().forEach(testsContext)
  // load 所有的资源文件,及src目录下的除了main.js文件的所有文件, 即要覆盖的所有代码
  const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/)
  srcContext.keys().forEach(srcContext)
  .babelrc文件
  关于babel这里不做详细介绍,只是列出配置,具体用法请自行查阅babel文档
  {
    "presets": [
      ["env", {
        "useBuiltIns": true,
        "targets": {
          "browsers": ["last 3 versions"]
        }
      }]
    ],
    "env": {
      "browse": {
        "plugins": ["istanbul"] // 必须,否则不会产生覆盖率
      }
    }
  }
  编写并运行测试
  我们可以在src/util.js中加一个测试方法跑一下
  export function util1 (name) {
    if (name) {
      return name
    }
    return 'hello'
  }
  在test/unit/utils.spec.js中写出测试用例
  import { util1 } from '../../src/util'
  describe('utils.js', () => {
      it('should return name', () => {
        const name = util1('teapot')
        expect(name).to.equal('teapot')
      })
  })
  运行
  npm test
  在终端可打印出测试覆盖率
  打开生成coverage目录的index.html查看测试覆盖率
  编写组件测试用例
  组件
  <template>
    <button>{{text}}</button>
  </template>
  <script>
    export default {
      data() {
        return {
          text: 'Hello Spec'
        }
      },
      created () {
        this.text = 'Bye Spec'
      }
    }
  </script>
  测试用例
  import Vue from 'vue'
  import SelfButton from '../../src/components/SelfButton.vue'
  describe('SelfButton', () => {
    it('has a created hook', () => {
      expect(typeof SelfButton.created).to.equal('function')
    })
    it('sets the correct default data', () => {
      const defaultData = SelfButton.data()
      expect(defaultData.text).to.equal('Hello Spec')
    })
    it('sets new text when created', () => {
      const vm = new Vue(SelfButton).$mount()
      expect(vm.text).to.equal('Bye Spec')
    })
    it('renders the correct text', () => {
      const Ctor = Vue.extend(SelfButton)
      const vm = new Ctor().$mount()
      expect(vm.$el.textContent).to.equal('Bye Spec')
    })
  })
  关于vue组件的测试用例请参考官方文档
 vue unit testing
  不过文档中关于测试用例的写法其实也很有限,这里我们下次再进行探讨。
  项目源码地址:https://github.com/teapot-py/vue-unit-test
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号