The ever growing JavaScript ecosystem is built by the developer community to solve their problems their way, which is ever so slightly different to the solutions that already exist. So when it comes to testing, the arena is quite deconstructed, just like the hipster cafes in Melbourne serving up ‘deconstructed’ coffee.

The main focus of this article is to give you an idea about how testing sits together in JavaScript and help you understand why and how it is deconstructed so that you can make better choices when it comes to choosing a library for the job at hand. After all we don’t want you to become a Candy Land developer, just because there are too many choices.

Testing Basics

When we write tests, as the good developers we are, we tend to stick to a few good practices, such as:

  • Arrange, Act and Assert pattern for writing clearer tests.
  • Test Data Builder pattern to simplify our Arrange.
  • Grouping our tests into suites/fixtures to have common test data.
  • Keeping it DRY with parameterised tests for different inputs.

These good practices form a structure, as depicted by the coloured areas in the image below, that is common for unit tests, integration tests and end-to-end tests. The white boxes represent the group of libraries that will help us achieve this structure in JavaScript.

JS Testing Overview.png

Test Framework

To start off, we need a test framework that allows us to create tests and group them into suites. We need it to allows us to create common setup logic for a group of tests as well. The code snippet below is an example of writing tests using Mocha library. In this example we have a test suite, represented by the describe function, called “LoginForm: Verify Validation” with three tests, represented by the it function.

test

The following code snippet shows us how to create parameterised tests using Mocha.

test cases.PNG

Assertion Library

Mocha promotes BDD-style assertions, which are assertions that can be read almost like a sentence. This is achieved using a technique called method chaining. Mocha’s default assertion library is ExpectJS. As with everything, we can easily replace it with a different assertion library as we see fit for the job at hand. The following code snippet is an example of assertions using Chai library, which has more chainable words than ExpectJS.

chai-assertions

Mocking Libraries

When it comes to unit testing, our focus is on testing a specific unit of work, known as System Under Test. The SUT can be one or more objects/components/actions that perform a unit of work. Our goal is to either verify a SUT’s state or its interaction with other objects/components. The following snippet is an example of simple unit test.

state verification.PNG

If that SUT uses other components and/or services to perform its job then including them in your test setup and execution will increase the scope of your test, known as scope creep. In such cases, we keep our test simple by mocking away the external dependencies. No, not in the sense of ridiculing them to the point they run away but more in sense of mimicking or imitating their behaviours.

Mocking is the art of replacing external dependencies with imitations that can simulate desired output to satisfy your test case. – Rajeev Nithiyananthan

The NSubstitute, Moq and Rhino Mocks are popular and general purpose C# mocking frameworks. Their counter parts in the JavaScript-land are Sinon, TestDoubleJS and JsMockito, not in any particular order.

Let’s add a twist to the previous example. The Warehouse now persist products in a database using a repository, rather than keeping them in-memory. The code snippet below shows what it would look like when we use Sinon to mock the external dependency.

mock.PNG

What if we want to make sure that a specific method wasn’t called too many times without changing its behaviour or what if we want to verify that the method we mocked wasn’t called too many times? The following snippet highlights how this can be done using Sinon.

spy.PNG

Test Runners

Test runners are essentially tools that wrap our test suites, in Mocha they are the describe functions, and run them in a specific environment.

Please keep in mind that you are not always going to need a separate test runner.

Some test frameworks, as with Mocha, are capable of running tests on Node.js when combined with the popular build tools, such as Gulp and webpack. These are great for running unit tests that do not require browser-based testing. The tests are effectively run in the terminal and the results are displayed in terminal as well.

When we are dealing with testing user interaction on a website, then we need to render it on a browser so that we can navigate thru the pages and verify the expected behaviour. To this end, we can use PhantomJS or Chutzpah, popular headless browsers. Headless browsers access web pages like any other browsers do but without showing the actual browser’s user interface. As with test frameworks running tests in terminal, headless browsers behave the same.

If the requirement is to run the tests on real browsers and in different environments, that’s when we will come across more advanced test runners such as Selenium WebDriverJs and Karma.

Popular Libraries for Testing

JS Testing Overview.png

Advertisement

One thought on “Introduction to testing in JavaScript

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s