资讯专栏INFORMATION COLUMN

前端组件的测试

haobowd / 1737人阅读

摘要:的配置文件是为了解析那些需要测试的源文件相关的文件,然后再给的单元测试用例去识别。其作用是仅仅渲染至虚拟节点,不会返回真实的节点,能极大提高测试性能。

为解放劳动力,发展生产力

测试有了这般变化:

鼠标点击手动测试 -> 用脚本模拟,自动化测试

Vue中的组件测试 需要安装的包

全局安装:babel、mocha、karma

其他局部安装的包在下面的【测试环境搭建】最下方配置文件中给出

测试环境搭建

配置主要是两个,一是 karma 的配置文件,另一个是 karma 需要的webpack 配置文件。

webpack 的配置文件是为了解析那些需要测试的源文件(vue 相关的文件),然后再给karma 的单元测试用例去识别。

webpack3 配置文件
var path = require("path")
var webpack = require("webpack")
var ExtractTextPlugin = require("extract-text-webpack-plugin")

function resolve(dir) {

    return path.join(__dirname, "..", dir)
}

var webpackConfig = {

    module: {

        rules: [

            // babel-loader
            {
                test: /.js$/,
                use: "babel-loader",
                include: [resolve("src"), resolve("test")]
            },

            // 为了统计代码覆盖率,对 js 文件加入 istanbul-instrumenter-loader
            {
                test: /.(js)$/,
                exclude: /node_modules/,
                include: /src|packages/,
                enforce: "post",
                use: [{
                    loader: "istanbul-instrumenter-loader",
                    options: {
                        esModules: true
                    },
                }]
            },

            // vue loader
            {
                test: /.vue$/,
                use: [{
                    loader: "vue-loader",
                    options: {
                        // 为了统计代码覆盖率,对 vue 文件加入 istanbul-instrumenter-loader
                        preLoaders: {
                            js: "istanbul-instrumenter-loader?esModules=true"
                        }
                    }
                }]
            },

            // css loader
            {
                test: /.css$/,
                use: ExtractTextPlugin.extract({
                    use: "css-loader",
                    fallback: "vue-style-loader"
                })
            },

            // img loader
            {
                test: /.(png|gif|jpe?g)(?S*)?$/,
                use: [{loader: "url-loader"}]
            },

            // font loader
            {
                test: /.(eot|woff|woff2|ttf|svg)(?S*)?$/,
                use: [{loader: "url-loader"}]
            },
        ]
    },

    resolve: {
        extensions: [".js", ".vue", ".json"],
        alias: {
            "vue$": "vue/dist/vue.esm.js",
            "@": resolve("src"), // 调用组件的时候方便点
        }
    },

    plugins: [
        new webpack.DefinePlugin({
            "process.env": {
                NODE_ENV: ""production""
            }
        })
    ]
}

module.exports = webpackConfig
karma配置文件

有两种方法:

cd进入当前项目,使用 karma init命令,然后一系列提示选择...

不用 karma init命令,新建一个karma.conf.js文件,然后配置:

var webpackConfig = require("../../build/webpack.test.config");

module.exports = function (config) {
    config.set({
        // to run in additional browsers:
        // 1. install corresponding karma launcher
        //    http://karma-runner.github.io/0.13/config/browsers.html
        // 2. add it to the `browsers` array below.
        browsers: ["PhantomJS"],
        frameworks: ["mocha", "sinon-chai", "phantomjs-shim"],
        reporters: ["spec", "coverage"],
        files: ["index.js"],
        preprocessors: {
            "./index.js": ["webpack", "sourcemap"]
        },

        webpackMiddleware: {
            noInfo: true
        },
        // 不显示 `webpack` 打包日志信息
        webpackServer: {
            noInfo: true
        },
        webpack: webpackConfig,
        coverageReporter: {
            dir: "./coverage",
            reporters: [
                { type: "lcov", subdir: "." },
                { type: "text-summary" }
            ]
        }
    })
}
目录结构
├─build 
│      webpack.test.config.js
│
├─src 
│
├─package.json
│
└─test 
      └─unit
          │  index.js
          │  karma.config.js
          │
          ├─coverage
          │
          └─specs
               *.spec.js

测试文件相关都放置在 test/unit 下,入口文件为 index.js,每个vue 组件对应的测试用例名为组件名称.spec.js,根据 istanbul-instrumenter-loader 文档的说明,测试总入口文件 index.js 内容如下:

import Vue from "vue"

Vue.config.productionTip = false

// 测试所有以 .spec.js 名称结尾的文件
// require all test files (files that ends with .spec.js)
const testsContext = require.context("./specs", true, /.spec$/)
testsContext.keys().forEach(testsContext)

// 要求除main.js之外的所有src文件进行覆盖
// require all src files except main.js for coverage.
// you can also change this to match only the subset of files that
// you want coverage for.
const srcContext = require.context("../../src", true, /^./(?!main(.js)?$)/)
srcContext.keys().forEach(srcContext)
最后看下package.json的devDependencies
"devDependencies": {

    ...

    "babel-core": "^6.9.0",
    "babel-loader": "^7.1.1",
    "babel-plugin-syntax-jsx": "^6.18.0",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-plugin-transform-vue-jsx": "^3.3.0",
    "babel-polyfill": "^6.26.0",
    "babel-preset-env": "^1.6.0",
    "babel-preset-es2015": "^6.18.0",
    "babel-preset-stage-2": "^6.18.0",
    "babel-runtime": "^6.18.0",
    "chai": "^4.1.2",
    "chalk": "^2.0.1",
    "css-loader": "^0.28.4",
    "extract-text-webpack-plugin": "^2.1.2",
    "istanbul-instrumenter-loader": "^3.0.0",
    "karma": "^1.7.1",
    "karma-coverage": "^1.1.1",
    "karma-mocha": "^1.3.0",
    "karma-phantomjs-launcher": "^1.0.4",
    "karma-phantomjs-shim": "^1.4.0",
    "karma-sinon-chai": "^1.3.2",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-spec-reporter": "0.0.31",
    "karma-webpack": "^2.0.4",
    "mocha": "^3.5.0",
    "phantomjs-prebuilt": "^2.1.15",
    "postcss-px2rem": "^0.3.0",
    "sinon": "^3.2.1",
    "sinon-chai": "^2.13.0",

    ...

    "style-loader": "^0.18.2",
    "url-loader": "^0.5.7",
    "vue-loader": "^13.0.4",
    "vue-router": "^2.7.0"
  },

执行命令 sudo npm install 安装所需要的包

注意:

当流程走到下面这个步骤时,可能耗费的时间比较长,千万别ctrl + c中断下载重新install,静静等待就好

开始测试

新建一个Hello.vue组件

 
 

test/unit/specs 目录下创建一个 Hello.spec.js 文件,再写个简单的单元测试用例:

import Vue from "vue"
import Hello from "@/components/Hello"

describe("Hello.vue", () => {
  it("should render correct contents", () => {
    const Constructor = Vue.extend(Hello)
    const vm = new Constructor().$mount()
    expect(vm.$el.querySelector(".hello h1").textContent)
      .to.equal("Welcome to Your Vue.js App")
  })
})

package.json文件配置:

  // package.json
  "scripts": {
     "test": "karma start test/unit/karma.config.js --single-run"
   }

执行npm run test输出测试结果,同时在 test/unit/coverage 生成测试报告。

一些测试的Case

网上的例子...

点我点我点我

再点我点我点我

React中的组件测试 Jest + Enzyme

Jest:JS单元测试工具,包含DOM API 支持、断言库、Mock 库等,还包含了 Spapshot Testing、 Instant Feedback 等特性

Enzyme:通过 jQuery 风格的方式进行DOM 处理,开发体验十分友好

测试环境搭建 1. 安装一些包
npm install jest enzyme babel-jest --save-dev
2. 在package.json中配置jest:
"jest": {
    "moduleFileExtensions": [
      "js",
      "jsx"
    ],
    "moduleNameMapper": {
      ".(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/__mocks__/fileMock.js",
      ".*.(css|less|scss)$": "/__mocks__/styleMock.js"
    },
    "transform": {
      "^.+.js$": "babel-jest"
    }
  },
3. 新增启动测试的脚本:
"scripts": {
    "test": "jest"
  }
开始测试 1. 引入
import { shallow } from "enzyme"

Enzyme 提供了三种方法

shallow:浅渲染。其作用是仅仅渲染至虚拟节点,不会返回真实的节点,能极大提高测试性能。但是它不适合测试包含子组件、需要测试声明周期的组件

mount:Full Rendering,非常适用于存在于 DOM API 存在交互组件,或者需要测试组件完整的生命周期

render:Static Rendering,用于 将 React 组件渲染成静态的 HTML 并分析生成的 HTML 结构

一般情况下,shallow 就已经足够用了,偶尔情况下会用到 mount。

2. 模拟
const setup = () => {
  // 模拟 props
  const props = {
    // Jest 提供的mock 函数
    onAddClick: jest.fn()
  }

  // 通过 enzyme 提供的 shallow(浅渲染) 创建组件
  const wrapper = shallow()
  return {
    props,
    wrapper
  }
}
3. 编写Test Case

Case1::测试组件是否正常渲染

describe("AddTodoView", () => {
  const { wrapper, props } = setup();

  // case1
  // 通过查找存在 Input,测试组件正常渲染
  it("AddTodoView Component should be render", () => {
    //.find(selector) 是 Enzyme shallow Rendering 提供的语法, 用于查找节点
    // 详细用法见 Enzyme 文档 http://airbnb.io/enzyme/docs/api/shallow.html
    expect(wrapper.find("input").exists());
  })
})

Case2:输入内容并敲下回车键,测试组件调用props的方法

it("When the Enter key was pressed, onAddClick() shoule be called", () => {
    // mock input 输入和 Enter事件
    const mockEvent = {
      keyCode: 13, // enter 事件
      target: {
        value: "Test"
      }
    }
    // 通过 Enzyme 提供的 simulate api 模拟 DOM 事件
    wrapper.find("input").simulate("keyup",mockEvent)
    // 判断 props.onAddClick 是否被调用
    expect(props.onAddClick).toBeCalled()
  })
生成报告

Jest 还提供了生成测试覆盖率报告的命令,只需要添加上 --coverage 这个参数既可生成

 "scripts": {
    "coverage": "jest --colors --coverage"
  }
写在最后

难点是要考虑周全,测试用例覆盖全面

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93231.html

相关文章

  • 本命年一定要记得穿红裤衩:2015年总结

    摘要:年终总结结果到这个时间才写,其实也是无奈。这一年最重要的事情就是顺利从一只学生狗转职为一只社畜。四月份毕业之后以前端工程师的职位入职天猫,到现在也差不多工作一年了。 年终总结结果到这个时间才写,其实也是无奈。本来计划过年写的,没想到Steam竟然开了个农历春节特惠,然后就被各种游戏打了,辣鸡平台,敛我钱财,颓我精神,耗我青春,害我单身 以下全都是个人看法,如果有不认同的地方,请大吼一声...

    AlienZHOU 评论0 收藏0
  • 本命年一定要记得穿红裤衩:2015年总结

    摘要:年终总结结果到这个时间才写,其实也是无奈。这一年最重要的事情就是顺利从一只学生狗转职为一只社畜。四月份毕业之后以前端工程师的职位入职天猫,到现在也差不多工作一年了。 年终总结结果到这个时间才写,其实也是无奈。本来计划过年写的,没想到Steam竟然开了个农历春节特惠,然后就被各种游戏打了,辣鸡平台,敛我钱财,颓我精神,耗我青春,害我单身 以下全都是个人看法,如果有不认同的地方,请大吼一声...

    xi4oh4o 评论0 收藏0
  • 如何构建大型前端项目

    摘要:如何构建大型的前端项目搭建好项目的脚手架一般新开发一个项目时,我们会首先搭建好一个脚手架,然后才会开始写代码。组件化一般分为项目内的组件化和项目外的组件化。 如何构建大型的前端项目 1. 搭建好项目的脚手架 一般新开发一个项目时,我们会首先搭建好一个脚手架,然后才会开始写代码。一般脚手架都应当有以下的几个功能: 自动化构建代码,比如打包、压缩、上传等功能 本地开发与调试,并有热替换与...

    lykops 评论0 收藏0
  • 如何构建大型前端项目

    摘要:如何构建大型的前端项目搭建好项目的脚手架一般新开发一个项目时,我们会首先搭建好一个脚手架,然后才会开始写代码。组件化一般分为项目内的组件化和项目外的组件化。 如何构建大型的前端项目 1. 搭建好项目的脚手架 一般新开发一个项目时,我们会首先搭建好一个脚手架,然后才会开始写代码。一般脚手架都应当有以下的几个功能: 自动化构建代码,比如打包、压缩、上传等功能 本地开发与调试,并有热替换与...

    plokmju88 评论0 收藏0
  • 前端架构涉及到哪些范围?

    摘要:前后端都要关注注入攻击跨站脚本攻击跨站请求伪造开放重定向这些安全性问题。前端也需要构建自动化测试,包括独立单元测试和端到端测试自动化,当然还有人工测试。 总体指导思想是前后端分离,后端同事提供线上API数据查询接口或websocket接口,前端同事负责处理获取到的数据、编写展示的页面、实现用户交互;前后端都要考虑web开发的安全性问题,表单提交到数据库前对用户的输入进行转义、登录避免明...

    dmlllll 评论0 收藏0

发表评论

0条评论

haobowd

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<