Use Tests with TypeScript

4 min read

Table of Contents:

Title Image for the Article

Introduction

Test your code with conditions you set to see if the functions will function correctly. Let's learn how to use Jest with TypeScript and see if our functions work!

https://github.com/cobb208/WeightCalculatorTests

What are Tests?

Creating tests allows for you to ensure your code operates the way you want it to. Testing libraries allow you to come up with combinations of data to ensure no irregular operations happen. Thankfully, libraries have already been created to take the heavy work out of testing.

Existing Project

For this project we are going to use another article's project to build on top of it.

Push Weight with TypeScript

Pull the code from the other project and we will build off it.

Refactor

Now we are going to take information out of the index.ts file and seperate it. While this is not going to follow a folder standard, it will follow a file structure. We will create two files:

touch funcs.ts
touch models.ts

Funcs.ts

The funcs file will house our testing function. Instead of our code just existing in the index file, we will put it into its own file.

// index.ts
// this file is not needed for this article but will be used later on.
if(parseInt(process.argv[2]) == NaN || process.argv[2] == null)
{
    console.log('Please enter a valid barbell weight');
    process.exit();
}
let barGoal = parseInt(process.argv[2]);
let barWeight = process.argv[3] ? parseInt(process.argv[3]) : 45;

Models.ts

The models will hold the type we created. A model is a representation of data, in JavaScript and other languages you will see classes. For this, we will continue to use a type for its simplicity.

type PlateResult =
{
    weight: number,
    count: number
};
export default PlateResult;

The export at the bottom will allow other files to import it. There are several ways to export items in a JS/TS file.

Funcs.ts

None of the logic in here is new just a rename to put all the logic inside of a function.

import PlateResult from "./models";
function calculateRequiredPlates(weight: number, barbellWeight = 45): PlateResult[]
{
    const WEIGHT_VALUES = [
        45,
        35,
        25,
        15,
        10,
        5,
        2.5
    ];
    let results: PlateResult[] = [];
    let barbellGoal = weight - barbellWeight;
    for(let i  = 0; i < WEIGHT_VALUES.length; i++)
    {
        let count = Math.floor(barbellGoal / (WEIGHT_VALUES[i] * 2));
        count *= 2;
        results.push({
            weight: WEIGHT_VALUES[i],
            count
        });
        barbellGoal -= WEIGHT_VALUES[i] * count;
    }
    return results;
}
export { calculateRequiredPlates }

The function will return an array of the PlateResult type. Again, everything else works the same as the previous article.

Install the Testing Framework

The framework used for testing is: JestJS and we will follow the instructions provided by them.

npm install --save-dev jest
npm install --save-dev babel-jest @babel/core @babel/preset-env
npm install --save-dev @babel/preset-typescript
npm install --save-dev @types/jest

These commands will install Jest, Babel, and the type system for TypeScript (so we can continue our project's theme).

Now we need to create a couple files:

touch funcs.test.ts
touch babel.config.js

Babel Config

module.exports = {
    presets: [['@babel/preset-env', {targets: {node: 'current'}}],
    '@babel/preset-typescript',
    ],
};

Babel has a lot of configuration, this file will have this information to tell Babel to use the TypeScript module and the current version of Node of the package.

# funcs.test.ts
import { calculateRequiredPlates } from './funcs';
import PlateResult from './models';
const result135: PlateResult[] = [
    { weight: 45, count: 2},
    { weight: 35, count: 0},
    { weight: 25, count: 0},
    { weight: 15, count: 0},
    { weight: 10, count: 0},
    { weight: 5, count: 0},
    { weight: 2.5, count: 0},
];
const result220: PlateResult[] = [
    { weight: 45, count: 2},
    { weight: 35, count: 2},
    { weight: 25, count: 0},
    { weight: 15, count: 0},
    { weight: 10, count: 0},
    { weight: 5, count: 2},
    { weight: 2.5, count: 2},
];
const result315: PlateResult[] = [
    { weight: 45, count: 6},
    { weight: 35, count: 0},
    { weight: 25, count: 0},
    { weight: 15, count: 0},
    { weight: 10, count: 0},
    { weight: 5, count: 0},
    { weight: 2.5, count: 0},
]
test('135 on a 45 bench should be: 2 45s', () => {
    expect(calculateRequiredPlates(135)).toStrictEqual(result135);
});
test('220 on a 45 bench should be: 2 45s 2 35s 2 5s, 2 2.5s', () => {
    expect(calculateRequiredPlates(220)).toStrictEqual(result220);
});
test('315 on a 45 bench should be: 6 45s', () => {
    expect(calculateRequiredPlates(315)).toStrictEqual(result315);
});

This will test our function to ensure it meets values we know for a fact are correct. The format for the testing is towards the bottom of the file. The arrays are just placeholder data that is correct (what we expect).

toBe vs toStrictEqual

ToBe is used to check singular values like integers against each other. When items such as types or objects need to be tested they will use toStrictEqual. This ensures that all fields of the object are correct.

Run the Test

In our package.json we will modify our "scripts" line to be:

  "scripts": {
    "test": "jest",
    "build": "tsc index.ts",
    "prestart": "tsc index.ts",
    "start": "node index.js"
  },
  "jest": {
    "transform": {
      "^.+\.[t|j]sx?$": "babel-jest"
    }
  },

The ""jest": { transform..." it is on the same level as the "scripts" object. If you copy and paste this over your old "scripts" tag it will work. This is just for you to understand it is not encapsulated into the scripts. The scripts has an added function we will use call "jest" that we call with "test".

Now in the terminal we will run:

npm run test

It will produce for you:

> weightcalc@1.0.0 test
> jest
 PASS  ./funcs.test.ts
  ✓ 135 on a 45 bench should be: 2 45s (4 ms)
  ✓ 220 on a 45 bench should be: 2 45s 2 35s 2 5s, 2 2.5s (1 ms)
  ✓ 315 on a 45 bench should be: 6 45s (1 ms)
Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        0.787 s, estimated 1 s
Ran all test suites.

This shows a pass of all the tests. If you do not get a pass, read what it tells you and start double checking the work to make it work!

What Now?

Make other tests see if you can create a test to break it and come up with a solution of how to fix it. Stay tuned for more content as we continue to build on this!

Recent Articles

Push Weight with Python

Create a simple terminal application that can let you know how much weight you need to put on the ba...

Validate Forms in TypeScript

Relying on HTML to validate your forms is just one step in ensuring visitors enter their information...

Automation with NodeJS

NodeJS can help you automate simple tasks. Being a web developer you can achieve the same goals as o...

Automation with Python

Python can take boring tasks away from you so you can continue to do other things. It is a scripting...

Speed With Cache in WordPress

Most WordPress sites use Apache as their server. Apache has a lot of tools built into it to speed up...

Social Media