Abdulazeez Abdulazeez Adeshina Software enthusiast, writer, food lover, and hacker.

Run faster tests in Node.js with Baretest

5 min read 1438

Run Faster Tests In Node.js With Baretest

Testing is an important part of application and software development. It ensures that our web apps function and work as expected.

In the JavaScript ecosystem, we have multiple testing libraries and frameworks, and today, we’ll be looking at Baretest, a new, minimalistic testing library that considers itself an alternative to Jest.

What is Baretest?

Baretest is a minimal, fast, and simple JavaScript test runner. In this modern software development era, where speed is very important, Baretest boasts of incredible speed as compared to Jest.

You can install it from npm:

npm i --save-dev baretest

And use it as such:

const test = require('baretest')
      assert = require('assert')

Baretest API methods

Baretest, being a minimalistic library, makes use of Node’s assert library. The assert module is a testing library in-built to Node with several methods for asserting passed arguments and statements. Baretest mainly act as a wrapper, while the real test is done with by the assert module.

The Baretest library has a number of methods:

test(name, fn)

This method initializes a test suite with the test’s name and corresponding function. For example, if we want to test that 1 is equal to 1, the following code helps us do so:

const test = require('baretest')
      assert = require('assert')

test('Proove that 1 == 1', () => {
  assert.ok(1 == 1)
})

test.only(name, fn)

The .only(name, fn) method accepts a name for the test and a function that contains the test itself. The method is used to instruct the test runner to run only this test and ignore the others.

Say, for example, we want to test a sum function, but we do not want to run other tests alongside it. We simply use the .only(name, fn) method, as in the example below:

We made a custom demo for .
No really. Click here to check it out.

const test = require('baretest')
      assert = require('assert')

test('Proove that 1 == 1', () => {
  assert.ok(1 == 1)
})

test.only('1 + 1 should equal 2', () => {
  assert.equal(1+1, 2)
})

When the above test is run, the sum test is the only one that is executed.

test.before(fn)

This method accepts a function as an argument. This function is executed before all supplied tests. For example:

test.before(() => {
  console.log("Yay! We're about to start!")
})

test.after(fn)

This method accepts a function as an argument, and just like .before(fn), it executes after the supplied tests have finished running. For example:

test.after(() => {
  console.log("It was a successful test!")
})

test.skip(name, fn)

This method is used to skip test cases and is useful for temporarily omitting tests.

test.run()

This method is invoked after writing all tests cases. The method runs the supplied tests in the test file:

const test = require('baretest')
      assert = require('assert')

test.before(() => {
  console.log("Yay! We're about to start!")
})

test('Proove that 1 == 1', () => {
  assert.ok(1 == 1)
})

test('1 + 1 should equal 2', () => {
  assert.equal(1+1, 2)
})

test.after(() => {
  console.log("It was a successful test!")
})

// Run test!

test.run()

Testing with Baretest

So we’ve briefly discussed the methods in the Baretest library. In this section, we will be testing some simple stack operations.

First, we’ll build the Stack data structure and then write tests for its operations. If you don’t know what a stack is, you should read this article on Data Structures.

Setup

First, we will create a folder, initialize it with npm, and then create the files needed for our test activity:

mkdir baretest & cd baretest
npm init -y & npm i --save-dev baretest
touch {stack, test}.js

Next, we implement the Stack data structure:

class Stack {
  constructor() {
    this.items = [];
  }

  push(item) {
    this.items.push(item);
  }

  pop() {
    return this.items.length == 0 ? "Not enough items!" : this.items.pop()
  }

  peek() {
    return this.items[this.items.length - 1];
  }

  isEmpty() {
    return this.items.length > 0 ? false : true 
  }

  clear() {
    while (this.items.length != 0) {
      this.items.pop()
    }
  }

  length() {
    return this.items.length
  }
}

module.exports = new Stack()

Having implemented our data structure, we move on to writing our test. We will be testing the push() , pop(), and length methods.

test.js

First, we import baretest, the assert module, and the stack:

const test = require('baretest')('Stack Operation Testing'),
  assert = require('assert')
  books = require('./stack')

Next, we write a test for our .push(), .pop(), .peek(), and .length() methods:

test('Add a new book', () => {
  books.push("Engineering Maths")
  assert.equal(books.peek(), "Engineering Maths")
})

In the test above, we pushed a new book into our books stack and confirm using the assert.equal() method. We will be using the assert.equal() method subsequently.

Next, we remove the book using the .pop() method and confirm that the length of our stack is 0:

test('Remove the book', () => {
  books.pop()
  assert.ok(books.length() == 0)
})

In the code above, we used the assert.ok() method that tests whether a given expression is true.

Next, we add a new book and write another test to ascertain that the stack’s top element doesn’t point to the passed value:

test('Add another book', () => {
  books.push("Engineering Thermodynamics")
  assert.equal(books.peek(), "Engineering Thermodynamics")  
})

test('Shoud false', () => {
  assert.notStrictEqual(books.peek(), "Engineering Maths")
})

We used the .notStrictEqual() method to show that the top of the stack isn’t equal to “Engineering Maths.”

Next, we add a random book and test to confirm the length of the stack:

test('Add a random book', () => {
  books.push("Random book")
  assert.equal(books.peek(), "Random book")
})

test('Confirm stack length', () => {
  assert.ok(books.length() == 2)
})

We have now completed the tests for basic operations. The failing of these tests above means that our implementation is wrong or we have made a mistake somewhere. If the result is not as expected, you can use the errors thrown in the console for guidance.

Finally, we call the .run() method:

test.run()

The next step is to run the test file to see the outcome of our tests:

node test.js
Baretest Test Passed Confirmation
Our test passed!

The speed of the test is really superb!

Baretest vs. Jest

Baretest considers itself an alternative to Jest and in this section, we’re going to discuss some of the differences between these libraries under three major factors:

  1. Speed: Speed is an essential feature of any library or framework. When run with Jest, the above test had a runtime of about 3x that of the Baretest runtime.
  2. Complexity and features: Baretest boasts of its minimalism, and thus, it lacks advanced features like parallelization, coverage reports, or mock functions. Jest, however, supports these features.
  3. Size: Baretest is written in 12 lines of code and has only one dependency, while Jest has over 70,000 lines of code and multiple dependencies.

Baretest vs. Jest: Speed test

The time it took Baretest to run the test above is:

Baretest Test Time

To determine the timing in Jest, we will have to write the test cases in the Jest wrappers, too. First, we will install Jest as a dev dependency:

npm install --save-dev jest

Next, we’ll create a test file for Jest and then write our tests:

touch jest.test.js

jest.test.js

const books = require('./stack')

// Describe the tests.
describe('Test the stack data structure implementation', () => {
    beforeAll(() => {
        books.clear()
    })

    test('Add a new book', () => {
        books.push("Engineering Maths")
        expect(books.peek()).toBe("Engineering Maths")
    })
    test('Remove the book', () => {
        books.pop()
        expect(books.length()).toBe(0)
    })
    test('Add another book', () => {
        books.push("Engineering Thermodynamics")
        expect(books.peek()).toEqual("Engineering Thermodynamics")
    })
    test('Should return false', () => {
        expect(books.peek()).not.toEqual("Engineering Maths")
    })
    test('Add a random book', () => {
        books.push("Random book")
        expect(books.peek()).toBe("Random book")
    })
    test('Confirm stack length', () => {
        expect(books.length()).toBe(2)
    })
})

To run our Jest test, we need to modify the test command under scripts in the package.json file:

"test": "jest jest.test.js"

Next, we run our tests:

npm run test

One noticeable behavior is Jest’s startup time.

Jest Test Time

From the screenshot above, it took Jest 12.923 seconds to run the same test that Baretest ran in 0.178 seconds.

Conclusion

This article should give you a basic understanding of what Baretest is and what it’s capable of. The major win for Baretest is its speed, as it depends on Node’s assert module to execute test cases. However, Baretest lacks complex features and, as a result, cannot be used for large-scale coverage tests.

On the other hand, Jest has the complex features but drags a bit even in the smallest test case. Since Baretest is still under active development, more features are expected to be added, and who knows if it might overtake Jest in the coming years? You can find all the code used in this article here.

200’s only Monitor failed and slow network requests in production

Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third party services are successful, try LogRocket. https://logrocket.com/signup/

LogRocket is like a DVR for web apps, recording literally everything that happens on your site. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. .
Abdulazeez Abdulazeez Adeshina Software enthusiast, writer, food lover, and hacker.

Leave a Reply