Introduction

This article describes the way in which tests are made in the different services and UI's of the dApps team.

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

Writing tests

Tests can be written in various ways. This section tries to give a standard and a rationale behind the way we writes tests.

Tests MUST be written using the describe and the it methods provided by jest

Describing and building context

The describe method SHOULD be used to describe, whenever it's possible, the context on which the piece of code to be tested will be executed and SHOULD build that context inside of its scope.

describe('when the flag is red', () => {
	...
})

describe('when the flag is blue', () => {
	...
})

To describe the context, we SHOULD use one of the following words: when for top level describes and having or and to indicate that there's a context that depends on other context that was defined before. The rationale behind this is to have a self described contexts that can be easily understood and checked by combining the describe sentences. As the idea is to concatenate the descriptions of the contexts, describes MUST be written in lowercase.

describe('when the flag is red', () => {
	...
	describe('and the wind is strong', () => {
     // The context here is described by the conjuncton of the describes:
     // "when the red flag is red and the wind is strong"
     ...
  })
})

Multiple describes can be nested at the same and at a lower level. Describes at the same level denote different contexts and describes in lower levels (nested describes) denote a more specific context.

describe('when the flag is red', () => {
	...
	describe('and the wind is strong', () => {
     ...
  })

	describe('and the wind is weak', () => {
     ...
  })
})

As mentioned before, each describe SHOULD be accompanied by a method that builds the context or a method that destroys or changes the context. The methods that MUST be used are the beforeEach and the afterEach.

<aside> ⚠️ The Jest framework has two methods, beforeEach and beforeAll, but combining both of them generates confusion and execution problems when nested contexts are present, as the order on which they are executed is not what we would expect.

</aside>

Contexts created with the beforeEach method will be more and more defined as we go deeper into the describe tree. Each beforeEach will specify the context more according to what their text says.

The variables set in the contexts SHOULD be defined according to the scope that they're going to be used in. That is, if a variable is used only for a specific context in a nested level of describes, the variable SHOULD be defined only on that specific context. The rationale behind this is to keep the variables close to the code that they're being used in, making the code easier to understand.


let flag = 'blue'
describe('when the flag is red', () => {
	let wind = 'mild'
	beforeEach(() => {
    flag = 'red'
  })
  ...

	describe('and the wind is strong', () => {
		beforeEach(() => {
	    wind = 'strong'
	  })
    ...
  })

	describe('and the wind is weak', () => {
		beforeEach(() => {
	    wind = 'weak'
	  })
    ...
  })
})