Automated testing with Jest 🤖
Tags: opensource, testing, javascript
Published: 2021-11-13 02:09:12

## Introduction

Managing code complexity can be difficult. I mean, you already added comments inside your codebase, wrote detailed documentation, and even set up static analysis tooling to keep your consistently formatted. But even so, somehow, your code still breaks. Human mistake? Bugs? It is hard to know. You can try adding safety nets to handle the errors, but can you even catch all of them? 

Luckily, we have tests. Testing allows developers to prevent their existing code from breaking, identifies bugs, and tracks easy to miss edge cases. The added extra layer of protection ensures that your project, small or large, will evolve in the right direction when new changes are introduced.

## What is Jest? 

Since I wrote my project in JavaScript, I can choose between Mocha and Jest. In the end, I decided to go with the later option, as I have a bit of experience with it before. 

A quick overview: [Jest](https://jestjs.io/) is a JavaScript testing framework that focuses on simplicity. It allows you to write tests and test suites in files ending with `.spec.js` or `.test.js`.

To begin, start by installing Jest using [npm](https://www.npmjs.com/package/jest):

```bash
npm install --save-dev jest
```

Then, create a file with the ending as mentioned above to begin testing.

## Writing tests

Because my project is a static site generator, I'll be testing the parsing logic that converts text to HTML.

First, I started by exporting and importing the necessary functions:

- `generate-html.js`

```js
module.exports = { generateHtmlBody, ... }
```

- `generate-html.test.js`

```js
const { generateHtmlBody, ... } = require('./generate-html')
```

With everything up and ready to go, I began thinking of how I should test the logic. Here are some example scenarios:

- Checking if the paragraphs are wrapped in `<p>` tags. A paragraph is identified by having one or several consecutive lines of text, followed by a single blank line as a paragraph limit.

- Checking if the title is wrapped in `<h1>` tags. A title is defined by being the first line followed by 2 blank lines.

Thus, my test should look something like this:

```js
describe('generateHtmlBody tests', () => {
  test('returned html paragraph should be wrapped in <p> tag', () => {
    const data = 'Hello World!';
    const extName = '.txt';
    const title = null;

    const result = generateHtmlBody(data, extName, title);
    expect(result).toMatch(new RegExp(/<p>(.+?)<\/p>/g));
  });

  test('returned html title should be wrapped in <h1> tag', () => {
    const data = 'Hello World!';
    const extName = '.txt';
    const title = 'a title';

    const result = generateHtmlBody(data, extName, title);
    expect(result).toMatch(new RegExp(/<h1>(.+?)<\/h1>\n\n/g));
  });
});
```

## Running the test

Great! We now have a file that tests for specific functionality, but how do we run it?

With Jest, setting up test scripts was not too difficult. Inside "package.json," add the following scripts: 

```json
{
  scripts: {
    "test": "jest --",
    "test:watch": "jest --watch --",
    "coverage": "jest --collectCoverage --"
  }
}
```

- `npm test [file]` will run the test on the specified file.
- `npm run test:watch [file]` will also run the test but in **watch** mode, which automatically re-runs when changes are made.
- `npm run coverage [file]` will generate a code coverage report.

## Conclusion

The experience of writing tests has forced me to challenge my way of thinking. Specifically, I had to abandon the thought of writing good tests every time and accepting that there would always be room for improvement. After all, there is no "done" in programming, only "version 1, 2, 3, and many more."


> Free yourself from the need to be perfect.  Embrace “better than it was” and continue living in that