TL;DR
我确实为我的任务创建了测试,我为 gulp 任务创建了两种测试:
- 单元测试,例如用于条件、选项等。
- 集成测试,例如流输入、流输出等
为了确保它可以轻松测试,我对从任务到 gulp 插件的所有内容进行了模块化。
单元测试
- 为每个 gulp 插件创建适配器。
- 在模块化任务中使用适配器。
- 窥探适配器并在流上添加调试属性。
- 断言任何条件和流序列。
集成测试
- 构建输入
- 运行 gulp 任务
- 输出到临时位置
真的很长的答案
闲聊已经够了,这里有一个单元测试和使用 jasmine 的集成测试示例:
/* spec/lib/tasks/build_spec.js */
var gulp = require("gulp");
var through2 = require("through2");
var exec = require("child_process").exec;
var env = require("../../../lib/env");
var build = require("../../../lib/tasks/build");
var gulpif = require("../../../lib/adapters/gulpif");
var gzip = require("../../../lib/adapters/gzip");
var uglify = require("../../../lib/adapters/uglify");
describe("build", function(){
it("stream to uglify then gzip if environment is production", function(testDone){
var streamSequence = [];
// 1. Stub condition and output path
spyOn(env, "production").and.returnValue(true);
spyOn(build, "dest").and.returnValue("./tmp");
// 2. Stub debug message for stream sequence
spyOn(gulpif, "stream").and.callFake(function(env, stream){
if (env.production()) streamSequence.push(stream.debug["stream-name"]);
return through2.obj();
});
spyOn(uglify, "stream").and.callFake(function(){
var stream = through2.obj();
stream.debug = { "stream-name": "stream-uglify" };
return stream;
});
spyOn(gzip, "stream").and.callFake(function(){
var stream = through2.obj();
stream.debug = { "stream-name": "stream-gzip" };
return stream;
});
var stream = build.run();
var url = "file://" + process.cwd() + "/tmp/resource.js";
stream.on("end", function(){
// 3. Assert stream sequence (unit test)
expect(streamSequence).toEqual(["stream-uglify", "stream-gzip"]);
exec("curl " + url, function(error, stdout, stderr){
// 4. Assert stream output (integration)
expect(eval.bind(Object.create(null), stdout)).not.toThrow();
testDone();
});
});
});
});
这是任务的模块示例:
/* lib/tasks/build.js */
var gulp = require("gulp");
var env = require("../env");
var gulpif = require("../adapters/gulpif");
var gzip = require("../adapters/gzip");
var uglify = require("../adapters/uglify");
var build = {
dest: function(){
return "./path/to/output";
},
run: function(){
return gulp.src("./path/to/resource.js")
.pipe(gulpif.stream(env.production(), uglify.stream()))
.pipe(gulpif.stream(env.production(), gzip.stream()))
.pipe(gulp.dest(this.dest()));
}
};
module.exports = build;
这里是适配器:
/* lib/adapters/gulpif.js */
var gulpif = require("gulp-if");
var adapter = {
stream: function(){
return gulpif.apply(Object.create(null), arguments);
}
};
module.exports = adapter;
/* lib/adapters/gzip.js */
var gzip = require("gulp-gzip");
var adapter = {
stream: function(){
return gzip.apply(Object.create(null), arguments);
}
};
module.exports = adapter;
/* lib/adapters/uglify.js */
var gzip = require("gulp-uglify");
var adapter = {
stream: function(){
return uglify.apply(Object.create(null), arguments);
}
};
module.exports = adapter;
这是演示条件测试的环境:
/* lib/env.js */
var args = require("yargs").argv;
var env = {
production: function(){
return (args.environment === "production");
}
}
最后,这里是使用任务模块示例的任务:
/* tasks/build.js */
var gulp = require("gulp");
var build = require("./lib/tasks/build");
gulp.task("build", function(){
build.run();
});
我知道它并不完美,并且有一些重复的代码。但我希望这可以让您演示我是如何测试我的任务的。