Post/Code

HomeAboutUsesNow

Node.js Testing with Mocha, Chai, Sinon and Istanbul.

Unit tests seem to be like flossing - everyone says you should do it... but do you really?

Unit testing has been on my development todo list for the past while and despite a few false starts, I have not really managed to get to grips with it. Today I decided to change all that and spent the day thrashing out some tests and here are some of my initial thoughts:

  • First and foremost - you need to actually build something to be tested. For me, I started a new Node.js/Express API from scratch and completed a set of CRUD operations on a route with the goal being that would be one complete set of routes that needed to be tested in completion. A unit of units if you will. On to the details:
  • Mocha is a test runner. That is to say, it is the frame upon which your tests hang. Mocha is the delivery guy to your pizza.
  • Chai is a TDD/BDD style assertion framework. In English, it means you can write your tests in a natural-language-like syntax.
  • Sinon is for spies, stubs and mocks. Basically, this means Sinon wholesale replaces segements of code in order to effectively test. Without Sinon you are basically doing integration tests.
  • Istanbul is a code coverage tool. This means, it compares your test code to your overall code and lets you know how much of your code is 'covered' by tests.

Now, with that out the way, you basically have 4x types of testing to my mind:

  1. Naive testing: This is what you probably do day to day. Manually running your API tests in Postman/Insomnia or clicking through your application.
  2. Unit testing is isolating a 'unit' of your code and testing it alone without dependencies or by mocking these dependencies. The smaller the better.
  3. Integration testing is basically taking parts of your application and testing them together. For example, when testing your API you are testing your routes with the database.
  4. End-to-end testing is (hopefully) programmatically going through your application (not something I have covered yet - Selenium seems to be a widley used tool here)

Now, my path to testing has been driven primarily by need. Working on applications that run in multiple markets, with multiple configurations in the cloud means that with each new market or entity, you have one more application area to test, and it quickly gets out of hand when you are running UAT and Production environments with agile release schedules. As such, I have gotten to the point where I need tests to back my team and I up when it comes to quality control. There just is not enough time to test every possible area with every code change and have the confidence you should that you have not broken something somewhere. While I am ashamed to admit it, I have been cowboy coding for far too long. Not cowboy cowboy, but the reality is that with the fast pace of development these days, one needs to have the following backups:

  • Linting (to help you code better in the moment - more on this soon)
  • Testing (to help you help yourself after the moment)

Something to keep in mind when testing is to have a 'validation' mindset. What I mean by that is, you need to be thinking about what you are testing with a hygenic mindset. Basically, if you have a round hole, you are specifying what fits in that round hole as well as specifying what does not fit. Essentially, you are being pedantic to some level.

Something that does come to mind as one goes through this is that testing is not very straightforward. It is kind of obscure at times and seems strange to get your head around. But, even if you find it uncomfortable, stick with it, because, I think, even the process of going through this, and getting yourself to think about your code from a different perspective will on some level, improve your code regardless of how the tests go.