How to write a Unit Test with Jest: Same test suites with different data
For our React Native iOS app, we choose Jest for testing.
The reason is pretty simple: it’s developed by Facebook officially (then fully supported and pervasive.)
Luckily, I found similarity between Jest and Spock, another testing framework I’m familiar to.
Both of them can keep duplicating the same test suites with different data concisely.
We can write down the data table in the test files like this:
str | expected
${null} | ${true}
${""} | ${true}
${"word"} | ${false}
In this article, you will find how to write the same test suites with different data in Jest 🚀
Installing Jest
Firstly, add Jest to your React Native project by hitting this command.
yarn add --dev jest
If you are using npm, hit:
npm install --save-dev jest
Then add the following section to your package.json file:
{
"scripts": {
"test": "jest"
}
}
Understanding Examples
Nextly, create these two files in the same directory.
export function isEmpty(str) {
return (!str || 0 === str.length);
}
The file above is a simple validation method which evaluates whether a passed string value is “empty” or not.
Only a string value that its length is one or more would NOT be evaluated as “empty”.
describe('isEmpty method with the argument', () => {
const validate = require('./validate');
describe.each`
str | expected
${null} | ${true}
${""} | ${true}
${"word"} | ${false}
`('$str', ({str, expected}) => {
test(`returns ${expected}`, () => {
expect(validate.isEmpty(str)).toBe(expected)
});
});
});
This is the test file for validate.js file.
Let’s understand what are the codes doing line by line.
At the first line:
describe('isEmpty method with the argument', () => {
the description of the test suites with different data is implemented.
The string, isEmpty method will be shown in the console when the test is done and you’ll found what tests have done by seeing it.
The second line imports the class we want to test.
const validate = require('./validate');
At the fourth line to the eighth line:
describe.each`
str | expected
${null} | ${true}
${""} | ${true}
${"word"} | ${false}
the data table is set.
Because in this test, I’d like to test three cases.
- When null is passed, the method returns true
- When empty string passed, the method returns true
- When a string contains at least one character passed, the method returns false
str
would be the argument for the method and expected
is the expected value the method returns.
Finally, at the ninth to the thirteenth line, the actual test is implemented.
`('$str', ({str, expected}) => {
test(`returns ${expected}`, () => {
expect(validate.isEmpty(str)).toBe(expected)
});
});
'$str'
will also be a shown message when the test is done.
Since the tests will be executed multiple times and the value changes, by setting $str
, the value of str
in each test suites will be shown.
({str, expected})
is passing the values in the data table.
returns ${expected}
is also a message and the value of expected
in each test suites.
And last but not least, this defines what the test will do 😎
expect(validate.isEmpty(str)).toBe(expected)
This defines that when isEmpty method is run with str
, it must return expected
.
Result
After understanding all, hit yarn start
!
The result would be like this.
PASS validate.test.js
isEmpty method with the argument
null
✓ returns true (6ms)
""
✓ returns true (1ms)
"word"
✓ returns false (1ms)
Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total