As many of my readers my know, or have figured out, I’ve been a fan of the Ruby language for quite some time and I’ve used it to construct some of my own open source testing solutions. I’m now actively pursuing JavaScript as my potential test ecosystem of choice. In a few upcoming posts, I’ll talk about this journey with practical examples. This first post starts things off by getting you up and running with a few possible JavaScript technologies.
To set expectations, in this post I’ll cover a bit about using Node as the means by which to host your JavaScript execution. I’ll talk about using NPM to get the required dependencies. I’ll very briefly cover one very popular test library, Mocha, and I’ll show you how to use a build management tool to fire things off. I’ll also provide a very brief foray into using a JavaScript alternative, called CoffeeScript.
By necessity I’m going to be giving you a bit of a whirlwind tour here. As a test developer myself, I often have enough knowledge of how to utilize different languages and different tools. That’s not the problem. The problem is simply knowing where to start and then actually getting started with some very minimal examples so that I can play around further on my own. So I need you to come in to this with at least some pre-existing knowledge or, at minimum, a comfort level with getting into a particular language’s ecosystem.
To do all this, you need Node.js and NPM. I have my Setting Up WebDev page to help you get started with all that. If you’re curious and/or a glutton for punishment, I also do have a series of Node.js tutorials, but they are much more involved than what you need for these test-specific discussions.
Create the Project
This part is simple. Just pick some spot on your filesystem where you want to create a project. Do note that I do just about everything via the command line, but if you want to use an editor and/or IDE, feel free. As with most such tutorials, a $ is meant to indicate a generic prompt and not something you should type in.
$ mkdir project-dir $ cd project-dir
Set up the Project
One of the test runners that is extremely popular for writing tests with JavaScript is called Mocha.js, usually shortened to just Mocha. Let’s first install this as a local project dependency.
$ npm install mocha
Some tutorials will have you install Mocha globally, by adding a “-g” flag to the above command. That’s certainly fine as it allows you to run the mocha
command from anywhere. As it is, with my current instructions you would have to run Mocha like this:
$ node_modules/mocha/bin/mocha
However, I tend not to install anything globally unless I absolutely have to. I’m going to show you how you don’t have to use that full command path. If you are creating a Node project specifically, you will usually have a package.json file which serves as a means of identifying a particular module. Normally people will initialize their project at the start — and that’s fine — but here I’m showing you can do it later. So let’s initialize our project:
$ npm init
You’ll be asked a series of questions about your project. You can pretty much just accept the defaults for now. One thing to note in particular is the “test command” prompt you are given. You’ll notice that it defaults to “(mocha)” and this is because NPM was smart enough to see that you already had a node_modules
directory and it looked within there to see that you also had a mocha
directory. Since NPM is aware that Mocha is a test runner, it makes the likely assumption that you want to use it for running tests.
What this means is that you can now run your test runner of choice by doing the following:
$ npm test
Obviously you don’t have any tests yet so if you run that now you’ll get something like Error: cannot resolve path (or pattern) 'test'
. We’ll come back to that in a bit but for now you can probably see that the nice thing about this approach is that you can switch out your test runner but still run the same command. You can also use multiple test runners in your project and simply add more sections to the package.json file.
Speaking of that file, if you look at its contents you’ll notice that “mocha” is now a “devDependency”, which is generally what you would want for your test projects. Although do note that deployment of a test solution can be a bit different than deployment of an application solution. I won’t go into that too much right now since this post isn’t about deploying test solutions, but rather just getting started with them.
You can probably see that there’s a lot of supporting material that I could be covering here but I’m not. I do talk a little about NPM and initializing projects in my third post on learning Node.js. For an exhaustive explanation of all the information that package. json can contain, just issue the npm help json
command or, even better, go to https://www.npmjs.org/doc/files/package.json.html. For an exhaustive list of all the commands of NPM, go to https://www.npmjs.org/doc/cli/npm.html. Regarding those version numbers you see in the package.json file, you can define any kind of version range; see https://www.npmjs.org/doc/misc/semver.html for more details.
Create a Test
So remember that horrendous looking error you got when running npm test
? What that was basically telling you is that Mocha was looking for a test
directory but couldn’t find it. Mocha will be able to run tests from anywhere but, by convention, it will look in a test
directory. So let’s set one up.
$ mkdir test
In that directory, create a file called first-test.js and put the following in it:
1 2 3 4 5 6 7 8 9 |
var assert = require('assert'); describe('a feature', function() { context('a scenario', function() { it('does something expected', function() { assert(true); }); }); }); |
If, like me, you’re coming from Ruby, you’ll notice this format is very much like RSpec. Both of these test solutions are conceptually similar to NSpec in the .NET testing world or GSpec in the Java testing world. I’m going go into more specifics about Mocha in a future post, so for now just take note of the structure.
You might notice that I’m using the built in assertion library of Node.js. This is really nice and simple. You can see the full documentation for the assert library. For some people that simplicity is enough for what they want. For others, however, they prefer more expressive ways to assert aspects about tests. I’ll talk about alternatives in that same future post where I’ll cover Mocha in greater detail.
Make sure you run this with:
$ npm test
You should see some nice output showing a passing test.
Syntactic Sugar for Tests
I’m adding this part mainly for the Rubyists in the crowd who tend to like their test structure to be as syntactically clean as possible. One thing you’ll note with JavaScript is you always have callback functions being passed around. It can add to the boilerplate of using JavaScript, to be sure. One neat “trick” is to use an alternative called CoffeeScript.
First, let’s install a local copy of CoffeeScript:
$ npm install --save-dev coffee-script
This will install the coffee-script module and, since I used the “–save-dev” flag, it will add it to the “devDependencies” of package.json. Incidentally, you may wonder why I didn’t use this same flag with Mocha earlier. That’s because I didn’t have a package.json file yet. Had I ran npm init
first and then installed Mocha I would have used the command npm install --save-dev mocha
to do so.
Now create a file called second-test.coffee in your test
directory. Put the following in that file:
1 2 3 4 5 6 |
assert = require 'assert' describe 'a feature', -> context 'a scenario', -> it 'does something expected', -> assert true |
As you can see, it’s the same test as before but with a lot less boilerplate. This is one of the reasons many JavaScript developers prefer CoffeeScript. As a tester focused on writing test solutions, I’m still on the fence about CoffeeScript. I don’t dislike it, by any means, but it’s one more layer I sometimes have to worry about.
In any event, if you run npm test
now you’ll find that your previous test still passes but the new one isn’t being run. The reason for this is that Mocha is looking for JavaScript (*.js) files but this is a CoffeeScript (*.coffee) file. CoffeeScript is basically a language that has be compiled into JavaScript in order for it to run. Without going into all the details of what this means, for now you can create a file called mocha.opts in your test
directory and put the following in it:
1 |
--compilers coffee:coffee-script/register |
You can now run the test command again:
$ npm test
You should see that you have two passing tests.
Using a Build Manager
Earlier I had talked about Grunt as a build tool to use for JavaScript, but a tool called Gulp definitely seems to be gaining momentum and I personally find Gulp’s stream approach to be a much more logical approach to specifying build tasks.
First, you have to install Gulp. In this case, I’m going to install Gulp globally, since it is a build tool that can be used for any project, as well as locally so that it serves as a dependency for my project.
$ npm install gulp -g $ npm install --save-dev gulp
You can check if you have a global Gulp by doing this:
$ gulp -v
Since I’m using Mocha as my test runner and I’m going to want Gulp to utilize it, I’m going to also locally install the gulp-mocha plugin.
$ npm install --save-dev gulp-mocha
Now, create a gulpfile.js file in the root of project-dir. And then put the following in that file:
1 2 3 4 5 6 7 8 9 |
var gulp = require('gulp'); var mocha = require('gulp-mocha'); gulp.task('mocha', function() { return gulp.src(['test/*.js'], {read:false}) .pipe(mocha({reporter: 'spec'})) }); gulp.task('default', ['mocha']); |
This isn’t the post to cover Gulp in detail but essentially what I’m doing there is setting up a build task called ‘mocha’ that reads in all of the *.js files in my test directory. I’m then using the Gulp stream approach, via the .pipe call, to send those files to Mocha. I’ve also said that the default task is to run my ‘mocha’ task. To run the build, just do this:
$ gulp
Hmm. Notice something interesting there? Only one test ran and that’s the JavaScript test. The CoffeeScript test did not run. This has to do with some oddities regarding how the mocha.opts file is processed. What you can do is change your task as follows:
1 2 3 4 5 |
gulp.task('mocha', function() { require('coffee-script/register'); return gulp.src(['test/*.js', 'test/*.coffee'], {read:false}) .pipe(mocha({reporter: 'spec'})) }); |
Now you should find that both tests are running.
And there you have it! A brief foray into the world of writing test solutions in JavaScript. Even though I’ve barely scratched the surface here, consider what you’ve done. You’ve used Node.js, NPM, Mocha, CoffeeScript, and Gulp all in one shot.