Hey there! Have you ever found yourself in a situation where you solved one problem, but then ended up introducing a new bug weeks later without realizing it? Well, it happens to the best of us! But, the good news is that you can easily avoid this by writing tests for your app.
When working on a project with a lot on your plate and tight deadlines, writing tests can often be overlooked and underestimated. However, once you learn how to write tests, you’ll see that it’s not as difficult as it may seem, and the benefits are well worth it! By writing tests, you can avoid future problems and make your life a lot easier in the long run.
So, I was recently tasked with writing Unit test cases for one of my client projects, and I gotta say, I was feeling a bit lost. It seems like there aren’t a lot of great resources out there to help you understand the concepts properly. The information is scattered all over the place, and it’s tough to figure out the best way to get started with Unit testing in React Native.
After a long search on the internet, I came across this quote
“It’s hard enough to find an error in your code when you’re looking for it; it’s even harder when you’ve assumed your code is error-free.” — Steve McConnell
In this article, we will focus on unit testing by providing a simple example of how to test a React Native app. This article is intended for anyone who is very new to testing in React Native.
What is Jest?
Jest is a JavaScript testing library created by the same company behind React: Facebook. But while Jest was created by the same developers who created React, it is not limited to only React — it can also be used with other frameworks like Node, Angular, Vue.js, and Babel.
Jest is a great tool for testing, with many advantages that make it an ideal choice for both front-end and back-end testing. Its ease of use, time-saving features, and lack of dependence on third-party tools make it an attractive option.
Getting started with Jest
Jest is included by default when initializing a React native app using npx react-native init Projectname
. However, when manually installing Jest with npm
, use the provided command to install it as a developer dependency.
npm install --save-dev jest
For TypeScript
npm install --save-dev ts-jest
Example App
For this tutorial, we are going to use this simple app, but of course, you can apply everything learned in any app you want.
Math function Testing!
For our first test, let’s test some math functions. Classic.
To understand the scenario let’s create maths.js which includes the math functions, and Math-test.js which includes the test case to test the math function of the maths.js file.
// maths.ts
export const add = (a: number, b: number) => {
const result = a + b;
return result;
};
Let’s move on to creating our test cases! To start, simply import the math functions into the Math-test.js file.
// Math-test.js
import {add} from '../src/utils/maths';
it('addition should return 4', () => {
const a = 2;
const b = 2;
expect(add(a, b)).toBe(4);
});
This is your standard it call (you can also use test). If we analyze this, it is a function that receives two arguments: a string for the test description, and a callback function that will be called when the test runs. on expect we are checking whether the math function gives the correct result.
Now let’s run this command in the terminal to run test cases.
npm test
Here, we can see all test cases passing. :)
Login functionality Testing!
For our second test, let’s test the real-world scenario of the login screen.
To understand the scenario let’s create login.js which includes the login validation functions, and Login-test.js which includes the test case to test the login function of the login.js file.
// login.js
export const LoginValidations = () => {
const isEmailValid = (text: string) => /@/.test(text);
const isPasswordValid = (password: string) => password.length >= 8;
const areFormFieldsValid = (email: string, password: string) =>
isEmailValid(email) && isPasswordValid(password);
return {
isEmailValid,
isPasswordValid,
areFormFieldsValid,
};
};
Let’s move on to creating our test cases! To start, simply import the login functions into the Login-test.js file.
// Login-test.js
import {LoginValidations} from '../src/utils/login';
const {areFormFieldsValid, isEmailValid, isPasswordValid} = LoginValidations();
it('should be a valid email', () => {
expect(isEmailValid('jhondoe@gmail.com')).toBeTruthy();
});
/**
* We want to be sure to handle failure as well
*/
it('should not be a valid email', () => {
expect(isEmailValid('jhondoe.gmail.com')).toBeFalsy();
});
///
it('should be a valid password', () => {
expect(isPasswordValid('12345678')).toBeTruthy();
});
it('should not be a valid password', () => {
expect(isPasswordValid('1234')).toBeFalsy();
});
////
it('should be valid fields', () => {
expect(areFormFieldsValid('jhondoe@gmail.com', '12345678')).toBeTruthy();
});
it('should not be valid fields', () => {
expect(areFormFieldsValid('jhondoe.gmail.com', '12378')).toBeFalsy();
});
Using .toBeTruthy
is a great way to ensure a value is true in a Boolean context when you’re not concerned with the specific value. The same goes for .toBeFalsy
used to ensure a value is false in a Boolean context when you’re not concerned with the specific value.
We can see how our tests run successfully:
Network call Testing!
For our third test, let’s test the real-world scenario of the network call.
To understand the scenario let’s create ApiHelper.js which includes the simple API call, and Dashboard-test.js which includes the test case to test the API function of the ApiHelper.js file.
// ApiHelper.js
import Http from '../utils/http';
export default {
getStoriesOfSection: (page: number) => {
return Http.request({
url: `https://randomuser.me/api?lego&randomapi?results=${page}&results=10&seed=abc`, //api token here should store at BE
});
},
};
Let’s move on to creating our test cases! To start, simply import the network call functions into the Dashboard-test.js file.
// Dashboard-test.js
import ApiHelper from '../src/service/ApiHelper';
// API test
describe('Test API', () => {
const TEST_CASE = [1, 2, 3, 4];
TEST_CASE.forEach((item, index) => {
test(`Test case ${index}: ${item}`, () => {
return ApiHelper.getStoriesOfSection(item).then(res => {
expect(res).toBeTruthy();
});
});
});
});
When writing test cases, you might want to break your test suite into components using describe. For instance, you could use a describe
block for each function in your user-facing class to better organize your tests based on your specific test strategy.
If you run the test now, you will see the following output:
Conclusion
And that’s that! In this post, we covered the basics of the Jest framework and how it could be used for testing simple JavaScript files. Keep in mind that well-structured code is easier to test. If testing is difficult, consider breaking the code into smaller, more manageable components. Remember, tests should enhance your app, not burden it.
This article offers an overview of React Native testing, but there’s so much more to learn! I encourage you to explore other testing techniques and tools, like Snapshot Testing, Detox, and React Native Testing Library. Choose the ones that work best for your project, and keep learning!
I hope this article has brought some new knowledge your way today. If you found it enjoyable and helpful, please don’t hesitate to give me a couple of reaction! 🦄
Happy Coding :)
Top comments (0)