Test Driven Development in TypeScript

Unit Testing TypeScript

I was recently asked by one of my students on my Java TDD course whether I had any material relating to test driven development and TypeScript.

I’m a big fan of TypeScript, and I do have a number of things planned relating to TypeScript for my new soon to be released membership site over at TheDeveloperCollective.com, but didn’t have anything quite ready to release over there, so decided to create this article in the meantime.

If you haven’t heard of TypeScript, then you can head over to the typescriptlang.org page for more info, but basically think of it as JavaScript combined with (optional) typing. Typing as in type safety, not more fingers on keys.

It’s a typed superset of JavaScript that can be compiled to JavaScript, and for me is something I have found can give a real development efficiency and quality boost, though it’s not without challenges of it’s own.

So, in this post, I want to talk about how we could unit test and therefore TDD a pure TypeScript project.

There are a few different approaches we could take.

We could for instance just use the TypeScript compiler to emit JavaScript files, and stick with plain JS testing, but that kind of defeats the purpose of using TypeScript if we don’t extend it to our test code too. I have seen this done, more commonly on mixed JS and TypeScript projects, but why wouldn’t we want the type safety there too?

You could also use the excellent babel for transpiling the code, but again, I think that is overkill for this particular use case.

Instead, I’ll demonstrate a relatively simple approach using the ts-node library to integrate with the mocha test framework.

My Environment

As far as my environment is concerned, I’m currently running the latest version of node.js, which at time of writing this is 9.8.0. For my IDE, I’m using Visual Studio Code, because it has excellent TypeScript support, so I get nice help from IntelliSense as I’m working.

I’m also assuming for this article that we want to be running our tests under node.js, rather than in a browser of any form. To be honest, even when testing JS/TypeScript that would be run in a browser, I would normally test in a node.js runtime as it’s far easier to manage, and quicker to run and work with.

Creating a project

For this article, I want to demonstrate setting all of this up from scratch, introducing code in a test driven way, though if you have an existing project you are working with, you can follow the exact same approach.

For this demonstration, I’m not being massively original, but I’m going with a simple calculator. It’s a simple example everyone should be familiar with, and demonstrates testing something that has it’s own internal state.

The techniques demonstrated could be applied to any kind of problem.

So, let’s get coding.

My first step is to create a new project. I’ll create a new directory for my project, and just use npm to create a skeleton package.json file.

 

After filling out a bit of info, we will have a basic package.json we can start working with.

 

We won’t worry about some of the details just yet, such as test command. We will add those once we are ready. The main entry of index.js also isn’t important as we are only going to be executing code via unit tests.

NPM Packages

So, first things first, let’s sort out our dependencies.

For this example, I want to use mocha as the test framework, with chai for assertions using the expect style of assertions.

You could use different assertion style or library. It really is up to you as to which you prefer. For me, I like both expect and should, with should for me being slightly more natural, but expect being more consistent, especially when concerned with null or undefined values.

We will of course, also by using the typescript package, as well as a node runner for typescript, ts-node. If you haven’t encountered this before, then ts-node is worth taking a look at. As well as helping us run our tests, it also has an interactive REPL which can be really useful during development.

 

So, we are using npm install, telling it to update the devDependencies section of our package.json.

You will notice from above, as well as the packages mentioned, we are also installing the type definitions for chai and mocha, so that they will play nice with our TypeScript compiler and IDE to give us the most benefit of using TypeScript.

If this all goes well, you should see an output that looks a bit like this:

 

ok, so now we have our base setup, we can start looking at some code.

Starting with the test

We are taking a test driven approach, so the logical place is the test. Let’s start by creating a test file, making sure we can execute tests, and then working towards our first failing test!

I want to keep my application source code and test source code in different directories. You don’t have to. I am seeing trends where people do like to keep them in the same directory, with a different suffix, maybe .spec.ts, .test.ts, or some variations involving underscores etc. It’s really up to what you prefer and what your motivations are.

So, I’ll create a src and a test directory

Next, I’ll create a test file, which can just be empty for now

Now, let’s make sure we can execute tests.

For this, let’s edit the test line in our package.json, and change it like so:

We can now verify that we can run tests, like by running

You should see a test run with unsurprisingly 0 tests passing as we don’t have any yet!

We can also execute mocha, and have it watch our test files for changes by passing the -w option to Mocha like so:

You should see the same output as before, but this time, mocha will not terminate, and will instead monitor for changes.

So, now we have our tests running, albeit with no actual tests to execute, but the important thing is we have verified this process works.

TDD

Now we can start to develop our test and application code together.

If you want to skip straight to the full test and application code then you can see all of that below, but to illustrate how I would go about creating that in a test driven way, see the screencast below, where I will rapidly iterate between test and app source code to develop a basic calculator class.

Completed test and application code

ok, so hopefully you have watched the video above, but if you wanted to jump straight to the code, that’s fine too, but I think the video is worth a watch later if you have a spare couple of minutes.

So, here is the completed test code

 

And now the application code being tested

 

So, hopefully there’s nothing too surprising there. As mentioned before, I’m using mocha as the test framework with chai expect for assertions.

It’s obviously only showing really basic functionality as far as the application code itself is concerned, but not matter how complex the application code is, the same approach can be used.

And all of this is being done in pure TypeScript. Aside from any dependencies we are pulling in, there is no straight JS. We are using type definitions for mocha and chai in order to integrate them nicely into our TypeScript project.

I hope if you are looking to setup a new TypeScript project, or start adding tests to an existing TypeScript project, this example is useful to you.

If you want to download the source code for yourself, then just checkout the git repo here – https://github.com/thedevelopercollective/tscalc

Leave a Reply