本文介绍了 karma 的入门知识点。
什么是 karma
karma 是一个提升测试效率的工具,帮助开发者更好更快速地在多种环境下执行测试代码,拿到测试结果。在运行的时候,它会自动启动配置好的浏览器,同时也会启动一个 node 服务器,然后在启动好的浏览器中执行测试代码,并将测试代码执行结果传回给 node 服务器,然后 node 服务器在打印出收到的执行结果。
安装 karma
可以通过 npm 安装 karma :
1 2 3 4 5
| // 本地安装 npm i karma --save-dev // 全局安装 npm i karma -g
|
初始化 karma
安装完成之后,切换到目标项目根目录,运行:
这样就会以向导的形式生成 karma 的配置文件 karma.conf.js
,文件内容大致为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| module.exports = function(config) { config.set({ basePath: '', frameworks: ['jasmine', 'requirejs'], files: [ 'test/main.js', { pattern: 'src/**/*.js', included: false }, { pattern: 'test/**/*Spec.js', included: false } ], exclude: [], preprocessors: { 'src/**/*.js': ['babel', 'coverage'], 'test/**/!(main).js': ['babel', 'coverage'], 'node_modules/protectobject/src/**/*.js': ['babel'] }, babelPreprocessor: { options: { presets: ['es2015', 'stage-0'], plugins: ['transform-decorators-legacy', 'transform-es2015-modules-amd'] } }, coverageReporter: { type: 'html', dir: 'coverage' }, reporters: ['dots', 'coverage'], port: 9876, colors: true, logLevel: config.LOG_INFO, autoWatch: true, browsers: ['Chrome', 'Firefox', 'Safari'], singleRun: false, concurrency: Infinity }); };
|
配置 Require.js
对于 Require.js ,还要注意配置一个入口文件,主要用于配置 Require.js 的模块信息等。
上述 karma 配置文件中的 test/main.js 即为 Require.js 的入口文件,在该文件中的代码一般来说应该是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| var TEST_REGEXP = /(spec|test)\.js$/i; var allTestFiles = []; Object.keys(window.__karma__.files).forEach(function(file) { if (TEST_REGEXP.test(file)) { var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, ''); allTestFiles.push(normalizedTestModule); } }); require.config({ baseUrl: '/base/src', paths: { 'jquery': '../lib/jquery', 'underscore': '../lib/underscore', }, shim: { 'underscore': { exports: '_' } }, deps: allTestFiles, callback: window.__karma__.start });
|
执行测试
运行如下命令,执行测试:
karma 分析
在执行测试的时候,点击 debug
按钮,进入 debug 页面,然后打开浏览器开发者工具,可以看到在 HTML 中有一段 js 代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| window.__karma__.config = {"args":[],"useIframe":true,"captureConsole":true,"clearContext":true}; window.__karma__.files = { '/base/node_modules/requirejs/require.js': '2c8b45573db27c131094a113e995236d20f043bb', '/base/node_modules/karma-requirejs/lib/adapter.js': '2621a4400d4a8a49588243fce2d8609ef950b46a', '/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js': '391e45351df9ee35392d2e5cb623221a969fc009', '/base/node_modules/karma-jasmine/lib/boot.js': '945a38bf4e45ad2770eb94868231905a04a0bd3e', '/base/node_modules/karma-jasmine/lib/adapter.js': '7975a273517f1eb29d7bd018790fd4c7b9a485d5', '/base/test/main.js': 'fc5206f4dff3b583db818cb10ed7c5cade572896', '/base/src/State.js': 'db89a58b4570983b8f8febfd4dedbc586c353670', '/base/test/StateSpec.js': 'faf31b373690a6d7a7035fdfdc9c85d906ace5c1' };
|
可以看到 window.__karma__.files
中列出了所有的可能会在浏览器中执行的 js ,如果通过 Require.js 加载这里没有列举出来的 js ,就会报错。
然后再看下面的一堆 script 标签,大致是这样的:
1 2 3 4 5 6 7 8 9
| <script type="text/javascript" src="/base/node_modules/requirejs/require.js"></script> <script type="text/javascript" src="/base/node_modules/karma-requirejs/lib/adapter.js"></script> <script type="text/javascript" src="/base/node_modules/jasmine-core/lib/jasmine-core/jasmine.js"></script> <script type="text/javascript" src="/base/node_modules/karma-jasmine/lib/boot.js"></script> <script type="text/javascript" src="/base/node_modules/karma-jasmine/lib/adapter.js"></script> <script type="text/javascript" src="/base/test/main.js"></script> <script type="text/javascript"> window.__karma__.loaded(); </script>
|
可以看到,直接引入了 require.js 、 karma 相关的一堆 js 、jasmine 相关的 js ,还直接引入了刚才配置的 test/main.js (Require.js 入口文件)。注意,此处并没有直接引入 included: false
的 js 。
URL 路径中的 base
如果仔细看各种资源请求的 URL 地址,会发现除了 debug.js
和 context.js
之外,其它 js 文件都会以 /base
开头,在配置 Require.js 的时候,务必注意这一点。
coverage
可以引入 karma 的 coverage 插件来查看测试覆盖率,该插件会在目标代码中插入很多额外的代码,用于判断测试代码执行流程有没有走到这些地方。在 debug 的时候,最好关掉 coverage 功能,不然这些额外的代码非常影响调试。
另外 karma-coverage-es6 声称支持 ES6 ,但是似乎并不行?
jasmine 的 HTML reporter
默认情况下,浏览器中 debug 页面是不会输出任何 jamine 测试结果的,可以借助 karma-jasmine-html-reporter
解决这个问题。
但是,karma-jasmine-html-reporter
有坑,在该插件的 index.js 中,有这样一段代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| var createPattern = function(path) { return {pattern: path, included: true, served: true, watched: false}; }; var initReporter = function(files, baseReporterDecorator) { baseReporterDecorator(this); files.unshift(createPattern(__dirname + '/lib/adapter.js')); files.unshift(createPattern(__dirname + '/lib/html.jasmine.reporter.js')); files.unshift(createPattern(__dirname + '/css/jasmine.css')); }; initReporter.$inject = ['config.files', 'baseReporterDecorator']; module.exports = { 'reporter:kjhtml': ['type', initReporter] };
|
files
指的就是 karma.conf.js 中配置的 files ,此处使用 unshift
方法将这堆 js 、 css 放在了 files 最前面,这样就会导致 html.jasmine.reporter.js
先于 jasmine.js
加载,从而报错(html.jasmine.reporter.js
是要依赖 jasmine.js
的),所以这里最好根据项目的实际情况,合理调整一下顺序。