karma如何与测试框架合作2之webpack
前文中,我们探讨了karma的工作的一些基本过程。但是,我并没有提及es6相关的内容, 本文来填这个坑。
抛出疑问
在现有的karma + webpack项目里,我们经常看到这样的配置,以vue-webpack生成的代码为例:
// index.js// require all test files (files that ends with .spec.js)
// const testsContext = require.context('./specs/serverVersion/', true, /tableAction.spec$/)
// const testsContext = require.context('./specs/clientVersion/', true, /\.spec$/)
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)
虽然有注释,但是在深入研究之前我一直没有搞明白过,这段代码是什么意思?!!!vue
组件、es6
这些代码又是怎么被加载的呢?下面让我们慢慢揭秘。
本文代码: https://github.com/njleonzhan...
还是从简单的例子出发
我们把上一篇文章的例子加工一下
// src/index.jsfunction add(x, y) {return x + y
}function sub(x, y) {return x - y + 1
}export {add,sub
}
// test/add.spc.jsimport {add} from '../src'describe('add suit', _ => {it('test add', done => {add(1, 2).should.equal(3)done()})
})
// test/sub.spc.jsimport {sub} from '../src'describe('add suit', _ => {it('test sub', done => {sub(5, 2).should.equal(3)done()})
})
// karma.conf.js{files: ['test/add.spec.js','test/sub.spec.js'],
}
这里我们把add
和sub
两个函数通过es6导出了,测试代码我们也不再自己写karma adapter了,而是用上了大家熟悉的mocha
。执行一下npm run test
试试,挂了:
Uncaught SyntaxError: Unexpected token import
回顾上文的内容, karma会把所有karma.config里files
字段里描述的所有文件都加载到测试页面里执行. 也就是说import
和export
这样的语法,被直接加载到浏览器里面了,出错也就难免了。怎么办呢?常规方案啊:用webpack
把es6编译成es5,再执行嘛。
karma-webpack
karma
和webpack
是通过karma-webpack
这个karma preprocess
结合在一起的。至于什么是preprocess
,顾名思义就是预处理器,在karma加载files
到页面之前,karma会先对files
通过preprocess
进行处理。
我们来配置一下:
// karma.conf.jsfiles: ['test/add.spec.js','test/sub.spec.js'],// preprocess matching files before serving them to the browser// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessorpreprocessors: {'test/add.spec.js': ['webpack'],'test/sub.spec.js': ['webpack']},webpack: {module: {loaders: [{test: /\.js$/,exclude: [/node_modules/],loader: "babel-loader"}]}}
我们用babel-loader
先对测试文件预处理一下。再执行下测试试试:
PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 2 of 2 SUCCESS (0.008 secs / 0.001 secs)
果然成功了。打开浏览器看一下add.spec.js
, 确实是被webpack
处理过
// 浏览器中的add.spec.js /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {.....
/***/ (function(module, exports, __webpack_require__) {"use strict";var _src = __webpack_require__(1);describe('test suit', function (_) {it('test add', function (done) {(0, _src.add)(1, 2).should.equal(3);done();});
});/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {"use strict";Object.defineProperty(exports, "__esModule", {value: true
});
function add(x, y) {return x + y;
}function sub(x, y) {return x - y;
}exports.add = add;
exports.sub = sub;/***/ })
/******/ ]);
到这是不是就配置好了呢?当然不是啦,文章开头的提到的index.js
里的代码是什么意思的问题还没解释呢。仔细看一下karma-wepack
的文档Alternative Usage部分:
This configuration is more performant, but you cannot run single test anymore (only the complete suite).
The above configuration generates a webpack bundle for each test. For many testcases this can result in many big files. The alterative configuration creates a single bundle with all testcases.
再细看一下上面中贴出的浏览器中的add.spec.js
的代码,我们会发现add
和sub
的代码都包含在了里面。同样浏览器中的sub.spec.js
的代码,也会包含add
和sub
的代码。实际上,karma-wepack
会把files
里的每一个文件都当做webpack entry去编译一次,这样如果我们有多个测试文件,就会多次打包,不但测试速度慢了,而且打包可能会重复多次,以至于包变大。
所以,karma-wepack
向我们推荐使用文章开头提到的配置方式,就是把所有的测试代码都通过一个index
文件加载起来。这里利用的是webpack的require.context和context module API,大家自行看一下文档就明白了。
再次优化一下我们的实例代码,添加一个test/index.js
文件,并修改karma.conf.js
的配置:
// karma.conf.js// list of files / patterns to load in the browserfiles: ['index.js'],// preprocess matching files before serving them to the browser// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessorpreprocessors: {'index.js': ['webpack']},
// test/index.js
var testsContext = require.context("./test", true, /\.spec$/);
testsContext.keys().forEach(testsContext);
再跑一下测试,观察一下,src和test里的代码确实都打到了一个文件里了!!
问题基本上都搞清楚了,但是细心的朋友可能发现了文章开头贴出的代码里,不仅仅require了所有的测试代码,还把src
下的代码require了一遍?本例中src
下的代码都都通过import的方式引用了,webpack自然也就把它们打包了。这样对测试覆盖率的统计不会有什么影响。但是,如果我们给一个库写测试用例,这个库有很多的组件,我们很有可能丢掉某个组件忘记写测试用例,这个时候如果我们不把src
下的代码也加载进来,那么测试覆盖率的统计就会丢掉这部分代码,所以require src
下的代码有时候也是必要的。(这个问题,可以参考require all src files in unit/index.js useless?)
结束语
我们接触计算机的技术的时候,一般都是先用起来,然后再深入掌握。本文是我个人在使用karma + webpack时对一些细节问题的探索,我把详细的思考过程记录在这里,希望对后来者所有帮助。
karma如何与测试框架合作2之webpack相关推荐
- 【Karma】多环境自动测试框架 -- 基础教程
介绍 前身 Testacular, AngularJs Team 创建出来的. 以下是官网对Karma的相关特点介绍 支持真实浏览器, 无浏览器PhantomJS 热更新,文件变化后自动测试 测试框架 ...
- karma 测试框架的前世今生
引言 在前端测试框架的学习中了解到了karma的强大,搜索得到淘宝前端团队的这片讲述karma特点及原理的分享,非常不错.转载分享至此, 原文链接:http://taobaofed.org/blog/ ...
- Mockito:一个强大的用于Java开发的模拟测试框架
介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用Mockito的Java示例. 模拟(Mock)的概念 在软件开发的世界之外, "mock"一 ...
- spring框架mvc框架_Spring的MVC测试框架入门–第1部分
spring框架mvc框架 最新推出的主要Spring框架是Spring MVC测试框架,Spring Guys声称它是"一流的JUnit支持,可通过流畅的API测试客户端和服务器端Spri ...
- spring框架mvc框架_Spring MVC测试框架入门–第2部分
spring框架mvc框架 这个迷你系列的第一个博客介绍了Spring MVC测试框架,并演示了其在单元测试Spring MVC Controller类中作为控制器而不是POJO进行单元测试的用途. ...
- Spring MVC测试框架入门–第1部分
最新推出的主要Spring框架是Spring MVC测试框架,Spring Guys声称它是"一流的JUnit支持,可通过流畅的API测试客户端和服务器端Spring MVC代码" ...
- Spring MVC测试框架入门–第2部分
这个迷你系列的第一个博客介绍了Spring MVC测试框架,并展示了其在单元测试Spring MVC Controller类中作为控制器而不是POJO进行单元测试的用途. 现在是时候讨论使用框架进行集 ...
- 前端测试框架(学习之路)前言
为什么需要单元测试 正确性:测试可以验证代码的正确性,在上线前做到心里有底 自动化:当然手工也可以测试,通过console可以打印出内部信息,但是这是一次性的事情,下次测试还需要从头来过,效率不能得到 ...
- 契约测试概念以及契约测试框架SCC VS PACT对比
契约测试 基于契约,对消费者与生产者间的协作的验证, 本质上就是验证生产者所提供的内容是否满足消费者的期望. 契约测试在行业内,主要分为两种类型,消费者驱动的契约测试和生产者驱动的契约测试,最常见的就 ...
最新文章
- python3 读写中文文件
- 利用Matlab优化工具箱求解旅行商最短路径问题
- python中指定变量为1byte_Python读字节某一位的值,设置某一位的值,二进制位操作...
- 吴恩达 coursera AI 专项五第三课(下)总结+作业答案
- 关于Topic和Partition
- php rmdir 返回值,php通过rmdir删除目录的简单用法
- Avalonia跨平台入门第二十一篇之玩耍CEF
- struct stat结构体简介
- keil无法生成axf文件之解决方法
- linux0.11内核完全注释读书笔记
- Windows软件防火墙实现技术简述
- 100行JS代码实现❤坦克大战js小游戏源码 HTML5坦克大战游戏代码(HTML+CSS+JavaScript )...
- mescroll-vue下拉上拉刷新的使用
- wps计算机一级考试提纲,2012年计算机一级考试WPSOffice考试大纲
- 计算机网络常见面试知识点总结
- uva 572 Oil Deposits
- 高薪程序员面试题精讲系列74之你熟悉cookie、session吗?有哪些请求方式?请求转发与重定向有什么区别?
- Pygame 官方文档 - pygame.display
- PGSQL学习——触发器
- chatgpt中的强化学习 PPO
热门文章
- Android自定义view之measure、layout、draw三大流程
- 自动化测试--实现一套完全解耦的测试框架(三)
- jdbc ?占位符不起作用_JDBC高级(二):DbUtils
- go语言打印日期_go语言基础:流程控制(4)-多重循环跳转控制
- window10删除目录时提示没有找到该项目
- java.sql.SQLSyntaxErrorException: Unknown column ‘###‘ in ‘field list‘
- FTP 编程 5 文件传输与目录切换
- python timer模块_Python timeit模块的使用实践
- 分布式事务框架 - Seata
- Python中使用xpath获取Scrtpt里面的内容