简体   繁体   中英

How do I use gulp with tape?

I'm trying to integrate Gulp with Tape ( https://github.com/substack/tape ), the NodeJs test harness.

How can I do this? There doesn't seem to be an existing gulp plugin.

I've see this, but it looks really inelegant:

var shell = require('gulp-shell')

gulp.task('exec-tests', shell.task([
  'tape test/* | faucet',
]));

gulp.task('autotest', ['exec-tests'], function() {
  gulp.watch(['app/**/*.js', 'test/**/*.js'], ['exec-tests']);
});

I've tried this, which looks like it should work:

var tape = require('tape');
var spec = require('tap-spec');


gulp.task('test', function() {
    return gulp.src(paths.serverTests, {
            read: false
        })
        .pipe(tape.createStream())
        .pipe(spec())
        .pipe(process.stdout);
});

but I get a TypeError: Invalid non-string/buffer chunk error

Your "inelegant" answer is the best one. Not every problem can be best solved with streams, and using gulp just as a wrapper is not a sin.

Right, your task won't work because gulp streams are based on vinyl, a virtual file abstraction. I don't really think there's a good way of handling this in gulp, it seems like you should be using the tape API directly. I mean, you could put some gulp task sugar around it if you wish:

var test = require('tape');
var spec = require('tap-spec');
var path = require('path');
var gulp = require('gulp');
var glob = require('glob');

gulp.task('default', function () {
    var stream = test.createStream()
        .pipe(spec())
        .pipe(process.stdout);

    glob.sync('path/to/tests/**/*.js').forEach(function (file) {
        require(path.resolve(file));
    });

    return stream;
});

Seems kind of messy to me; not only because we're not using any of gulp's streaming abstractions, but we're not even putting it into a way that could hook into a gulp pipeline afterwards. Furthermore, you can't get gulp's task finished message when using this code either. If anyone knows a way around that then, please, be my guest. :-)

I think I would prefer to use tape on the command line. But, if you want all of your build step tasks in your gulpfile this might be the route to go.

Just use code below and gulp tdd and having TDD :) with tape

const tapNotify = require('tap-notify');
const colorize = require('tap-colorize');
const tape = require('gulp-tape');
const through = require('through2');
gulp.task('test',function(){
    process.stdout.write('\x1Bc');
    const reporter = through.obj();
    reporter.pipe(tapNotify({
        passed: {title: 'ok', wait:false},
        failed: {title: 'missing',wait:false}
    }));
    reporter
        .pipe(colorize())
        .pipe(process.stdout);
    return gulp.src('test/**/*.js')
        .pipe(tape({
            outputStream: through.obj(),
            reporter: reporter
        }));
});
gulp.task('tdd', function() {
    gulp.run('test');
    gulp.watch(['app/scripts/**/*.js*', 'test/**/*.js'],['test']);
});

In a GitHub issue for tape jokeyrhyme mentions that gulp tasks can be Promises, and suggests a way to use that for running tape tests. Based upon that advice I've done this:

gulpfile.babel.js :

import glob from "glob";

gulp.task("test", () => {
    let module = process.argv[process.argv.length - 1];

    return new Promise(resolve => {
        // Crude test for 'gulp test' vs. 'gulp test --module mod'
        if (module !== "test") {
            require(`./js/tape/${module}.js`);
            resolve();
            return;
        }

        glob.sync("./js/tape/*.js").forEach(f => require(f)));
        resolve();
    });
});

Looking at Ben's answer I suspect what I've done isn't very nice though, for one thing I've noticed that failing tests don't result in a non-zero exit code (although I've not tried Ben's approach to validate whether that does).

// npm i --save-dev gulp-tape
// npm i --save-dev faucet (just an example of using a TAP reporter)

import gulp from 'gulp';
import tape from 'gulp-tape'; 
import faucet from 'faucet';

gulp.task('test:js', () => {
    return gulp.src('src/**/*test.js')
        .pipe(tape({
            reporter: faucet()
        }));
});

Here's an example of my solution:

var gulp = require('gulp');
var tape = require('tape');
var File = require('vinyl');
var through = require('through2');
var exec = (require('child_process')).execSync;

function execShell(shcmd, opts) {
    var out = '';
    try {
        out = exec(shcmd, opts);
    } catch (e) {
        if (e.error) throw e.error;
        if (e.stdout) out = e.stdout.toString();
    }
    return out;
};

gulp.task('testreport', function(){
    return gulp.src(
        'testing/specs/tape_unit.js', {read: false}
    ).pipe(
        through.obj(function(file, encoding, next) {
            try{
                // get tape's report
                var tapout = execShell(
                    "./node_modules/.bin/tape " + file.path
                );
                // show the report in a console with tap-spec
                execShell(
                    "./node_modules/.bin/tap-spec", { input: tapout, stdio: [null, 1, 2] }
                );
                // make a json report
                var jsonout = execShell(
                    "./node_modules/.bin/tap-json", { input: tapout }
                );
                // do something with report's object
                // or prepare it for something like Bamboo
                var report = JSON.parse(jsonout.toString());
                // continue the stream with the json report
                next(null, new File({
                    path: 'spec_report.json',
                    contents: new Buffer(JSON.stringify(report, null, 2))
                }));
            }catch(err){ next(err) }
        })
    ).pipe(
        gulp.dest('testing/reports')
    );
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM