Element源码系列——搭建Karma测试环境及Eslint语法检测
Element源码系列——搭建ESlint语法检测及Karma测试环境
先介绍下背景,这件事发生在我们团队的开发过程中,这件事也是我们团队为什么要坚定不移使用Eslint的导火索.事情是这样,项目在稳定版本后进行分支继续开发,新人同事无意中将之前的一个Web Worker文件里的半角)
改成了圆角)
,Webpack编译一直报错并无法定位到错误,只能一片一片代码去注释来定位错误,而修复这个问题他至少耽误了1个小时。
客观的来说,这虽然是他个人粗心的问题,但谁又能保证自己不犯错呢?但是,随着团队人员的加入,代码量的递增,那么维护的成本将会越来越高,这时候,语法检测和单元测试的引入绝对是开发过程中的一大助力。
话不多说,下面让我们来看看Element-ui的语法检测与测试环境
- Element源码系列——搭建ESlint语法检测及Karma测试环境
- ESlint语法检测
- ESlint有三种方式配置:
- 安装的ESlint依赖包
- 打开eslint-config-elemefe文件
- 配置IDE的ESlint环境
- 小结
- Karma测试环境
- 安装依赖包
- 项目结构
- 编写babel配置文件
- 编写webpack配置文件
- 编写Karma配置文件
- 编写需要测试的文件以及测试用例
- 配置package.json的script命令
- 总结
- ESlint语法检测
ESlint语法检测
ESlint有三种方式配置:
1.package.json中eslintConfig字段
2.项目根目录的.eslintrc文件
3.命令行配置文件
这里我们使用的第二种方式实现,并且也继承element-ui团队的规范。项目根目录新建.eslintrc文件
,代码如下:
# .eslintrc文件
{"env": {"mocha": true # 添加所有的Mocha测试全局变量},"globals": {"expect": true, # 允许以下两个全局变量被重写"sinon": true},"plugins": ["html", "json"], # 使用"eslint-plugin-html"和"eslint-plugin-json"两个插件"extends": "elemefe", # 继承”eslint-config-elemefe“的rules 可以省略掉eslint-config-部分"rules": { "no-restricted-globals": ["error", "event", "fdescribe"] # 禁用特定的全局变量},"parserOptions": {"ecmaFeatures": { # 表示你想使用的额外的语言特性"experimentalObjectRestSpread": true,"jsx": true}}
}
我们也可以添加.eslintignore文件来排除一些不需要进行语法检查的文件
# .eslintignore文件*.sh
node_modules
*.md
*.scss
*.woff
*.ttf
coverage
安装的ESlint依赖包
通过分析配置文件,我们可以得出至少需要如下依赖:
"devDependencies": {"eslint": "4.14.0","eslint-config-elemefe": "0.1.1","eslint-loader": "^1.9.0","eslint-plugin-html": "^4.0.1","eslint-plugin-json": "^1.2.0"}
在安装完成依赖后,实际上ESlint环境已经搭建完成了。但是为了提高我们的效率还需要再做几件事。
打开eslint-config-elemefe文件
为了以后语法检测可以更快的定位错误 ,我们还是看看写了什么吧。
const rules = require('./rules'); // 引用规则文件module.exports = { 'root': true, // ESlint会在所有父级目录里寻找配置文件,一直到根目录,一旦发现 'root': true 时就会停止在父类寻找'env': {'browser': true, // 浏览器环境中的全局变量'node': true, // Node.js 全局变量和 Node.js 作用域。'amd': false, // 禁止将 require() 和 define() 定义为像 amd 一样的全局变量'mocha': false, // 禁止添加所有的 Mocha 测试全局变量'jasmine': false // 禁止添加所有的 Jasmine 版本 1.3 和 2.0 的测试全局变量},'parserOptions': {ecmaVersion: 6, // 默认设置为3,5(默认)sourceType: 'module', // ECMAScript 模块'ecmaFeatures': {'experimentalObjectRestSpread': true,'jsx': true}},rules: rules // 引用规则文件
};
rules文件我们就不分析了,所有的语法规则都在这里,需要研究的可以参照。
配置IDE的ESlint环境
由于每个用的IDE各不相同,我只简单的介绍一下Sublime Text 3下的ESlint插件,如果需要配置细节可自行搜索。
插件的话我常用的为ESlint-Formatter
和SublimeLinter
一个是修改,一个是提示。具体配置在这里就不过多介绍了
小结
在完成以上配置后,当编写代码时出现语法规则上的错误时,Sublime就会有提示
如果需要修复问题的话,只需要使用ESlint-Formatter
的快捷键ctrl+shift+h
修复即可,如果无法通过快捷键修复的问题的可以对应语法规则一一修改,在熟练掌握之后,相信代码质量绝对能有显著的提高的。
Karma测试环境
Karma是由Google团队开发的一套前端测试运行框架,它需要与mocha等测试框架共同使用。而根据所测试的不同语言以及拓展语言安装所对应的插件,最后通过Webpack构建工具的各种loader进行整合打包,最终生成测试覆盖率报告
安装依赖包
# package.json"dependencies": {"normalize-wheel": "^1.0.1"},"peerDependencies": {"vue": "^2.5.2"},"devDependencies": {"babel-core": "^6.26.3","babel-loader": "^7.1.5", "babel-plugin-add-module-exports": "^0.2.1","babel-plugin-module-resolver": "^3.1.1","babel-plugin-syntax-jsx": "^6.18.0","babel-plugin-transform-vue-jsx": "^3.7.0","babel-preset-es2015": "^6.24.1","chai": "^4.1.2","cross-env": "^5.2.0","css-loader": "^1.0.0","html-loader": "^0.5.5","isparta-loader": "^2.0.0","json-loader": "^0.5.7","karma": "^2.0.4","karma-chrome-launcher": "^2.2.0","karma-coverage": "^1.1.2","karma-mocha": "^1.3.0","karma-sinon-chai": "^2.0.2","karma-sourcemap-loader": "^0.3.7","karma-spec-reporter": "0.0.32","karma-webpack": "^3.0.0","mocha": "^5.2.0","postcss-loader": "^2.1.6","progress-bar-webpack-plugin": "^1.11.0","sinon": "^6.1.3","sinon-chai": "^3.2.0","style-loader": "^0.21.0","url-loader": "^1.0.1","vue": "^2.5.2","vue-loader": "^13.3.0","vue-router": "2.7.0","vue-template-compiler": "^2.5.2","vue-template-es2015-compiler": "^1.6.0","webpack": "^3.7.1", # 注意这里使用webpack版本}
项目结构
element-ui├── build //编译配置文件├── node_modules ├── packages // 组件源码目录├── src // 国际化等源码目录├── tset // 测试目录├── util├── specs├── package.json├── .eslintrc├── .babelrc├── .eslintignore├── package-lock.json├── .gitignore
编写babel配置文件
不得不说,ES6的语法糖用起来确实很舒服,而babel的配置又非常简单,babel不火都难!
{"presets": [["es2015", { "loose": true }]], # ES6 loose模式"plugins": ["transform-vue-jsx"], # vue支持jsx语法
}
编写webpack配置文件
karma支持直接引入webpack配置文件,为了后续更好的修改,我们将webpack.test.js建立在build根目录下。
之后在根目录下建立config.js文件
// config.jsvar path = require('path');// 路径别名导出
exports.alias = {main: path.resolve(__dirname, '../src'),packages: path.resolve(__dirname, '../packages'),examples: path.resolve(__dirname, '../examples'),'element-ui': path.resolve(__dirname, '../')
};
// 不进行测试的文件与路径
exports.jsexclude = /node_modules|utils\/popper\.js|utils\/date\.js/;
// webpack.test.jsconst path = require('path');
const ProgressBarPlugin = require('progress-bar-webpack-plugin'); // webpack进度条插件const config = require('./config'); // 引入config.jsconst webpackConfig = {entry: {app: ['./src/index.js'] // 入口文件},output: {path: path.resolve(process.cwd(), './dist'), // 输入文件路径publicPath: '/dist/', // 图片、svg等资源开发路径转为输出路径设置filename: '[name].js', // 对应entry的键名chunkFilename: '[id].js'},resolve: {// 自动解析扩展省略后缀 import File from '../path/to/file'extensions: ['.js', '.vue', '.json'], alias: Object.assign(config.alias, {'vue$': 'vue/dist/vue.common.js'}),modules: ['node_modules']},devtool: '#inline-source-map',module: {rules: [{enforce: 'post', // 首先执行test: /\.jsx?$/,loader: 'isparta-loader', // Karma入口文件解析options: { esModules: true },exclude: config.jsexclude,include: /src|packages/},{test: /\.(jsx?|babel|es6)$/,include: process.cwd(),exclude: config.jsexclude,loader: 'babel-loader'},{test: /\.vue$/,loader: 'vue-loader',options: {loaders: {js: process.env.CI_ENV ? 'isparta-loader' : 'isparta-loader!eslint-loader'},preserveWhitespace: false}},{test: /\.json$/,loader: 'json-loader'},{test: /\.css$/,loader: ['style-loader', 'css-loader', 'postcss-loader']},{test: /\.html$/,loader: 'html-loader?minisize=false'},{test: /\.otf|ttf|woff2?|eot(\?\S*)?$/,loader: 'url-loader',query: {limit: 10000,name: path.posix.join('static', '[name].[hash:7].[ext]')}},{test: /\.svg(\?\S*)?$/,loader: 'url-loader',query: {limit: 10000,name: path.posix.join('static', '[name].[hash:7].[ext]')}},{test: /\.(gif|png|jpe?g)(\?\S*)?$/,loader: 'url-loader',query: {limit: 10000,name: path.posix.join('static', '[name].[hash:7].[ext]')}}]},plugins: []
};if (!process.env.CI_ENV) {webpackConfig.plugins.push(new ProgressBarPlugin());
}module.exports = webpackConfig;
编写Karma配置文件
test => unit 下建立index.js和karma.conf.js
首先是入口文件,参照isparta-loader
// index.js
// Polyfill fn.bind() for PhantomJS
/* eslint-disable no-extend-native */// require all test files (files that ends with .spec.js)
const testsContext = require.context('./specs', true, /\.spec$/);
testsContext.keys().forEach(testsContext);// 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);
其次是karma的配置文件
// karma.conf.jsvar webpackConfig = require('../../build/webpack.test'); // 引入webpack配置文件// 测试时不需要入口文件
delete webpackConfig.entry;module.exports = function(config) {var configuration = {// 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.browser: ['Chrome'],frameworks: ['mocha', 'sinon-chai'], // 使用的测试框架reporters: ['spec', 'coverage'],files: ['./index.js'], // 入口文件preprocessors: {'./index.js': ['webpack', 'sourcemap']},webpack: webpackConfig, // webpack配置文件webpackMiddleware: {noInfo: true // 不开启提示信息},coverageReporter: {dir: './coverage', // 覆盖率生成报告路径reporters: [{ type: 'lcov', subdir: '.' },{ type: 'text-summary' }]},client: {mocha: {timeout: 4000 // 测试超时时间限制}}};config.set(configuration);
};
编写需要测试的文件以及测试用例
package下新建app.vue文件
// app.vue
<template><div><h1>{{ title }}</h1></div>
</template>
<script>export default {data() {return {title: '标题'};},mounted() {this.title = 'Hello World';},methods: {setMessage(msg) {this.message = msg;}}};
</script>
test => unit => specs下建立app.spec.js
// app.spec.js
import Vue from 'vue';
import app from '../../../packages/app.vue';describe('test app.vue', () => {it('组件加载后,title应该是Hello World', () => {let vm = new Vue(app).$mount();expect(vm.title).to.equal('Hello World');});
});
配置package.json的script命令
"scripts": {"lint": "eslint test/**/* packages/**/* --quiet","test": "npm run lint && cross-env CI_ENV=/dev/ karma start test/unit/karma.conf.js --single-run","test:watch": "karma start test/unit/karma.conf.js"},
总结
完成所有配置之后执行npm run test
将开始测试,当编译通过后可以访问 http://127.0.0.1:9876 来查看测试情况,或者在test => unit => coverage => icov-report =>index.html查看覆盖率报告
Element源码系列——搭建Karma测试环境及Eslint语法检测相关推荐
- Element源码系列——Row以及Col组件
Element源码系列--Row以及Col组件 Element源码系列--Row以及Col组件 序言 Row Col 总结 序言 官网中对Layout 布局的定义是: 通过基础的 24 分栏,迅速简便 ...
- linux 源码搭建lnmp_详解CentOS 7.0源码包搭建LNMP 实际环境搭建
Centos7+Nginx1.11.7+MySQL5.7.16+PHP7.1.0+openssl-1.1.0c 一.linux 系统限制配置 1.关闭系统防火墙 systemctl stop fire ...
- 源码编译搭建LAMP环境
源码编译搭建LAMP环境 一.将 LAMP 相关软件包上传刡 linux 上 [root@node63 ~]# ls anaconda-ks.cfg install.log ...
- FreeCAD v0.19源码编译与VS2017+Qt5环境搭建
FreeCAD v0.19源码编译与VS2017+Qt5环境搭建_$firecat全宏的代码足迹$-CSDN博客一.环境准备VS2017,x64cmake-3.14.5-win64-x64.msiFr ...
- 【MQTT从入门到提高系列 | 01】从0到1快速搭建MQTT测试环境
这是机器未来的第24篇文章 原文首发地址:https://blog.csdn.net/RobotFutures/article/details/125532208 1. mosquitto概述 Ecl ...
- 源码解读_入口开始解读Vue源码系列(二)——new Vue 的故事
作者:muwoo 转发链接:https://github.com/muwoo/blogs/blob/master/src/Vue/2.md 目录 入口开始解读Vue源码系列(一)--造物创世 入口开始 ...
- 基于Centos7.5源码编译搭建LAMP架构
简介LAMP源码编译搭建LAMP架构 为什么要源码编译 一般来说,我们软件的安装方式有Yum(rpm),和源码编译两种方式,那么为什么我们需要源码编译安装一部分软件?选择源码编译安装软件有以下几个原因 ...
- 源码系列第1弹 | 带你快速攻略Kafka源码之旅入门篇
大家过年好,我是 华仔, 又跟大家见面了. 从今天开始我将为大家奉上 Kafka 源码剖析系列文章,正式开启 「Kafka的源码之旅」,跟我一起来掌握 Kafka 源码核心架构设计思想吧. 今天这篇我 ...
- 【spring源码系列-05】refresh中prepareRefresh方法的执行流程
Spring源码系列整体栏目 内容 链接地址 [一]spring源码整体概述 https://blog.csdn.net/zhenghuishengq/article/details/13094088 ...
- 骗子收录网站源码PHP搭建
简介: 骗子收录网站源码PHP搭建 程序特色: 1.可对接多个货源 2.有广告栏位可添加自己的广告[也可作为广告位] 3.官方公告可自己作为推销你网站的手段 4.后端监控完全不用考虑程序加载慢这种问题 ...
最新文章
- VSCode搭建Vue项目
- GPT-3等三篇论文获NeurIPS2020最佳论文奖 | AI日报
- 算法----删除链表中的节点(Java)
- Charles(HTTP抓包工具软件)中文版
- 【python-numpy 】中的随机打乱数据方法np.random.shuffle
- WinPcap编程3——获取网络适配器列表
- 前端学习(2345):uniapp学习
- 例题:打印正三角形。两层for循环,难点明白行与列的关系
- python的运行方式有哪两种_Python基础:Python运行的两种基本方式
- (转载)web.xml中 IntrospectorCleanupListener的作用
- 6.STM32F407之HAL库——定时器中断
- 小菜鸡跟着小破站黑马程序员学习JAVA的真实经历、感受与收获
- iMindMap手绘思维导图软件免费版
- Gitlab 登录报422错误,账号密码是对的?
- android_97_TouchSlop
- 典型的FPGA芯片有哪些,看完这篇文章就知道了
- 网约车成品源码 代驾顺风车拼车打车货运司乘双端小程序安卓苹果源码
- 实现用户端的充值、修改密码、查看个人信息、保存用户的信息到文件操作
- 一个误操作导致 5.4 万 Star 全部归零,10年的心血...
- java 去除HTML中的所有标签,获取TEXT文本