Подтвердить что ты не робот

Как протестировать задачи Gulp

Поскольку я начал использовать Gulp, мой проект стал больше. Теперь у меня есть несколько довольно причудливых задач, и теперь мне интересно, может быть, я должен построить некоторые модульные тесты, чтобы сохранить здравый смысл?

Есть ли хороший и простой способ загрузить Gulpfile и убедиться, что мои задачи делают то, что я хочу, чтобы они делали?

Кто-нибудь когда-либо тестировал свои сценарии, или это была полная трата времени?

4b9b3361

Ответ 1

Способ уменьшить сложность может заключаться в модуляции задач и введении их в отдельные файлы. В этом случае вам может понадобиться использовать плагины gulp и gulp. Я сделал это следующим образом:

в Gulpfile.coffee:

gulp = require 'gulp'
$ = require('gulp-load-plugins')()

require('./src/build/build-task')(gulp, $)

gulp.task "default", ['build']

в ./src/build/build-task.coffee:

module.exports = (gulp, $)->    
   gulp.task "build",->
       $.util.log "running build task"

Хотя некоторые могут утверждать, что этот подход сделает его еще более сложным, и, возможно, лучше сохранить все в Gulpfile, однако это сработало для меня, и мне почти кажется, что я не могу жить без тестов.

Ответ 2

Мой подход заключается в создании тестового экземпляра и использовании exec и yeoman-assert. Хотя это больше похоже на интеграционный тест, я считаю полезным, чтобы задачи выполнялись должным образом (мой прецедент, являющийся генератором-иоманом). Пример (мокко):

'use strict';
var path = require('path');
var helpers = require('yeoman-generator').test;
var assert = require('yeoman-generator').assert;
var exec = require('child_process').exec;
var fs = require('fs');
var injectStyles = require('../.test-instance/tasks/dev');


describe('gulp inject', function ()
{
    var instancePath = path.join(__dirname, '../.test-instance');
    var mainScss = path.join(instancePath, 'app/styles/main.scss');
    var gulpfile = path.join(instancePath, 'gulpfile.js');
    var gulp = '$(which gulp)';
    var injectStylesCmd = gulp + ' injectStyles';

    describe('scss partials in styles folder', function ()
    {
        var expectedContent = [
            [mainScss, /_variables/],
            [mainScss, /base\/_buttons\.scss/],
            [mainScss, /base\/_fonts\.scss/],
            [mainScss, /base\/_forms\.scss/],
            [mainScss, /base\/_icons\.scss/],
            [mainScss, /base\/_lists\.scss/],
            [mainScss, /base\/_page\.scss/],
            [mainScss, /base\/_tables\.scss/],
            [mainScss, /base\/_typography\.scss/],
            [mainScss, /functions\/_some-function\.scss/],
            [mainScss, /mixins\/_some-mixin\.scss/],
            [mainScss, /placeholders\/_some-placeholder\.scss/]
        ];
        var expected = [
            mainScss
        ];


        beforeEach(function (done)
        {
            this.timeout(10000);
            fs.truncateSync(mainScss);
            fs.writeFileSync(mainScss, '// inject:sass\n\n// endinject');
            exec(injectStylesCmd + ' injectStyles', {
                cwd: instancePath
            }, function (err, stdout)
            {
                done();
            });
        });

        it('creates expected files', function ()
        {
            assert.file([].concat(
                expected
            ));
            assert.fileContent([].concat(
                expectedContent
            ));
        });
    });
});

Конечно, вам нужно убедиться, что у вас установлен тестовый экземпляр. Например, файлы тестирования можно создать с помощью fs.writeFileSync. В большинстве случаев вам нужно убедиться, что экземпляр имеет одну и ту же структуру каталогов и что по крайней мере присутствует gulpfile.

Ответ 3

Я обнаружил, что просмотр модульных тестов из плагинов gulp (например: https://github.com/jonkemp/gulp-useref/tree/master/test) является хорошей отправной точкой для написания собственных.

Решение, которое работало для меня в конце (главным интересом был процесс сборки), было не тестировать задачи gulp индивидуально, а иметь каталоги с исходными файлами, скопировать исходные файлы на место, запустить gulp (' gulp build 'в качестве команды оболочки) и сравните выходные каталоги и файлы с другим каталогом с сохранением правильного вывода. -

Ответ 4

TL; DR

Я создаю тесты для своей задачи, есть два типа тестов, которые я создал для задач gulp:

  • Единичные тесты, например. для условий, параметров и т.д.
  • Интеграционные тесты, например. поток, поток и т.д.

Чтобы убедиться, что он может быть легко протестирован, я модулирую все из задачи в плагин gulp.

Unit Test

  • Создайте адаптеры для каждого плагина gulp.
  • Используйте адаптер в модульной задаче.
  • Шпион на адаптере и добавьте свойство отладки в поток.
  • Утвердить любое условие и последовательности потоков.

Интеграционный тест

  • Ввести ввод
  • Запустить задачу gulp
  • Выход на временное местоположение

Действительно длинный ответ

Достаточно chit-chat, здесь unit test, смешанный с примером интеграции с использованием 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();
});

Я знаю, что это не идеально, и есть дублированный код. Но я надеюсь, что это может дать вам демонстрацию того, как я проверил свою задачу.