DEV Community

Cover image for A Case for Unit Testing and an Intro to Jest
Joanna
Joanna

Posted on

A Case for Unit Testing and an Intro to Jest

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.

"scripts": {
    "test": "jest"
  },
  "jest": {
    "collectCoverage": true,
    "coverageReporters": [
      "html"
    ]
  }
Enter fullscreen mode Exit fullscreen mode

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.

// 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');
  })
})
Enter fullscreen mode Exit fullscreen mode

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.)

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, writing unit tests doesn't provide much instant gratification, but it can save you a lot of pain down the road.

Top comments (1)

Collapse
 
idanarye profile image
Idan Arye