RequireJS

Karma を Require.js で実行するには、2 つのファイルが必要です。

  • 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 ランナーで使用できるようにするすべてのファイルが含まれています。 デフォルトでは、included: false オプションを使用しない限り、ファイルごとに script タグが作成されます。

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 は、ソースの相対 require を変更する必要がないように、src/main.js のベース URL と同じフォルダにする必要があります。 したがって、ベース URL を 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

Karma と Require.js を使用した実行例を以下に示します。.