A Case for Unit Testing and an Intro to Jest
Tags: codenewbie, javascript, testing, wecoded
Published: 2020-01-13 04:46:10

If you're anything like me, when faced with a deadline, you want to jump headfirst into actual coding. Sure, maybe you'll do a little bit of wireframing, or sketch out your API endpoints, but the faster you get to coding, the better -- you've got a lot to do! 

In this post, I'm going to try to make the case that testing is not only worth your time, but will ultimately save you lots of heartache and struggle down the road, because it will force you to thoroughly organize your program by breaking up large tasks into smaller pieces.

I'll also run through a short example of how to write unit tests using the **Jest** framework.

## What is testing, and why unit test?

In the context of coding, unit testing involves breaking down the functionality of a program into its most tiny and digestible *units*, and writing tests that verify that each unit of your code is performing as expected.

At first, it may not seem obvious that testing is useful. After all, doesn't it mean you end up writing *more* code?

That's true. It takes time. But--

### 1. It doubles as documentation.
Test framework syntax is pretty similar to English -- closer than your vanilla programming language, at least. Because of this, test functions are almost a literal explanation of what a given function should do! Pretty handy for your future self and other programmers reading your code.

### 2. You can't always predict the complexity that can sneak up on you.
As programmers, we should remain humble, and assume that we'll sometimes get confused on the path towards our goal.

Code can start off digestible, but it can easily grow in complexity. We should use whatever tools we can to avoid being overwhelmed by that complexity. Testing is one such tool.

### 3. Unit testing forces you to modularize your code and organize your thoughts.
Ideally, testing will result in you breaking down your program into the smallest possible units, and *really* digging in to what you expect each unit to do. Not only will this make your code less brittle, but it will force you to have a deep understanding of how each section of your code works, and how all of it works together.

## Testing frameworks

You technically don't need a framework to run tests, but they make the process super convenient. There are a several reliable testing frameworks out there. I'm going to work with __Jest__ for this example, which is a tool that comes with the Create-React-App boilerplate. It has its own built-in *assertion, spy, stub, and mock libraries*, and also allows you to easily test front end components.

## The basics of Jest

### Setup and syntax

You'll need a `package.json` file. (If you don't have one, run `npm init -y` from your terminal.)

Run `npm install --save-dev jest` and add `jest` to the `test` script in your `package.json`. From here on out, running `npm test` will activate your Jest test suite.

```js
"scripts": {
    "test": "jest"
  },
  "jest": {
    "collectCoverage": true,
    "coverageReporters": [
      "html"
    ]
  }
```
If you've installed a `create-react-app` boilerplate, Jest should already be there in your `test` script for you.

Create a file where you'll write and export the function you're testing. Create another file for your tests. Require the function you want to test in your test file. 

```js
// mySweetFunction.js
const mySweetFunction = () => {
  const somethingSweet = 'sweet';
  return somethingSweet;
}

module.exports = mySweetFunction;

// mySweetFunction.test.js
const mySweetFunction = require('./mySweetFunction'); 

describe('my sweet function', () => {

  test('it should return something sweet', () => {
    expect(mySweetFunction()).toBe('sweet');
  });

  test('it should not return something sour', () => {
    expect(mySweetFunction()).not.toBe('sour');
  })
})
```

`describe()` groups multiple related tests together. `test()` calls each individual test. Both `describe()` and `test()` take two arguments:

1. A string that describes what the particular feature of the function is, or what function we're describing.
2. An anonymous test function

A common way to write a test with Jest is to use the `expect()` keyword with a __matcher__ to compare values. In the example above, `toBe()` and `not.toBe()` are matchers. (There are many matchers to suit your needs. Check them out [here.](https://jestjs.io/docs/en/using-matchers))

## For the love of MPJ, write unit tests!

This is a super brief intro to test writing and why you should invest your time in it. The example I've given here is a small one, and I wouldn't necessarily recommend writing a test suite for a very small program. But for any robust project with multiple moving parts, you should seriously *consider writing tests before you write any other code.*

Like [flossing your teeth](https://youtu.be/TWBDa5dqrl8?t=394), writing unit tests doesn't provide much instant gratification, but it can save you a lot of pain down the road.