要讓 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 執行器可用的每個檔案。除非您使用 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 專案一樣,您需要一個主要模組來啟動您的測試。我們在 test/test-main.js
中執行此操作。
/base
目錄 #Karma 在 /base
目錄下提供檔案。因此,在伺服器上,對檔案的請求將在 https://127.0.0.1:9876/base/*
下提供服務。
Require.js 設定的 baseUrl
為使用相對路徑載入的模組提供起始上下文。為 Karma 伺服器設定此值時,它需要以 /base
開頭。我們希望測試的 baseUrl
與 src/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 模組。我們將所有內容包裝在 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