继续阅读以了解 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);
如果您不喜欢 promises,可以使用发出的 '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 使用与生成器相关的断言助手扩展了 原生 assert 模块。您可以在 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()
断言相反。