前文中,我们探讨了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'],
}  

这里我们把addsub两个函数通过es6导出了,测试代码我们也不再自己写karma adapter了,而是用上了大家熟悉的mocha。执行一下npm run test试试,挂了:

Uncaught SyntaxError: Unexpected token import

回顾上文的内容, karma会把所有karma.config里files字段里描述的所有文件都加载到测试页面里执行. 也就是说importexport这样的语法,被直接加载到浏览器里面了,出错也就难免了。怎么办呢?常规方案啊:用webpack把es6编译成es5,再执行嘛。

karma-webpack

karmawebpack是通过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的代码,我们会发现addsub的代码都包含在了里面。同样浏览器中的sub.spec.js的代码,也会包含addsub的代码。实际上,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相关推荐

  1. 【Karma】多环境自动测试框架 -- 基础教程

    介绍 前身 Testacular, AngularJs Team 创建出来的. 以下是官网对Karma的相关特点介绍 支持真实浏览器, 无浏览器PhantomJS 热更新,文件变化后自动测试 测试框架 ...

  2. karma 测试框架的前世今生

    引言 在前端测试框架的学习中了解到了karma的强大,搜索得到淘宝前端团队的这片讲述karma特点及原理的分享,非常不错.转载分享至此, 原文链接:http://taobaofed.org/blog/ ...

  3. Mockito:一个强大的用于Java开发的模拟测试框架

    介绍 本文将介绍模拟测试框架Mockito的一些基础概念, 介绍该框架的优点,讲解应用Mockito的Java示例. 模拟(Mock)的概念 在软件开发的世界之外, "mock"一 ...

  4. spring框架mvc框架_Spring的MVC测试框架入门–第1部分

    spring框架mvc框架 最新推出的主要Spring框架是Spring MVC测试框架,Spring Guys声称它是"一流的JUnit支持,可通过流畅的API测试客户端和服务器端Spri ...

  5. spring框架mvc框架_Spring MVC测试框架入门–第2部分

    spring框架mvc框架 这个迷你系列的第一个博客介绍了Spring MVC测试框架,并演示了其在单元测试Spring MVC Controller类中作为控制器而不是POJO进行单元测试的用途. ...

  6. Spring MVC测试框架入门–第1部分

    最新推出的主要Spring框架是Spring MVC测试框架,Spring Guys声称它是"一流的JUnit支持,可通过流畅的API测试客户端和服务器端Spring MVC代码" ...

  7. Spring MVC测试框架入门–第2部分

    这个迷你系列的第一个博客介绍了Spring MVC测试框架,并展示了其在单元测试Spring MVC Controller类中作为控制器而不是POJO进行单元测试的用途. 现在是时候讨论使用框架进行集 ...

  8. 前端测试框架(学习之路)前言

    为什么需要单元测试 正确性:测试可以验证代码的正确性,在上线前做到心里有底 自动化:当然手工也可以测试,通过console可以打印出内部信息,但是这是一次性的事情,下次测试还需要从头来过,效率不能得到 ...

  9. 契约测试概念以及契约测试框架SCC VS PACT对比

    契约测试 基于契约,对消费者与生产者间的协作的验证, 本质上就是验证生产者所提供的内容是否满足消费者的期望. 契约测试在行业内,主要分为两种类型,消费者驱动的契约测试和生产者驱动的契约测试,最常见的就 ...

最新文章

  1. python3 读写中文文件
  2. 利用Matlab优化工具箱求解旅行商最短路径问题
  3. python中指定变量为1byte_Python读字节某一位的值,设置某一位的值,二进制位操作...
  4. 吴恩达 coursera AI 专项五第三课(下)总结+作业答案
  5. 关于Topic和Partition
  6. php rmdir 返回值,php通过rmdir删除目录的简单用法
  7. Avalonia跨平台入门第二十一篇之玩耍CEF
  8. struct stat结构体简介
  9. keil无法生成axf文件之解决方法
  10. linux0.11内核完全注释读书笔记
  11. Windows软件防火墙实现技术简述
  12. 100行JS代码实现❤坦克大战js小游戏源码 HTML5坦克大战游戏代码(HTML+CSS+JavaScript )...
  13. mescroll-vue下拉上拉刷新的使用
  14. wps计算机一级考试提纲,2012年计算机一级考试WPSOffice考试大纲
  15. 计算机网络常见面试知识点总结
  16. uva 572 Oil Deposits
  17. 高薪程序员面试题精讲系列74之你熟悉cookie、session吗?有哪些请求方式?请求转发与重定向有什么区别?
  18. Pygame 官方文档 - pygame.display
  19. PGSQL学习——触发器
  20. chatgpt中的强化学习 PPO

热门文章

  1. Android自定义view之measure、layout、draw三大流程
  2. 自动化测试--实现一套完全解耦的测试框架(三)
  3. jdbc ?占位符不起作用_JDBC高级(二):DbUtils
  4. go语言打印日期_go语言基础:流程控制(4)-多重循环跳转控制
  5. window10删除目录时提示没有找到该项目
  6. java.sql.SQLSyntaxErrorException: Unknown column ‘###‘ in ‘field list‘
  7. FTP 编程 5 文件传输与目录切换
  8. python timer模块_Python timeit模块的使用实践
  9. 分布式事务框架 - Seata
  10. Python中使用xpath获取Scrtpt里面的内容