should.js is my assertion library of choice when unit testing my node.js and Titanium projects, for a few reasons:
- Works flawlessly with mocha. Not a surprise since they have the same author.
- Works in node.js, browser, and Titanium.
- Extremely readable and expressive.
- Extendable to be even better at #3, if you know how.
Here I’d like to explain exactly how you can do #4. I was originally inspired by this post, but the method therein made available only a small subset of should.js’s assertion functionality. To quote Freddy Mercury, ♫ I want it all, and I want it now. ♫
Test Case
Let’s say you have a configuration file that must abide by this format:
config.json
1 2 3 4 5 |
|
We’d like to strictly enforce that format using assertions. Lots of them. A ridiculous amount in fact. Yes, it could be done much more tersely, but it helps express the point of customization. Let’s do it in a mocha BDD structure.
No Custom Assertions
test.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Here we’re effectively asserting the format of the configuration, but we’re losing a bit of the expressiveness of should.js in the process. We’ve essentially got 11 lines of assertion code when what we really just want to say is
this object should be a valid config
In addition, what if we want to validate the config at the beginning of many tests and keep it DRY? It’s undoubtedly getting messy fast here.
Custom Assertions
Let’s say “this object is a valid config” exactly by creating a custom assertion within should.js. And let’s go one step further and show how this custom assertion can be placed in a separate module. This will make our tests as simple, clean, and expressive as possible.
I’m going to explain some of the should.js assertion internals inline, but for more details I’d highly suggest perusing the source code, particularly the extensions.
assertions.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
and now are unit test looks like this:
test.js
1 2 3 4 5 6 7 8 9 10 11 |
|
Aaaaaahhh, now that is nice. It should be pretty clear at this point how custom assertions can improve the readability and scalability of your test suites. It becomes clearer as your test suites grow.
Examples
Just in case you aren’t convinced, here’s a few more examples of using custom assertions in should.js to execute critical testing while preserving maximal expressiveness.
Titanium Proxies
Remember, Titanium proxies don’t play well with should.js, so you need to wrap them manually before running assertions.
assertions.js
1 2 3 4 5 6 |
|
usage
1 2 3 4 5 |
|
Format Validation
Here’s a simple case of validating that a given object is an XML string using xmldom.
assertions.js
1 2 3 4 5 6 7 8 9 10 |
|
usage
1 2 3 4 5 |
|
Complex matchers
You can even do some really complex validating using functions instead of getters. Here’s an example of asserting that a chunk of Javascript will be be minified into an expected string using uglifyjs.
assertions.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
usage
1 2 3 4 5 |
|
Resources & Links
- should.js on github and lots of assertion examples
- mocha website and github
- “Custom assertions with should.js” by Andrew Swerlick