Marcus Node Bits - Should is a nice way to do asserts

· February 7, 2014

I’m writing down some of the things I’ve picked up when I started to learn about Node, Express and Mongo. Here are all the post in the series:

This post is about an assertion framework that I’ve come to love; should.js.

The thing with most Node packages is that they are quite small, often around 100-200 lines. They, in turn, make use of other packages in the form of dependencies. This is a good thing and leads both to modularity, better design (maybe…) but gives you the opportunity to stitch together an environment just like you like it. Never is this better displayed than when writing tests.

Not only is there a plethora of testing framework to choose from, equally many test runners that can run them, mocking frameworks but also separate assertion frameworks. This is not news to me (I love ShouldFluent when writing C# for example) and makes for a very customisable experience.

The assertion framework that I’ve ended up using is called should.js. Finally a framework that has a name that reveals something of it’s usage and syntax.

It’s easily installed with npm, of course

npm install should

and you’re ready to use the should assertions in your test code. Oh well you need to:

var should = require(“should”);

in your test file of course.

The assertions

Should make heavy use of the Javascript dynamic features and slabs on extension functions to the objects you are testing. This means that you write your assertions after the thing you assert which gives for a very read-it-out-loud syntax. Like this:

The full list of the assertions that is supported can be found here but here’s the ones that I’ve (you might like others…) come to use a lot:

  • x.should.equal(y)
    • hey, I don’t need to explain them. How is that for a great demonstration of the use of readable syntax…
  • x.should.be.true
  • x.should.be.false
  • x.should.startWith(“a string”)
  • not - just negates the assertions. x.should.not.be.equal(y) for example.

In fact, there’s an whole array (.an, .of, .a, .and, .be, .have, .with, .is, .which) of those conjunctions that you could add for readability. Like this example:

user.should.be.an.instanceOf(Object).and.have.property(‘name’, ‘tj’);

I have only used not so far, but I could see that some of the others might be useful.

The trip upsThe things I often forget

There are a few problems that I keep running into. It’s not very flattering for my intelligence that I keep doing it over and over but I thought I’d write it down so that at least know how to fix it the next time.

Assert for null and undefined

If you’re checking that something is null or not, you’re at a bit of loss, since should cannot attach any extension methods to null (since that’s no object I presume). In these cases you need to write the should as a standalone, global method. Here’s an example:

Forgetting the require

Another, very basic thing, that trips me up is that I forget to add the require statement for should in my test file. I presume I forget this since you don’t have to add one for mocha.  My feeble mind seems to reason “Hey, great! In tests we apparently don’t need to add any requires.” Let’s say you have the following assertion:

If you don’t add the require-statement for should you’ll end up with an error message like this:

“TypeError: Cannot call method ‘equal’ of undefined”

Luckily it’s easy fixed. Add this at the top of your test-file:

var should = require(“should”);

“This way assert you should” - Yoda (and Rob Conery)

One last thing that I’ve found very useful. In the testing episode of the  excellent TekPub series on Angular Rob Conery have a short little part on how he writes assertions (or it-functions in the case of mocha et al). I have done the same journey as he and picked up, what he calls, the Yoda way.

Up to then I used to write:

it(“should be defined”), it(“should validate presence of email”)

But really why put the “should” in there? In the immortal words of Yoda:

Do or do not. There is no try!

Or in our case:

Do or do not. There is no should!

And just removing the “should” from the assertions clears them up quite a lot.

it(“is defined”) it(“validates presence of email”)

This also makes for nicer reports, like this:

Twitter, Facebook