为了让 Karma 与 Require.js 一起运行,我们需要两个文件
karma.conf.js
— 用于配置 Karmatest-main.js
— 用于为测试配置 Require.js让我们假设我们的应用程序有一个类似于以下的目录结构
$ tree
.
|-- index.html
|-- karma.conf.js
|-- lib
| |-- jquery.js
| |-- require.js
| `-- underscore.js
|-- src
| |-- app.js
| `-- main.js
`-- test
|-- appSpec.js
`-- test-main.js
3 directories, 9 files
第一步是创建我们的 karma.conf.js
。我们可以通过命令行执行此操作
$ karma init
这将为您提供一系列提示,例如源文件和测试文件的路径以及要捕获的浏览器。
在本例中,我们将使用 Jasmine,但其他测试框架也同样适用。
选择“是”以使用 Require.js。
对于问题“您想用 <script> 标签包含哪些文件?”,我们需要选择所有 未 由 Require.js 加载的文件。通常,您只需要包含您的 test-main.js
文件,它对测试的作用与使用 Require.js 时 main.js
对应用程序的作用相同。
对于问题“您的源文件和测试文件在哪里?”,我们选择所有我们想要用 Require.js 加载的文件。对于此示例,我们需要
lib/**/*.js
— 所有外部库src/**/*.js
— 我们的源代码test/**/*Spec.js
— 所有测试然后,在排除文件时,输入 src/main.js
,因为我们不想在测试中实际启动应用程序。
现在您的 karma.conf.js
应该包含
// list of files / patterns to load in the browser
module.exports = function(config) {
config.set({
frameworks: ['jasmine', 'requirejs'],
files: [
{pattern: 'lib/**/*.js', included: false},
{pattern: 'src/**/*.js', included: false},
{pattern: 'test/**/*Spec.js', included: false},
'test/test-main.js'
],
// list of files to exclude
exclude: [
'src/main.js'
]
});
};
files 属性包含您希望 Karma 运行程序可用的每个文件。默认情况下,将为文件创建 script 标签,除非您使用 included: false
选项。
如果您希望在 requirejs 之前添加一个 script 标签(在 requirejs 之前加载一个与 amd 兼容的脚本),那么您必须将 requirejs 和适配器脚本添加到 files 列表中,并从 frameworks 列表中删除 requirejs。这允许您控制顺序。例如,要在 requirejs 之前加载 knockout.js
...
config.set({
frameworks: ['jasmine'],
files: [
'knockout.js',
'node_modules/requirejs/require.js',
'node_modules/karma-requirejs/lib/adapter.js',
{pattern: 'lib/**/*.js', included: false},
{pattern: 'src/**/*.js', included: false},
{pattern: 'test/**/*Spec.js', included: false},
'test/test-main.js'
],
就像任何 Require.js 项目一样,您需要一个主模块来引导您的测试。我们通过 test/test-main.js
完成此操作。
/base
目录 #Karma 在 /base
目录下提供文件。因此,服务器对文件的请求将在 http://localhost:9876/base/*
下提供。
baseUrl
的 Require.js 配置为使用相对路径加载的模块提供一个起始上下文。在为 Karma 服务器设置此值时,它需要以 /base
开头。我们希望测试的 baseUrl
与我们在 src/main.js
中的 baseUrl 相同,这样源中的相对 require 就无需更改。因此,由于我们希望我们的 baseUrl 在 src/
,我们需要编写 /base/src
。
使用 Karma,我们不需要自己列出所有测试文件,因为我们可以很容易地从 test-main.js
中指定的文件中找到它们:Karma 包含 window.__karma__.files
中的所有文件,因此通过过滤此数组,我们找到了所有测试文件。
现在我们可以告诉 Require.js 加载我们的测试,这必须异步完成,因为在运行测试之前必须获取依赖项。test/test-main.js
文件最终看起来像这样
var TEST_REGEXP = /(spec|test)\.js$/i;
var allTestFiles = [];
// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function(file) {
if (TEST_REGEXP.test(file)) {
// Normalize paths to RequireJS module names.
// If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
// then do not normalize the paths
var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');
allTestFiles.push(normalizedTestModule);
}
});
require.config({
// Karma serves files under /base, which is the basePath from your config file
baseUrl: '/base/src',
// example of using a couple of path translations (paths), to allow us to refer to different library dependencies, without using relative paths
paths: {
'jquery': '../lib/jquery',
'underscore': '../lib/underscore',
},
// example of using a shim, to load non AMD libraries (such as underscore)
shim: {
'underscore': {
exports: '_'
}
},
// dynamically load all test files
deps: allTestFiles,
// we have to kickoff jasmine, as it is asynchronous
callback: window.__karma__.start
});
测试现在可以编写为常规的 Require.js 模块。我们将所有内容包装在 define
中,在内部我们可以使用常规的测试方法,例如 describe
和 it
。示例
define(['app', 'jquery', 'underscore', './test-helper'], function(App, $, _, testHelper) {
describe('just checking', function() {
testHelper.setup();
it('works for app', function() {
var el = $('<div></div>');
var app = new App(el);
app.render();
expect(el.text()).toEqual('require.js up and running');
});
it('works for underscore', function() {
// just checking that _ works
expect(_.size([1,2,3])).toEqual(3);
});
});
});
现在我们可以从命令行运行测试
$ karma start
如果您没有将 Karma 配置为监视所有文件并在任何更改时自动运行测试,则可以通过键入以下内容手动触发测试
$ karma run