RequireJS

为了让 Karma 与 Require.js 一起运行,我们需要两个文件

  • karma.conf.js — 用于配置 Karma
  • test-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 #

第一步是创建我们的 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 #

就像任何 Require.js 项目一样,您需要一个主模块来引导您的测试。我们通过 test/test-main.js 完成此操作。

Karma /base 目录 #

Karma 在 /base 目录下提供文件。因此,服务器对文件的请求将在 http://localhost:9876/base/* 下提供。

baseUrl 的 Require.js 配置为使用相对路径加载的模块提供一个起始上下文。在为 Karma 服务器设置此值时,它需要以 /base 开头。我们希望测试的 baseUrl 与我们在 src/main.js 中的 baseUrl 相同,这样源中的相对 require 就无需更改。因此,由于我们希望我们的 baseUrl 在 src/,我们需要编写 /base/src

Require 每个测试文件 #

使用 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 #

测试现在可以编写为常规的 Require.js 模块。我们将所有内容包装在 define 中,在内部我们可以使用常规的测试方法,例如 describeit。示例

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

这是一个使用 Require.js 的 Karma 运行示例.