Alon Yehezkel

@alonn24

Minimize Your Tests Boilerplate

Introducing Suite Wrappers

Tests should be readable and consist of the minimum information required to understand the test case. Extra data and boilerplate distract the reader mind and make it harder to understand how the system behave.

Reducing extra information and boilerplate can be done in many ways, one of them is to use test drivers which hold implementation details of “how” to run the unit under test and leave the “what” do the test. Another technique is to use test kits to offload the usage of external resources to a kit that provides clear APIs.

Drivers, test kits, and other techniques are very useful and very recommended, However, they can easily backfire with huge amount of boilerplate. For example, lets say you want to use come kind if a database. You need to start a connection and shut it down at the end by probably running the code in before and after blocks — code that is not directly related to the tests and there to support it.

The test becomes tedious and less readable. think of other usages that requires a lot more boilerplate and startup code. Moreover, to create another suit that uses the same boilerplate code you are going to copy / paste the same code which causes code duplication and makes the system harder to maintain.

Suit Wrappers

Suite wrappers can help us remove the boilerplate that does not directly related to the code, but rather belongs to the test kits being used. Suit wrappers hold the preparation boilerplate and run it seamlessly.

The suit wrappers implementation is tightly coupled with testing frameworks such as mocha, jest, and jasmine but provides clean API to the test. To achieve that, we are going to extend the suite with before and after statements that executes implicitly.

Suit wrapper consist of 3 parts:

  • Test Framework Wrappers — provides the ability to wrap the test framework functionality with specific implementation.
  • Test Kit Wrappers — use the test framework wrapper and extend with the specific test kit functionality.
  • Test Suit — The actual test without extra boilerplate code.

The Test Framework Wrappers

The test framework wrappers provide functionality to create custom wrappers and export custom suits including the test kit functionality.
For example, mocha wrappers:

In the example above we export an API that gets a conf item which will hold the implementation we want to insert the suit. Given a beforeDesc object we can run it before describe blocks. The same goes for afterDesc, beforeIt and afterIt.

The Test Kit Wrappers

The test kit wrappers use the test framework wrappers and provide test suit with extra functionality. For example, we can implement here the functionality to start and shut down the external database we want to use or any other functionality we want to run before and after tests.

Test Suit Usage

The test suit uses the test kit wrappers and expose the context and a test kit object to the tests by simply use mySuit.describe and mySuit.it. The test gain the extra functionality without extra code and make the test leaner.

The test above looks neat and minimal, however a lot is going on under the hood. Before the test actually run, the test kit before block executes, then the suit beforeEach runs, then the test and finally the test kit after block.

Disclaimers

Suit wrappers, as test drivers and test kits, are tools in our toolkit. We should use them wisely as they can be an overkill for simple scenarios. Misuse of such can lead to over complexity and cause unmaintainable codebase.

To make a wise use of the tools, I recommend to write the tests without, then search for a tool that will actually make the code better. This is what we did when encountered a messy test — all other tools we tried didn’t make the job done and the test cleaner and finally we came up with suite wrappers.

Photo by Goh Rhy Yan on Unsplash

On the one hand, use of suit wrappers can lead to the usage of shared objects which can be easily created and make tests failed with no visible reason. It is up to the test kit wrappers to start and clean the test kit and maintain the context so such things wont happen. On the other hand, the suit wrappers can keep objects in memory and soft clean the environment between each test, hence run tests faster.

You can find all the examples here :
https://gist.github.com/alonn24/e18fe297fcfd8ad5ca47ce020944d2d9

Thank you for reading! 
Have an opinion on the subject? please comment! 
I would love to hear about it.

More by Alon Yehezkel

Topics of interest

More Related Stories