New feature: SofySense – Manual test case & test results AI generator to help you speed up your testing process. Try it today.  

Sofy launches product feature suite to deliver effortless test maintenance and ensure continuous precision – learn more.

sofy logo

Writing Tests for React Native and Flutter Applications

It's no secret that Google's Flutter and Meta's React Native are fighting a no-holds-barred slugfest. But how do they compare?

Over the course of the last several years, Google’s Flutter and Meta’s React Native have duked it out in an effort to win over not only market share but also the hearts and minds of the open source community of developers.

When it comes to writing contemporary multi-platform applications, no other tools do it better. Flutter offers a rich toolkit of pre-built widgets while React Native has a more user-friendly declarative UI. Flutter is popular with mobile app development while React Native finds more popularity in web app development circles.

Yet in the long list of comparable features, one aspect is often overlooked—testing.

Each Software Development Kit (SDK) provides its way of writing, grouping, and running tests. (And indeed you may well have your own preference!) In this post, we will discuss how Flutter and React Native handles testing, and along the way take a look at some of the differences between the two.

But before we do that, let’s take a step back and look a little closer at both Flutter and React Native.

What is Flutter?

Developed by Google and first released in 2017, Flutter is an open-source framework that allows developers to build multi-platform applications from a single code base. In short, this means you can develop one app, and then deploy it as a mobile iOS or Android App, a Windows, macOS, and Linux desktop app, and a web app—all from one repository of code.

Flutter uses Dart, a server-side object oriented programming language developed by Google. With the relative ease of use, incredible open source libraries, and development tooling, many of today’s most popular applications were built using Flutter, including Google Ads and Alibaba’s huge Xianyu app.

Flutter brings a lot of ease-of-use features to the table. For example, with Flutter, you can simplify your code base, improving time-to-market and allowing for easy changes across platforms. 

What is React Native?

Developed by Meta (formerly known as Facebook) in 2015, React Native lets developers deploy to multiple devices from a single code base, but uses a JavaScript framework. Since it relies on the JavaScript framework and boasts a more comprehensive library, many developers may feel more at home using React Native over Flutter.

In 2018, React Native boasted the second highest number of contributors of any repository on GitHub and is used for the production of thousands of popular mobile apps today. This includes not only Meta platforms like Facebook, Instagram, and Oculus, but also apps by Walmart, Tesla, and even Microsoft Outlook.

Writing tests 

So, what what about testing? If you’re deploying code across every device, you need to make sure it works on every device, right? Each SDK Recommends writing unit, widget (or component), and integration tests for your code base. Note that each type of test offers a unique and important view into the health of an application. A well-rounded testing strategy involves all three. Here’s an overview of each.

Unit test

Unit tests validate a single function, method, or class and ensure that the smallest units of functionality are operating correctly. The goal of a unit test is to verify the accuracy of logic under multiple conditions. If there is a function that adds two numbers together, we’d want to verify it outputs 10 when 5 and 5 are provided. We would also want to write tests for edge cases. What happens when two large numbers are provided or if only one number is provided?

Widget tests and component tests

Widget tests or component tests validate that a single component is behaving correctly when interacted with and renders correctly. If one of our widgets is a calculator, a unit test will evaluate if a function correctly adds two numbers, and a widget test will verify if the calculator widget displays the output when the ‘=’ button is pressed, and if the component renders the entire component correctly.

Integration testing and end-to-end testing

Integration testing, also called end-to-end testing, tests the application—or multiple pieces of the application—together. These verify that the system components are working together correctly. In general, integration tests should only be run if all other types of testing have been passed first.

Image: Sofy x Sawant Ajit, Shutterstock

Writing tests for React and Flutter

The real comparison between writing Flutter and React tests relies on comparing their respective testing libraries as well as their frameworks, Jest and Dart. Developers may find themselves preferring one over the other for their own reasons. We’re not going to try to tell you which one is better—each has its pros and cons—so we’ll just lay out what to expect when it comes to testing in both.

React and Jest

You’ll write all your React test classes using Jest, a JavaScript testing framework created and maintained by Meta. Jest automatically ships with your React implementation. Customized to your app, you’ll spend less time on configuration. Jest sets dozens of default config options for a quicker ramp-up. You can either take advantage of the default setup, or retrieve and change them.

Jest’s powerful mocking library makes it simple to stub out and mock unit test dependencies. A robust collection of mock functions allow you to quickly mock services and functions to utilize across your tests. Classes can also be automatically mocked, providing a mock constructor and a mock version of all methods. This makes writing tests much faster.

React uses Jest’s test renderer to render react components to pure JavaScript by grabbing the component hierarchy and storing in memory so that tests can make assertions against it. This is all done without relying on the DOM.

Another powerful React test feature is snapshots, which renders a UI component, takes a snapshot, and compares it to a previously rendered snapshot. This helps prevent unexpected changes.

Writing React tests

Jest unit tests are easily written using It, Expect, ToBe, which provides an excellent syntax for easily understanding what the test is, what’s expected, and the actual result:

  • IT: is a string description of what the test will cover, the given input, and the expected result
  • Expect: will take the function being tested, along with whatever arguments the function needs
  • ToBe: is the assertion itself, that will indicate if the test passes or fails.

You can easily group texts together by using the describe class. For example, we can group calculator functions together under one testing group and run them together.

Integration/End-to-End (E2E) Tests

So far we’ve dealt with testing the code implementation of the mobile app. There has been no guarantee that they will function on a particular device. E2E testing involves using an emulator to simulate testing on a device. These emulators allow us to control elements on the screen, including swiping, button pressing, and text inputs and making assertions about the result.

Testers can use the Detox framework, which is tailored for React Native apps, to create and run E2E tests.

Flutter and Dart

Users compose Flutter tests using Dart. At some point, Google identified a need for an in-house multi-platform programming language with a flexible execution run time platform, and the result was Dart. Google first released Dart 2011, and the programming language has subsequently gained more and more popularity, particularly with the introduction of Flutter and Flutter 2. If you’re well versed in JavaScript, Dart is easy to learn.

For testing, Dart uses Package: test, which provides a standard way of writing tests with Dart. The framework can be used to write single tests, or to group tests together. The package allows you to write both synchronous and asynchronous tests in a similar manner. 

@Tags, short strings you can use to categorize tests or test groups, allow you to create custom configurations and associate them to certain tests. For example, you can use a tag to indicate if a certain test should wait longer before timing out due to external dependencies. Use tags to also filter tests to execute, making it easier to specify which tests you want to run.

While Flutter doesn’t provide the flexible mocking capabilities of Jest, developers can take advantage of the dart mockito library, inspired by the open-source Mockito mock framework, to generate mocks from imports.

Writing Flutter tests

Writing unit tests in Flutter is similar to Jest with some initial setup requirements. First, add the test dependency and create the test file. In the test file, import your class and package:test.

Call the Test() function in Void Main (). The Test() method contains a string description of the test, much like ‘It’ in Jest. Then execute your method and use Expect to assert the result.

As with describe in Jest, you can group similar tests together with the group() function to easily execute them in the future for integration testing.

Conclusion

Here are a few quick take-aways to consider when comparing Flutter and React Native:

  • Developers familiar with JavaScript will feel more at home testing with React Native.
  • Flutter offers a strong set of libraries and ‘hot reload’. This allows you to receive instant testing feedback when changes are made to code.
  • Both Flutter and React Native offer great tools to quickly mock dependencies.
  • React Native Jest can use Snapshots to easily capture and compare UI components.

Both React Native and Flutter are very popular development tool kits—and for good reason. They’re rich in libraries and features and offer the ability to develop multi-platform applications from a single code base. In all likelihood, your preference may come down to familiarity with the languages (Dart or JavaScript) or it may simply be a matter of how each tool supports testing.

Disclaimer: The views and opinions expressed above are those of the contributor and do not necessarily represent or reflect the official beliefs or positions of Sofy.