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 執行器可用的每個檔案。除非您使用 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 目錄下提供檔案。因此,在伺服器上,對檔案的請求將在 https://127.0.0.1:9876/base/* 下提供服務。

Require.js 設定的 baseUrl 為使用相對路徑載入的模組提供起始上下文。為 Karma 伺服器設定此值時,它需要以 /base 開頭。我們希望測試的 baseUrlsrc/main.js 中的基本網址相同,以便來源中的相對 require 不需要更改。因此,由於我們希望基本網址位於 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 #

現在可以將測試編寫為常規的 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 的執行範例.