Best tools for testing JavaScript code

Mocha? Chai? Jest or Cypress? It’s easy to get lost in the world of JavaScript testing. That’s why we’ve put together this overview on testing for JavaScript developers. Read on to find out how to choose the best tools for your unit and E2E tests in JavaScript.

Why should JavaScript code be tested?

In the era of agile development and continuous integration, it’s crucial for us developers to test our code not only once, but repeatedly. Popular agile methods like test-driven development (TDD) and behaviour-driven development (BDD) rely on testing as a fundamental building block.

So why are tests so central to modern programming? Each program is susceptible to bugs, some of which might show up only after the program’s been deployed. By testing our modules independently and in as many scenarios as possible, we minimise the danger of having to revise entire programs. Tests ensure that we find and fix our bugs early in the development cycle, saving us both time and money.

A nice side-effect of tests written in TDD and BDD is that they’re self-documenting. By reviewing the corresponding tests, any team member can quickly understand what a piece of code is (or at least should be) doing!

What are JavaScript testing tools?

Of course it’s possible to write some of your tests directly in the JS framework of your choice. But you’ll soon get tired of having to write the same boilerplate code over and over again. There’s a much quicker and more elegant way of dealing with tests, and that’s through the use of specialised tools.

What types of tests are there?

Unit tests check the performance of one isolated function or class. Since most programs consist of interactions between modules, isolating a function isn’t trivial. As we’ll see later, JS test procedures offer a number of ways to deal with this issue. Unit tests are further divided into server-side (on the back end) and client-side (on the front end).

Integration tests act as the complement to unit tests. They help us test the way that several components interact. It’s possible that all the components of an integration test have passed our unit tests—but once when we put them together, they don’t integrate as we had expected. Integration tests identify such cases.

Finally, end-to-end (E2E) tests allow us to simulate a full user experience that invokes both the front and back ends of an application. An E2E test usually simulates a user interaction with the application by automating actions like mouse clicks and keyboard input in a web browser. E2E tests are the most complex in the testing cycle and are addressed by special test frameworks.

What test components are there?

When we unit test, we want our tests to run as quickly as possible. We don’t want to wait for a database to respond every time we test a tiny function. Plus, we want to make sure that our unit tests cover only the code we’re testing. Luckily, JavaScript testing offers established protocols that help us with isolating our programs and dealing with dependencies.

The actual test that checks whether a piece of code does what we expect of it is called an ‘assertion.’ When our code turns out true (that is, it behaves the way we want), assertions pass quietly. Faulty code, on the other hand, will cause an assertion to throw an error and alert the developer to a bug in the code.

To deal with external dependencies, we use ‘test doubles’ (a play on ‘stunt doubles’). With test doubles, we may prepare a canned response from, say, a database, that allows us to test whether our code is able to deal with a given value as it should. You’ll often see a distinction between mocks and stubs, but they really both fulfill the same purpose of isolating your code from the outside world.

Sometimes we want to have some meta-information about a test itself. For example: how many times did a function actually run within a given test? To do that, we’ll employ ‘spies.’ A spy wraps the function and returns information about it, telling us more about the inner workings of our code.

So once you have all of your assertions, mocks, and spies in place, does that mean that your test pipeline is complete? Not quite. After all, you’ll want to make sure that you’re really testing all the functionalities of your code. A helpful metric is test coverage: special libraries that check how much of your code is actually covered by your test. For example, if your test only ever tests the if-condition of an if-else statement, how do you know that your program won’t fail when encountering a new condition? While test coverage isn’t a catch-all, it definitely helps to aim for a good score here.

JavaScript test tools

Below we’ll list out the most popular JavaScript test tools, grouped by test category.

Server-side unit and integration tests

Mocha

Mocha is a test framework for Node.js applications. Asynchronous tests (when one component has to wait for another one to issue a command) are an important feature in JS testing, and it’s easy to perform them using Mocha. The framework can combine different kinds of assertion libraries, but its flexibility means that it takes a little longer to set Mocha up compared to other frameworks.

Jest

Jest is another very popular testing framework. It’s maintained by Facebook and can be used to test different JavaScript frameworks, including React, Angular, and Vue. It comes with mocking and assertion libraries, resulting in a configuration that’s much faster than Mocha’s. Developers often praise Jest tests for being particularly quick to run.

Jasmine

A slightly older framework, Jasmine was explicitly designed for testing in BDD. Like Jest, Jasmine is easy to set up and comes with in-built functions for assertions and test doubles. It’s the preferred framework for testing in Angular.

Chai

Chai is an assertion library built for unit testing back-end and front-end code. It can be combined with any JavaScript test framework.

Sinon

Sinon is a mocking tool. This library takes care of your mocks, stubs, and spies. Like the Chai assertion library, it’s usually imported into another test framework.

Client-side unit tests

Once you’re happy with the results of your back-end unit and integration tests, you might want to test the elements of your code that work solely in browser. A test runner will help you test your front-end elements in a variety of environments. A popular test runner choice is Karma. It was written by the Angular JS team and can be used out-of-the-box for running tests written in Mocha, Jasmine, and QUnit (another JavaScript unit testing framework).

End-to-end tests

In your E2E tests, you combine both the back and front end to verify that your applications really work. You might want to simulate an entire user experience, such as signing up for a service or changing a password. Traditionally, E2E tests have been pretty time-consuming. Thankfully, we now have Cypress, an E2E test framework designed specifically for developers. Cypress is fast and simple to use. We like it so much that we’ve written an entire blog post about Cypress—check it out if you want to learn more about this E2E test framework.

How do I pick the best tools for JavaScript testing?

The JavaScript testing universe boasts dozens of free-to-use tools. This can be a bit overwhelming for someone who’s just starting out. A good point of reference is the annual State of JS survey which polls JavaScript developers on their practices regarding frameworks, libraries, and JS test tools.

In last year’s survey, more than 23,000 developers gave their input. Results are categorised by ‘awareness’, ‘interest’, ‘usage’, and ‘satisfaction’. While the first two categories simply describe whether or not people know about a certain framework and think about using it, the latter two reflect actual usage statistics:

Category ‘Usage’ (source: State of JS) Category ‘Satisfaction’ (source: State of JS)

Checking to see what your peers are using is great, but there are other factors to consider as well. Oftentimes, your entire setup and use case will limit the choice of test framework. For instance, if you’re a developer wanting to do end-to-end tests, you’ll probably want to go for Cypress. If on the other hand, you’re looking to test your Node.js applications, you’ll be looking for a server-side unit testing framework, such as Mocha or Jest.

Other times, one choice of framework will dictate what other tools to use. For example, most people who use Mocha for handling their test flows combine it with the Chai assertion library and the mocking tool Sinon for easy integration.

Start testing with Mailosaur

No matter your choice of test framework, integrating the either the Mailosaur Cypress plugin or Node.js library into your tests is quick and easy. Sign up for an account to use Mailosaur for email testing in your JS code.

Continue reading

How to use Telnet to test SMTP servers

When testing for bugs or searching for the root of email-related issues, it’s wise to rule out the possibility of an SMTP server malfunction. In this article, we provide a bit of background on what SMTP and Telnet are and how you can use Telnet to help validate the email functionality in your applications.

Read

Getting started with WebdriverIO

In this article, we take a detailed look at what WebdriverIO is and how to use it to set up automated tests.

Read