Categories
Technology

Test React Native App with Jest and React Native Testing Library

Test React Native App with Jest and React Native Testing Library

Testing is an important part of any software development process. It helps you to ensure that your code is working as expected and that you are not introducing any bugs. In this article we will focus on unit testing by providing a simple example of how to test a React Native component.

Setting up the project

let’s create a simple React Native app and then we will add testing to it.

react-native init AwesomeProject

This will create a new  app in a folder called AwesomeProject. Now we can run the following command to start our app:
cd AwesomeProject && yarn start

Configuring the React Native Testing Library:

  • Install Required Packages:
    Ensure you have Jest and React Native Testing Library installed in your project. If not, you can install them using npm or yarn:

@yarn add –dev babel/preset-react jest-environment-jsdom @babel/plugin-proposal-decorators @testing-library/jest-dom @testing-library/react-native

  • Configuration:

Create a jest.config.js file in the root of your project and configure Jest:

module.exports = {
preset: "react-native",
testEnvironment: 'jest-environment-jsdom',
};
  • Setting up Babel:

If you’re using Babel in your project, you might need to add some configuration to your .babelrc or babel.config.js file to make sure Jest can handle importing images and other assets in your tests. Here’s an example of what you might need to add to your Babel configuration:

module.exports = function (api) {
api.cache(false);
return {
presets: [
'module:metro-react-native-babel-preset',
'@babel/preset-env', 
'@babel/preset-react', 
"@babel/preset-typescript"
],
plugins: [
['react-native-reanimated/plugin'],
["@babel/plugin-transform-class-properties", { "loose": true }],
["@babel/plugin-transform-private-methods", { "loose": true }],
["@babel/plugin-transform-private-property-in-object", { "loose": true }],
["@babel/plugin-proposal-decorators", { "legacy": true }],
    ]
};
};
  • Writing Your Tests:

With the setup done, you can now start writing tests for your React Native components using React Native Testing Library. Here’s a simple example of a test for a component :

  • Steps.
    1. In the rood directory of the project create a folder name __tests__

2. In this file create test suits which are files with the testing code.

// App.test.js

import 'react-native';
import React from 'react';
import App from './../app/App';
import renderer from 'react-test-renderer';

// snapshot test
test('renders correctly', () => {
const snapshot = renderer.create(<App/>).toJSON();
expect(snapshot).toMatchSnapshot();
})

  • Running Test Case:
    • yarn test –u  (this will create the new snapshot of the testcases or update the old test snapshots)

yarn test  (this will match the snapshot with the previous taken snapshot or print the result to console weather it pass or fails.

JEST Features:

  • The coverage report
    The Jest coverage report provides detailed information on your test coverage. To show a coverage report in the console, you can simply use the –coverage flag when running the test. A table containing information about coverage is now shown in the console.

–coverage

–coverage –coverageDirectory=’coverage’
(create a visually appealing coverage report)

  • % Stmts: Percentage of all instructions that were executed at least once by means of tests.
    • % Branch: Percentage of all branches whose conditions were fulfilled at least once by way of tests and thus passed.
    • % Funcs: Percentage of all instructions that were called at least once by means of tests.
    • % Lines: Percentage of all source code lines that were run at least once by way of tests.
  • The watch plug-in
    • get quick feedback on code changes.
    • Jest can now be started with the CLI option –watch to only re-run tests affected by file changes.
    • ‘f’ only re-runs failed tests;
    • ‘u’ triggers an update of all failed snapshots; and
    • ‘i’ launches an interactive mode to update snapshots individually.
  • Mocking
    • Mocking is a software development practice used in unit testing. It involves creating fake or mock versions of external dependencies (such as modules, objects, APIs, or databases) that your code under test relies on.
    • The main purposes of mocking are: Isolation, Control, Speed, Independence.
  • Timer mocks
  • Snapshot testing
    • Snapshot testing is a way to test React components by rendering the component, taking a “snapshot” of the rendered output, and comparing it with a previously approved snapshot. If the output matches the approved snapshot, the test passes; otherwise, it fails.
    • This is particularly useful when refactoring or making changes to existing components, as snapshot tests can catch regressions in the component’s output.

Types of Test Cases

  • Unit Tests: Focus on testing individual components or functions in isolation. This is crucial for ensuring that each part of your application works as expected under controlled conditions.
    • Component Testing (Snapshot tests, prop and state changes, lifecycle methods)
    • Logic and Utility Testing (Pure functions, utility functions, business logic)
  • Integration Tests: Test how different parts of your application work together. This could involve testing the integration between components or between components and external services.
    • Component Integration Testing (Testing interactions between parent and child components)
    • Redux and State Management Testing (Action creators, reducers, selectors, and integration with components)
  • Snapshot Tests: As mentioned earlier, snapshot tests allow you to compare the current output of your components against a previously saved snapshot. This is particularly useful for catching unexpected changes in the UI.
  • End-to-End (E2E) Tests: These tests simulate real user scenarios across the entire application. E2E testing is essential for ensuring that your application works seamlessly from start to finish.
  • Other Tests:
    • API and Network Testing
    • Asynchronous Testing
    • Platform-specific Testing

References:

Categories
Technology

Automate and deploy Android and iOS Builds using Fastlane and Self-Hosted Runners

Automate and deploy Android and iOS Builds using Fastlane and Self-Hosted Runners

Introduction :

Why automate Android and iOS builds?

Automating Android and iOS builds focuses on the build and deployment steps in the Software Development Life Cycle (SDLC) to save time. By automating these processes, we reduce manual intervention, minimize errors, and ensure faster and more consistent delivery of application updates.

Continuous Integration and Continuous Deployment (CI/CD) pipelines are crucial in modern mobile app development. They ensure that code changes are automatically built, tested, and deployed, reducing manual effort and the risk of errors.

Introduction to CI/CD Pipeline

Continuous Integration (CI) and Continuous Delivery (CD) are practices that enable development teams to deliver code changes more frequently and reliably.

Continuous Integration (CI): Developers merge their code changes into a central repository. Automated builds and tests are run to ensure that the new code does not introduce any bugs or break existing functionality.

Continuous Delivery (CD): Once code passes CI, it is automatically deployed to a staging environment. From there, it can be released to production with a manual approval step.

Tools: Jenkins, GitHub Actions, GitLab CI, CircleCI, Travis CI.

Benefits of a CI/CD Pipeline

  • Faster Development Cycles: Automated processes reduce the time required for code integration and deployment.
  • Improved Code Quality: Continuous testing ensures that code changes do not introduce new bugs or regressions.
  • Enhanced Collaboration: Teams can collaborate more effectively with a streamlined workflow.
  • Reduced Manual Effort: Automation minimizes manual intervention, reducing human error and freeing up developer time for more critical tasks.

The primary goal is to ensure that code changes are integrated and delivered to production rapidly and safely.

Introduction to Self-Hosted Runners

Self-hosted runners are machines that you manage and maintain to run GitHub Actions workflows. Unlike GitHub-hosted runners, which are managed by GitHub, self-hosted runners provide more control over the hardware, operating system, and software environment.

Step-by-Step Guide

  • Create a Runner:     
    a. Go to your repository on GitHub.
    b. Navigate to Settings > Actions > Runners > New self-hosted runner.
    c. Choose the operating system for your runner (Linux, macOS, or Windows).
  •  Download and Configure the Runner: Follow the provided steps to setup self-       hosted runners.

Introduction to Fastlane

  • Fastlane is an open-source platform designed to streamline the process of building, testing, and releasing mobile applications for iOS and Android. It automates many repetitive tasks in the app development lifecycle, making it easier and faster for developers to deploy their apps.

Setting Up Fastlane for Android and iOS

  • Installing Fastlane :  
                              Fastlane can be installed in multiple ways. The preferred method is with Bundler. Fastlane can also be installed directly through Homebrew (if on macOS). It is possible to use macOS’s system Ruby, but it’s not recommended, as it can be hard to manage dependencies and cause conflicts.
  • Setting up Fastlane :   
         Navigate your terminal to your project and run ‘Fastlane init’ inside android and iOS directory.

        This will create Fastlane folder inside our project android and iOS directory.

Deploy Android and iOS Builds to Firebase

Android fastlane code

iOS fastlane code

Integrating Fastlane with GitHub Actions

Integrating Fastlane with CI/CD (Github Actions) pipelines is essential for automating the build, test, and deployment processes for mobile applications. This integration ensures that each code change is automatically built, tested, and deployed, improving efficiency and reducing the risk of human errors.

Explanation:

  • Trigger: The pipeline runs on push events to the main branch and on pull requests
    Or on Workflow_dispatch on manual trigger.
  • Jobs:
    a. Build: Checks out the code, sets up the JDK, caches Gradle dependencies, builds the app, runs unit tests, and uploads the APK.
    b. Deploy: Deploys the apk or aab to Firebase App Distribution/Playstore/Appstore (after the build job succeeds).

 Workflow in Github Actions

Common Issues and Troubleshooting