Game of Life in JavaScript - Part 2
Roll up, roll up. You waited a whole 2 days for this and here it is - the second part of my “n” part series on writing a Game of Life implementation using JavaScript and Jest, the testing framework.
If you’ve come to this article directly, don’t forget to read part 1 here so that you know where I began with this series.
On today’s menu is getting Jest installed and writing a couple of basic tests so that you can proudly tell your friends and family that you know TDD.
Installation
To be fair, the online getting started section is really good, but that won’t write a blog post, so here’s my take on installing this fantastic framework.
To begin, we’ll use NPM to install the software.
1 | C:\>mkdir game-of-life |
NPM will ask you a whole bunch of questions which you can fill in if you like, but for simplicit, I would just press enter for each question. At the end, type: “yes”.
1 | C:\game-of-life>npm init |
If you don’t have npm
installed (you will soon realise), you can go and grab it here. If so, do that now and try the command above again.
Looking through the output, near the end of the file where you see the JSON (the stuff inside curly braces), we have the package.json
contents.
Let’s now add to that by installing Jest, the test framework.
1 | C:\game-of-life>npm install --save-dev jest |
The --save-dev
flag means that we only want to use this for development purposes - i.e. don’t install into production. Realistically, we won’t be creating the next Amazon with this package, but it does keep things separate at least. Lastly, jest
in the command line above is the package name, as you might have guessed.
After installation, you will see something similar to this:
1 | C:\game-of-life>npm install --save-dev jest |
The deprecations aren’t a huge problem and the vulnerabilities might be were we to make this public, but we’re fine for what we are doing here. It’s a small, personal, project that will live on our hard-drives.
At this point, we will now have a folder and file in our directory. On my Windows system, here’s how it looks, but if you are using a Mac or Linux, it will differ a little.
1 | C:\game-of-life>dir |
So far, so good. A quick peek inside the package.json
tells us what that command just did so let’s take a look now.
1 | C:\game-of-life>type package.json |
We can see that our installation of Jest is in the development section and that it is already up to version 26.6.3. When you do this, you will probably see a different number, and that’s OK. Things change rapidly in the JavaScript world.
We’ve got the software installed in our folder (in node_modules
), but we can’t run it yet, at least not based on how we’ve installed it. The next step is to add a command into the package.json
file tell it that when we want to run a test, it should use jest.
Whilst package.json
is open in your text editor, find this line:
1 | "test": "echo \"Error: no test specified\" && exit 1" |
and change it to:
1 | "test": "jest" |
Save that.
Running the Test Harness
We can test that is now working by typing the following onto the command line:
1 | C:\game-of-life>npm test |
Your first thought might be that it has all gone wrong but no, actually everything is fine. Take a look at the line which reads “No tests found, exiting with code 1”; we just don’t have any tests for it to find and run, so we’re good. Let’s do that next.
So what test files is it actually looking for? The regular expression above (all those astericks) is looking for any files named test.js or something.test.js, where something
is a valid filename segment. Here’s some examples:
1 | test.js |
Adding a Simple Test
For now, create a file called basic.test.js
and add the following into it:
1 | test('two plus two is four', () => { |
This is straight out of the guide and is an example of a matcher
. That’s what Jest names the way in which you are testing a value to be true or otherwise. In this case, the toBe()
function is a bit like an equality operator in that it is testing that 2 + 2
will be 4.
Reading the function from top to bottom, we could interpret it this way:
I want to create a test with the label: “two plus two is four”. This test will expect that when you add 2 plus 2, the answer will be 4.
Run your test harness - the name we give to the runner or system that will execute your tests - with the following command:
1 | >npm test |
All being well, you should see something like this:
1 | PS C:\game-of-life> npm test |
Yours will probably be nicely colour-coded, but either way, what a lovely thing to see your tests pass (legitimately!).
Seems quite straight-forward right? Let’s try a different matcher - something to do with strings instead of numbers.
Create another test file, this time named: string.test.js
and place the following test code inside:
1 | test('there is no I in team', () => { |
Here, again from the docs, we’re using regular expressions to search for strings inside other strings. What makes this first test a little different is the use of the not
function which inverts the nature of the matcher. Stick it in front of a toBe()
and it’s the same as saying it is not toBe()
.
Before you run these tests, what do you think will happen? This is the output from my machine:
1 | PS C:\game-of-life> npm test |
I’ve deliberately left the other test file in there (basic.test.js
) so that you can see what happens if Jest can find others. Here, it tells us that both test files passed and that 3 tests in total ran: the 1 from basic.test.js
and 2 others from string.test.js
.
There are a whole bunch more matchers which you can read about here but we’ll cover those as we need them when we return to the very exquisite Game of Life, in part 3. One more thing you might want to take a look at is this great intro video on Jest by Karl Hadwen; it covers a bunch of stuff from very simple testing to some quite advanced mocking etc.
Hi! Did you find this useful or interesting? I have an email list coming soon, but in the meantime, if you ready anything you fancy chatting about, I would love to hear from you. You can contact me here or at stephen ‘at’ logicalmoon.com