DEV Community

Cover image for Run faster tests in Node.js with Baretest
Brian Neville-O'Neill
Brian Neville-O'Neill

Posted on • Originally published at blog.logrocket.com on

Run faster tests in Node.js with Baretest

Written by Abdulazeez Abdulazeez Adeshina✏️

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
Enter fullscreen mode Exit fullscreen mode

And use it as such:

const test = require('baretest')
      assert = require('assert')
Enter fullscreen mode Exit fullscreen mode

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.

LogRocket Free Trial Banner

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

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:

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

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!")
})
Enter fullscreen mode Exit fullscreen mode

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!")
})
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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

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")
})
Enter fullscreen mode Exit fullscreen mode

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

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")
})
Enter fullscreen mode Exit fullscreen mode

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

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()
Enter fullscreen mode Exit fullscreen mode

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

node test.js
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

touch jest.test.js
Enter fullscreen mode Exit fullscreen mode

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

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

"test": "jest jest.test.js"
Enter fullscreen mode Exit fullscreen mode

Next, we run our tests:

npm run test
Enter fullscreen mode Exit fullscreen mode

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 show GraphQL requests in production

While GraphQL has some features for debugging requests and responses, making sure GraphQL reliably serves resources to your production app is where things get tougher. If you’re interested in ensuring network requests to the backend or third party services are successful, try LogRocket.

Alt Text

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 GraphQL requests to quickly understand the root cause. In addition, you can track Apollo client state and inspect GraphQL queries' key-value pairs.

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. Start monitoring for free.


The post Run faster tests in Node.js with Baretest appeared first on LogRocket Blog.

Top comments (0)