How to Test Flutter Apps Using Appium Automation
By Neha Vaidya, Community Contributor - March 21, 2023
An open-source tool for cross-platform app development introduced by Google, Flutter has gained some popularity for its ability to create cross-platform apps. Flutter apps can be developed once and cross-compiled for multiple platforms – iOS, Android, Mac, Linux, Google Fuchsia, Windows, and the web.
Developers also favor Flutter because of its extensive documentation. The latest version of Flutter has stabilized, and new features are beginning to emerge – to facilitate easy app development.
Given the rising preference for Flutter, this article will discuss how to run automated app tests on Flutter apps using Appium.
What is Flutter Framework?
Flutter is an open-source mobile UI framework that can create Android and iOS apps (among other platforms) from a single codebase.
Multiple frameworks provide excellent features to develop mobile applications. For developing mobile apps, Android provides a framework based on Java and Kotlin, while iOS utilizes a framework based on Objective-C or Swift language.
Therefore, devs need two different languages and frameworks to develop applications for both OS. Naturally, a cross-platform framework like Flutter makes life simpler for app developers, saving time, resources, and effort.
Features of Flutter Framework
- Modern and reactive framework
- Uses the easy to learn Dart programming language
- Facilitates fast development
- Fluid and intuitive user interfaces
- Vast widget catalog
- Runs the same UI for multiple platforms
Flutter Architecture
The architecture comprises four components:
- Flutter Engine
- Foundation Library
- Widgets
- Design Specific Widgets
Flutter apps are written in the Dart programming language and run on Dart virtual machines.
1. Flutter Engine
It is a portable runtime for high-quality mobile apps and is primarily based on the C++ language. It implements Flutter core libraries that include animation and graphics, file and network I/O, plugin architecture, accessibility support, and a Dart runtime for developing, compiling, and running Flutter applications. The Engine uses Google’s open-source graphics library Skia, to render low-level graphics.
2. Foundation Library
It contains all required packages that form the basic building blocks of writing a Flutter application. These libraries are written in the Dart language.
3. Widgets
According to the official document, the Flutter framework is based on the core concept of ‘everything is a widget’. Widgets are the fundamental components of the Flutter app. Each widget is an immutable declaration of the UI. Widgets are the configuration or the instructions for different parts of the UI, and placing the widgets together creates the application.
4. Design Specific Widgets
The Flutter framework has two sets of widgets that conform to specific design languages. These are Material Design for Android application and Cupertino Style for IOS application.
What is Appium?
Appium is an open-source framework that allows QAs to conduct automated app testing on different platforms like Android, iOS, and Windows.
It automates testing for:
- Native Mobile Applications that are written using iOS, Android, or Windows SDKs
- Mobile Web Applications that can be accessed using mobile browsers such as Safari, Chrome, or in-built native browser applications for Android devices
- Hybrid Mobile Applications that have a native wrapper around the web view
Appium is a flexible cross-platform testing framework, enabling testers to write test scripts against multiple platforms such as iOS, Windows, and Android using the same API. That means QAs can use the same code for iOS as for Android.
Now, let’s move on to automating Flutter apps using Appium.
Setting up Flutter
Flutter is relatively straightforward to set up. Depending on the OS being used, follow the steps in this official Flutter tutorial: https://flutter.dev/docs/get-started/install
How to Create a Flutter App
Firstly, one must be clear on the difference between stateless and stateful widgets. A stateless widget specifies a portion of the user interface by constructing a structure of other widgets that describe the UI with more precision. Stateful widgets can alter their state and be redrawn on the screen several times while the program is running.
To create a Flutter app, install the Flutter SDK as well as other framework-related tools. In this article, the app is developed in IntelliJ IDE, which requires the installation of two plugins – Dart and Flutter.
Appium Flutter Driver
Flutter driver in Appium is an automation tool for Flutter apps that can be used on various platforms.
It uses webSocket communication to carry the WDIO script to start the Flutter driver. In this case, the request will be sent to the particular application. After that, the AUT will be able to send the response to the script through the Appium Flutter driver.
One can also build Appium in their machine through the source code. After cloning the source code:
run npm install then npm run built type a command node to start the Appium server
Appium Flutter Finder
Appium Flutter Finder is used by Appium to interact with the Flutter elements. It is a part of Appium Flutter Driver package and mimics the CommonFinders Class of Flutter Driver Library.
Step 1 Download the package from GitHub.
The package consists of:
- Appium Flutter Driver
- Appium Flutter Finder
Step 2 Clone the sample project to get the WDIO code.
Now let’s start with writing a script for testing Flutter apps using Appium.
First, let’s begin with package.json
package.json – Package which is required by appium-flutter-driver
{ "name": "appium", "version": "1.0.0", "description": "", "main": "index.js", "dependencies": { "appium-flutter-finder": "0.0.13", "webdriverio": "^5.15.0" }, "scripts": { "start": "node test.js", "ios": "APPIUM_OS=ios npm start", "android": "APPIUM_OS=android npm start", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "xyz", "private": true, "license": "" }
test.js – This is the main testing file.
const wdio = require('webdriverio'); const assert = require('assert'); const find = require('appium-flutter-finder'); const osSpecificOps = process.env.APPIUM_OS === 'android' ? { platformName: 'Android', deviceName: 'emulator-5554', {Mention your device name} app: __dirname + '/..Mention the path', }: process.env.APPIUM_OS === 'ios' ? { platformName: 'iOS', platformVersion: '12.2', deviceName: 'iPhone X', noReset: true, app: __dirname + '/../ios/Runner.zip', } : {}; const opts = { port: 4723, capabilities: { ...osSpecificOps, automationName: 'Flutter' } }; (async () => { console.log('Initial app testing') const driver = await wdio.remote(opts); assert.strictEqual(await driver.execute('flutter:checkHealth'), 'ok'); await driver.execute('flutter:clearTimeline'); await driver.execute('flutter:forceGC'); //Enter login page await driver.execute('flutter:waitFor', find.byValueKey('loginBtn')); await driver.elementSendKeys(find.byValueKey('emailTxt'), 'xyz@gmail.com') await driver.elementSendKeys(find.byValueKey('passwordTxt'), '123456') await driver.elementClick(find.byValueKey('loginBtn')); //Enter home page await driver.execute('flutter:waitFor', find.byValueKey('homeGreetinglabel')); assert.strictEqual(await driver.getElementText(find.byValueKey('homeGreetinglabel')), 'Welcome to Home Page'); //Enter Page1 await driver.elementClick(find.byValueKey('page1Btn')); await driver.execute('flutter:waitFor', find.byValueKey('page1GreetingLabel')); assert.strictEqual(await driver.getElementText(find.byValueKey('page1Greetinglabel')), 'Page1'); await driver.elementClick(find.byValueKey('page1BackBtn')); //Enter Page2 await driver.elementClick(find.byValueKey('page2Btn')); await driver.execute('flutter:waitFor', find.byValueKey('page2GreetingaLbel')); assert.strictEqual(await driver.getElementText(find.byValueKey('page2GreetingLabel')), 'Page2'); await driver.switchContext('NATIVE_APP'); await driver.back(); await driver.switchContext('FLUTTER'); //Logout application await driver.elementClick(find.byValueKey('logoutBtn')); driver.deleteSession(); })();
Run Appium to test the Flutter App
To run the Appium Project, follow the steps below:
- Change directory to “appium” folder
- Start the Appium server with the command “appium” in the console
- Start Android emulator (check emulator address with “adb devices)
Install required nodejs package
npm install
And change Android configuration in test.js“)
and run command
APPIUM_OS=android npm start
to start Appium automation.
And that is how one can automate Flutter apps using the Appium framework.
To keep up with the demands of fast and reliable testing across various platforms, devices, and versions, automation testing using Appium is not just preferable but highly recommended. Favored throughout the industry, Appium offers feasibility, flexibility, and cost-friendliness above other testing tools, enabling teams to deliver great user experiences within the continuous delivery approach.
However, to take full advantage of its features, Appium tests must be run on real mobiles devices (iOS, Android, Windows, etc.) There is no way to accurately identify all possible bugs without testing apps in real user conditions, and that is where BrowserStack App Automate comes in. Here is how you can test Flutter Apps using the BrowserStack platform.
BrowserStack’s real device cloud offers thousands of real mobile devices from major vendors and manufacturers for app testing (manual and automated). Each device is loaded with real operating systems – multiple versions of popular operating systems in use.
Essentially, QAs can access thousands of popular mobile device-OS combinations to test their app. They don’t have to worry about buying and updating devices and installing software. They just need to sign up for free, choose the required device-OS combination and start testing their app.