Implementing a Testing Framework
Tags: beginners, opensource, javascript, testing
Published: 2023-11-11 03:04:38

This week I managed to add a testing framework to my open source project, [TILerator](https://github.com/mismathh/TILerator). Since it's a JavaScript project, I decided to use [Jest](https://jestjs.io/) as my testing framework.

<h2>What is Jest?</h2>
Jest is a JavaScript testing framework developed by Facebook, and is widely used for testing JavaScript and React applications. I have been exposed to Jest in other projects and along with having a detailed [documentation](https://jestjs.io/docs/getting-started), it is quite easy to install.

<h3>Setting up Jest</h3>
Jest is needed only for testing purposes so install it as a dev dependency.
```JavaScript
npm install --save-dev jest
```
Next, add a test script to your `package.json` file to be able to run tests using Jest.
```Json
"scripts": {
    "test": "jest --",
    "test:watch": "jest --watch --"
  }
```
Finally, create a testing directory to hold all of you tests.

<h2>Writing Tests</h2>
For my first test, I decided to test out a function that receives a string and checks if a certain `regex` pattern can be matched, and if it can, it adds an HTML `<b></b>` tags to the string. I wrote 5 tests to check on the function's behaviour with certain inputs.
```JavaScript
describe('markdownToHTML tests', () => {
    test('should return a string with <b> tags if part of string is encompassed between **', () => {
        expect(markdownToHTML('**sentence 1**  sentence 2  **sentence 3**')).toBe('<b>sentence 1</b>  sentence 2  <b>sentence 3</b>');
    });
```

In order to test out the core functionality of the program, I also wrote 3 tests to confirm if the correct output would be returned. There was one hiccup when writing these tests, as within the core functions, I used `process.exit()` to exit the program on certain conditions, and if it is called within a Jest test, it will immediately stop the test runner which could lead to incomplete test results.

After reading the documentation to combat this, I found out about  `mock functions` and `spyOn()`. Using mock functions and `mockImplmentation()`, we can define the default implementation of a mock function, and the spyOn() function can be used to monitor the behaviour of the function. Combining these functions resulted in being able to monitor `process.exit()` to check the exit code that was outputted while not actually exiting the process.
```JavaScript
 test("should exit with exit code -1 and error message if invalid file path is given", async () => {
    const mockStdErr = jest.spyOn(console, "error").mockImplementation();
    const mockExit = jest.spyOn(process, "exit").mockImplementation();
```
The testing commit can be found here: [fc128e0](https://github.com/mismathh/TILerator/commit/fc128e073795b80cf1ce7474c14c60aaedb530f2)

<h2>Learning Outcomes</h2>
Despite working with Jest before in other JavaScript projects, there was still a lot that I learned on the capabilities of Jest. Additionally, from writing all those tests, I improved my understanding of TILerator. Testing should be a fundamental process that is used within your project to not only identify bugs, but to also create reliable software. If you have a JavaScript project that needs a testing framework, try out Jest!