請继续阅读,以深入了解 Yeoman 添加的測試輔助工具,幫助減輕單元測試產生器的負擔。
以下範例假設您在 BDD 模式下使用 Mocha。整體概念應該很容易套用在您選擇的單元測試框架。
整理測試
保持測試簡單且易於編輯非常重要。
通常整理測試的最佳方法是將每個產生器和子產生器分為其專屬的 describe
區塊。然後,為產生器接受的每個選項新增一個 describe
區塊。最後,對每個斷言 (或相關斷言) 使用一個 it
區塊。
在程式中,您最終應該得到類似以下的結構
describe('backbone:app', function () {
it('generates a project with require.js', function () {
// assert the file exist
// assert the file uses AMD definition
});
it('generates a project with webpack');
});
測試輔助工具
Yeoman 提供測試輔助工具方法。這些方法包含在 yeoman-test
套件中。
var helpers = require('yeoman-test');
您可以在 這裡查看完整的輔助工具 API。
在單元測試產生器時,最實用的方法是 helpers.run()
。此方法會傳回 RunContext 執行個體,您可以在其上呼叫方法來設定目錄、模擬提示、模擬引數等。
var path = require('path');
it('generate a project', function () {
// The object returned acts like a promise, so return it to wait until the process is done
return helpers.run(path.join(__dirname, '../app'))
.withOptions({ foo: 'bar' }) // Mock options passed in
.withArguments(['name-x']) // Mock the arguments
.withPrompts({ coffee: false }) // Mock the prompt answers
.withLocalConfig({ lang: 'en' }) // Mock the local config
.then(function() {
// assert something about the generator
});
})
有時您可能希望建構一個測試情境,讓產生器可以在目標目錄中使用現有內容執行。這種情況下,您可以呼叫 inTmpDir()
,並指定一個回呼函式,如下所示
var path = require('path');
var fs = require('fs-extra');
helpers.run(path.join(__dirname, '../app'))
.inTmpDir(function (dir) {
// `dir` is the path to the new temporary directory
fs.copySync(path.join(__dirname, '../templates/common'), dir)
})
.withPrompts({ coffee: false })
.then(function () {
assert.file('common/file.txt');
});
您也可以在回呼中執行非同步工作
var path = require('path');
var fs = require('fs-extra');
helpers.run(path.join(__dirname, '../app'))
.inTmpDir(function (dir) {
var done = this.async(); // `this` is the RunContext object.
fs.copy(path.join(__dirname, '../templates/common'), dir, done);
})
.withPrompts({ coffee: false });
執行 Promise 會使用產生器執行的目錄來解析。如果您想使用產生器執行的暫時目錄,這會很有用
helpers.run(path.join(__dirname, '../app'))
.inTmpDir(function (dir) {
var done = this.async(); // `this` is the RunContext object.
fs.copy(path.join(__dirname, '../templates/common'), dir, done);
})
.withPrompts({ coffee: false })
.then(function (dir) {
// assert something about the stuff in `dir`
});
如果產生器呼叫 composeWith()
,您可能想模擬那些依賴的產生器。使用 #withGenerators()
,傳入陣列的陣列,使用 #createDummyGenerator()
作為第一個項目,並在第二個項目中指定一個名稱空間作為模擬的產生器
var deps = [
[helpers.createDummyGenerator(), 'karma:app']
];
return helpers.run(path.join(__dirname, '../app')).withGenerators(deps);
如果您不喜歡使用承諾,可以使用發生的 'ready'
、'error'
和 'end'
活動
helpers.run(path.join(__dirname, '../app'))
.on('error', function (error) {
console.log('Oh Noes!', error);
})
.on('ready', function (generator) {
// This is called right before `generator.run()` is called
})
.on('end', done);
您也可以將產生器匯入為模組來執行。如果產生器的原始程式碼經過轉譯,此作法會很有用。
您需要為 run
提供以下設定
resolved
:產生器的路徑,例如../src/app/index.js
namespace
:產生器的名稱空間,例如mygenerator:app
var MyGenerator = require('../src/app');
helpers.run(MyGenerator, {
resolved: require.resolve(__dirname, '../src/app/index.js'),
namespace: 'mygenerator:app'
});
斷言輔助工具
Yeoman 會使用產生器相關的斷言輔助工具延伸 內建的斷言模組。您可以在 yeoman-assert
資源庫 上看到斷言輔助工具的完整清單。
需要斷言輔助工具
var assert = require('yeoman-assert');
斷言檔案存在
assert.file(['Gruntfile.js', 'app/router.js', 'app/views/main.js']);
assert.noFile()
會斷言相反的結果。
斷言檔案內容
assert.fileContent('controllers/user.js', /App\.UserController = Ember\.ObjectController\.extend/);
assert.noFileContent()
會斷言相反的結果。