NutUI 3.0 中单元测试的探索和实践

发表于:2020-3-11 13:36

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

 作者:宋成林    来源:京东设计中心

分享:
  众所周知,单元测试功能,是组件库开发中必不可少的一部分,负责进行检查和验证,保证了组件的合理性和规范性。本文主要讲的就是单元测试在 NUTUI 组件库 中的探索实践,我们将从如何编写单元测试、持续集成服务、Coveralls 自动测试代码覆盖率三方面进行阐述。如图所示:
  
  如果你对这些内容感兴趣,就和我一起来看一下吧!
  单元测试配置
  在进入单元测试配置正文之前,我们先来了解下面两个问题。
  – 单元测试是什么?
  – 为什么需要单元测试?
  单元测试是什么?
  单元测试(unit testing),可以对软件中的最小可测试单元进行检查和验证,是软件开发中重要的一部分。它使得添加新功能和追踪问题更加容易。
  为什么需要单元测试?
  单元测试在开发的时候很有用,即能帮助开发者思考如何设计一个组件,也能够重构一个现有组件。每次代码发生变化的时候它们都会被运行。有了单元测试,我们可以自信的交付自己的代码,而没有任何的后顾之忧。
  组件的单元测试有以下等优点:
  * 提供描述组件行为的文档
  * 减少调试时间,节省手动测试的时间
  * 减少研发新特性时产生的 bug,测出功能的隐藏 bug
  * 减少和快速定位 bug
  * 促进重构,保证代码重构的安全性
  如何编写单元测试?
  我们既是单元测试的受益者,同时也是开发者,接下来我们进入正题,来聊一聊,如何在 vue 组件库中,加入单元测试。
  单元测试用到的工具大致分为三部分:测试框架、测试运行器、断言库。
  测试框架
  因为我们是 vue 组件库,所以使用 Vue Test Utils 作为测试框架,它是 Vue 组件单元测试的官方库,有详细的指引和自定义设置用于测试,文档清晰,容易上手。
  我们将其作为开发依赖安装在项目中:
  npm install --save-dev @vue/test-utils
  它依赖浏览器环境,可以运行在真实的浏览器或是 Node 虚拟浏览器中,因为在不同的平台上启动真实的浏览器是比较复杂的。所以我们让其运行在 Node 虚拟浏览器中,这就需要借助 JSDOM 帮助我们让它在 Node 虚拟浏览器环境运行测试。
  我们把 JSDOM 做为开发依赖安装:
  npm install --save-dev jsdom jsdom-global
  然后在项目根目录创建 /test 的空文件夹,创建 setup.js 文件
  require('jsdom-global')()
  在测试入口处使用 jsdom-global 手动设置 JSDOM 即可。这样每次运行单元测试都会执行 setup.js 文件,从而引入 JSDOM。
  测试运行器
  测试运行器(test runner)就是运行测试的程序。测试运行器很多,Vue Test Utils 基本上可以支持主流 JavaScript 测试运行器。比较好的是,Vue Test Utils 帮我们筛选了一遍,推荐了两个测试运行器给我们,我们从中选择一个即可,
  · Jest: 功能最全的测试运行器。它所需的配置是最少的,默认安装了 JSDOM,内置断言且命令行的用户体验非常好。
  · mocha-webpack: webpack + Mocha 的包裹器,包含顺畅的接口和侦听模式。
  测试单文件组件的策略是通过 webpack 编译所有的测试文件,然后在测试运行器中运行,使用 mocha-webpack 好处在于我们能够通过 webpack + vue-loader 得到完整的单文件组件支持,我们不必对源代码做任何妥协,虽然 Jest 也提供了vue-jest 预处理器来处理最常见的单文件组件,但仍不是 vue-loader 100% 的功能。所以我们选用了 mocha-webpack。
  通过 npm 安装 mocha、mocha-webpack:
  npm install --save-dev mocha mocha-webpack
  需要注意的是,mocha-webpack 依赖 webpack 和 mocha,并且对版本有要求 webpack 版本需要4.x.x,mocha 版本为4.x.x & 5.x.x。
  断言库
  我们使用 mocha 进行测试的时候,需要结合断言库去使用,Mocha 不像 Jest 框架一样有内置的断言库。它允许我们自己选择合适的断言库。expect 是一款断言库,它极简的 BDD 风格,得到很多测试框架的认可,这些测试框架内置的也是 expect 断言库,因此我们本次也使用了 expect 断言库。
  首先安装开发依赖:
  $ npm install --save-dev expect
  并在 test/setup.js 中写入:
  global.expect = require('expect')
  令其全局可用,这样就不需要在每个测试文件里导入它了。
  安装好了各种开发依赖之后,在根目录 package.json 文件中定义定义一个 npm 脚本 test 命令
{
    ...
    "scripts": {
        ...
        "test": "cross-env NODE_ENV=test mocha-webpack --webpack-config dist_cli/webpack/test.config.js  --require dist_cli/test/setup.js src/packages/*/__test__/**.spec.js"
    },
    ...
}
  值得注意的是,如果项目没有安装 cross-env,需要先安装一下,它用于跨平台设置环境变量。
  简单来了解一下 test 命令参数的含义:
  * –webpack-config:指定了该测试使用的 webpack 配置文件。
  * –require:确保了文件 test/setup.js 会在任何测试之前运行,这样我们可以在该文件中设置测试所需的全局环境。
  * 最后一个参数 src/ 目录:是该测试包所涵盖的所有测试文件的集合。
  准备好以上环境,在命令行执行 npm test 就可以执行测试。
  效果如下:
  最基本的单元测试已经配置完成,但我们的工作还没有结束,继续往下看
  增加单元测试代码覆盖率
  覆盖率既是度量测试完整性的一个手段,也是测试有效性的一个度量。测试覆盖是对测试完全程度的评测。
  Mocha 是 JavaScript 项目的测试工具,Istanbul 是 JS 测试覆盖率报告的生成工具。我们利用二者测试代码并生成代码库的测试覆盖率报告。
  nyc 是 Istanbul 的命令行接口,我们将其作为开发依赖安装在项目中:
$ npm install --save-dev nyc
  然后在上面的 npm 脚本增加 nyc
{
    ...
    "scripts": {
        ...
        "test": "cross-env NODE_ENV=test nyc mocha-webpack --webpack-config dist_cli/webpack/test.config.js  --require dist_cli/test/setup.js src/packages/*/__test__/**.spec.js"
    },
    ...
}
  同时需要在的 package.json 中配置 nyc:
{
    ...
    "nyc": {
    "include": [
        "../../../src/packages/**/*.vue"
    ],
    "reporter": [
        "lcov",
        "text"
    ],
    "instrument": false,
    "sourceMap": false
    },
    ...
}
  介绍一下参数的含义:
  · include: 测试文件路径
  · reporter: 输出 lcov (lcov.info + html 报告)和文本形式的覆盖率报告
  · instrument 和 sourceMap: 设置为 false,禁用 nyc 去 instrumenting 和 sourceMap 你的代码,后续我们指定 loader 去完成。
  这时我们运行 npm test 命令, 就可以获得代码库的测试覆盖率报告。
  如图所示,出现了多个 Unknow,显然还有一些问题,需要安装一下 istanbul-instrumenter-loader,然后把 loader 加到我们的 test.config.ts 的配置文件中。再把生成环境的配置文件 package.conf.ts 导入 merge 进去。
import { packageConfig } from './package.config';
import merge from 'webpack-merge';
module.exports =  merge(packageConfig(false), {
    module: {
        rules: [
            {
                test: /\.(js|ts)/,
                use: {
                    loader: 'istanbul-instrumenter-loader',
                    options: { esModules: true }
                },
                include: [ROOT_PACKAGE_PATH('src/packages')]
            },
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader', 
                ]
            },
            {
                test: /\.scss$/,
                use: [
                    'style-loader',
                    'css-loader',
                    {
                        loader: 'sass-loader',
                        options: { 
                            prependData: `@import "@/styles/index.scss"; `
                        }
                    }
                ]
            }
        ],
    },
    devtool: 'inline-cheap-module-source-map',
    externals: [require('webpack-node-externals')()] // 忽略node_modules文件夹中的所有模块
});
  至此,整个项目的代码覆盖率统计配置基本完成,值得注意的是 istanbul-instrumenter-loader 需要放在最上面,保证它最后执行,这时我们在终端执行 npm test 会显示测试覆盖率结果。


本文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
21/212>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

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

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

沪ICP备05003035号

沪公网安备 31010102002173号