Let’s jump right in and take a look at a complete set of Gulp tasks that can be used to verify your local code before you would push it to a GitHub repository for integration testing and deployment.

You can think through what you normally do when you run Mocha from the command line and then put that into your Gulp file. Let’s first install the Gulp mocha plugin:

npm install –save-dev gulp-mocha

For my Node project I have three types of tests I like to run – functional, UI automation and load testing. I want to run each one in sequence.

Before the tests run, I will need to launch my project. After the tests complete I want to stop the Node process. Here is the code in my gulpfile.js file. This works on my Windows machine, and you can figure out what changes are necessary on other operating systems.

I have put in comments to explain each section of the code. The whole thing would be kicked off from the command line by typing “gulp runAllTestsLocal”. Here is gulpfile.js:

'use strict';
var gulp = require('gulp');
var mocha = require('gulp-mocha');
var exec = require('child_process').exec;
// Use the built in Node child_process module to execute our Node command.
// The exec callback does not return until the node process is killed by our taskkill,
// so we need to have the cb() callback outside of the exec() so as to signal to the func_test
// task that it can run.
gulp.task('serverStart', function(cb) {
exec('node server.js', function(err, stdout, stderr) {
console.log(stdout);
console.log(stderr);
});
cb();
});
// Just because the serverStart task has finished, does not mean that our Node.js process
// is up and ready with things like database connections initialized.
// That is why we have the five second delay.
// We also have to use the 'error' and 'end' events to call the cb() callback
// as that is when we know the mocha test has run to completion.
// We give the Mocha test a time limit of 30 seconds to run.
gulp.task('func_test', ['serverStart'], function(cb) {
setTimeout(function() {
return gulp.src(['test/functional_api_crud.js'], { read: false })
.pipe(mocha({
reporter: 'spec', // nyan
timeout: 30000,
ignoreLeaks: true
}).once('error', function() {
cb('error');
}).once('end', function() {
cb();
}));
}, 5000);
});
// The load testing is a node.js project to run and not executed with Mocha
// The node.js process will actually terminate itself and then we are able to move on and
// call the cb() callback
gulp.task('load_test', ['func_test'], function(cb) {
exec('node test/loadtest_api_crud.js', function(err, stdout, stderr) {
console.log(stdout);
console.log(stderr);
cb(err);
});
});
// This is a Mocha test like we had above, but for UI automation.
gulp.task('uiauto_test', ['load_test'], function(cb) {
return gulp.src(['test/ui_automation_UAT.js'], { read: false })
.pipe(mocha({
reporter: 'spec', // nyan
timeout: 90000,
ignoreLeaks: true
}).once('error', function() {
cb('error');
}).once('end', function() {
cb();
}));
});
// We finally make it here, unless there was a test error. We kill the node process.
gulp.task('runAllTestsLocal', ['uiauto_test'], function(cb) {
exec('taskkill /F /IM node.exe', function(err, stdout, stderr) {
console.log(stdout);
console.log(stderr);
cb(err);
});
})

You can see that I would run this whole thing by typing:

gulp runAllTestsLocal

You can see that some tasks have prerequisite tasks that are run first. For example, the task ‘runAllTestsLocal’ goes back to ‘uiauto_test’ and so forth until ‘serverStart’ is seen and run as it has no dependency task. The order of task execution is thus – ‘serverStart’, ‘func_test’, ‘load_test’, ‘uiauto_test’ and then finally the code in ‘runAllTestsLocal’.

Conclusion

Up to this point, you know quite a bit about how to string together Gulp tasks. All that remains is walking through the rest of the tasks that you normally do to get into staging and then to a production deployment. You can simply add more tasks to accomplish the rest of the work required. For example, you can use the gulp-git module to manage your source control command like add, commit and push.

For AWS integration, there are a few approaches you can take from here. One approach would be to use the EB CLI (Elastic Beanstalk Command Line Interface) capabilities to zip up and deploy to whatever instance you like and then use further tasks to test and verify that.

You might want to go back and revisit the tasks that you set up for your tests and utilize command line parameter passing to tell the tests what they are to test as the end point.

Another option is to use the EB CLI to integrate with your Git/GitHub repository and that way, you can use a push command to get code deployed to whatever location you like. Look into the EB swap command to do a CNAME swap to avoid any downtime when you are ready to take some staged code to production.

Be sure to educate yourself the rest of the way for what is capable and you certainly will be able to accomplish whatever is remaining of your CI/CD tasks.