DEV Community

ashwithpoojary98
ashwithpoojary98

Posted on

Automating Flutter App Using Flutter Appium driver

Flutter App Automation
Why Flutter is the most popular cross-platform mobile SDK??

Running a development team for each mobile platform sucks up resources from other work. Flutter is the most popular way for one development team to build on all platforms.

What is Flutter?
Flutter is Google’s free, open-source software development kit (SDK) for cross-platform mobile application development. Using a single platform-agnostic codebase, Flutter helps developers build high-performance, scalable applications with attractive and functional user interfaces for Android or IOS. Flutter relies on a library of pre-made widgets that make it simple for even people with limited programming or development experience to launch their own mobile applications quickly.

A list of companies doing noteworthy work with Flutter

As of January 2023, there are over 700,000 apps in the Play Store that are built with Flutter, and one in five new apps on the Play Store use Flutter, more than all other cross-platform frameworks put together. Flutter is picking up market share from other cross-platform frameworks, which are flat or declining over the last twelve months.
Top Popular App built with flutter

  1. Alibaba Groups
  2. Google pay
  3. ByteDance
  4. BMW
  5. Dream11
  6. Nubank
  7. Pubg Mobile
  8. AWS Amplify
  9. Google ClassRoom
  10. Zerodha

How to Automate Flutter App
Flutter app automation is not always straightforward.
Flutter apps render using a two-stage process:

  1. Widget tree
  2. Render Object tree

The flutter rendering engine is highly efficient and can render complex UIs at high frame rates. This is because the rendering engine uses a number of optimizations, such as caching render objects and batching draws calls.

There are a few different ways to automate flutter apps.
1. Flutter Driver:

Flutter driver used to interact with the app's UI, verify that the app is behaving as expected and perform other tasks.
To use flutter driver, you need to install it's dependency in your flutter project

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_driver:
    sdk: flutter
  test: any
Enter fullscreen mode Exit fullscreen mode

Sample test

import 'package:flutter_driver/driver_extension.dart';
import 'package:test/main.dart' as app;

void main() {
  enableFlutterDriverExtension();
  app.main();
}

test('increments the counter', () async {
      await driver.tap(incrementButtonFinder);

      expect(await driver.getText(counterTextFinder), "1");
    });
Enter fullscreen mode Exit fullscreen mode

Challenges that can encounter when using Flutter Driver to Automate Flutter apps:

  1. Writing test in other languages than Dart
  2. Running integration test for Flutter app with embedded webview or native view, or existing native app with embedded Flutter view
  3. Running test on multiple devices simultaneously(Parallel Run)
  4. Running integration test on device farms, such as Sauce Labs, HeadSpin, AWS, Firebase

2. Appium Flutter Driver

Appium Flutter Driver is the most popular tool used to automate Flutter apps.
Appium is a cross-platform automation tool that can be used to automate apps that run on a variety of platform, including flutter.

Pre Requisite
Your Flutter app-under-test (AUT) must be compiled in debug or profile mode, because Flutter Driver does not support running in release mode. Also, ensure that your Flutter AUT has enableFlutterDriverExtension() before running App. Then, please make sure your app imported flutter_driver package as its devDependencies as well.

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_driver:
    sdk: flutter
  test: any
Enter fullscreen mode Exit fullscreen mode
import 'package:flutter/material.dart';
import 'package:flutter_driver/driver_extension.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
import 'package:hello_world/stream.dart';

part 'main.g.dart';

void main() {
enableFlutterDriverExtension(enableTextEntryEmulation: false);
 init();
  runApp(MyApp());
}

@widget
Widget myApp() => MaterialApp(
  title: 'Counter App',
  home: MyHomePage(title: 'Counter App Home Page'),
);



@widget
Widget myHomePage(BuildContext context, {String title}) => Scaffold(
  appBar: AppBar(
    title: Text(title),
  ),
  body: Center(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text(
          'You have pushed the button this many times:',
        ),
        Tooltip(
          message: 'counter_tooltip',
          child: StreamBuilder<int>(
            stream: counterStream,
            builder: (context, snapshot) {
              return Text(
                '${snapshot.data}',
                key: Key('counter'),
                style: Theme.of(context).textTheme.display1,
                semanticsLabel: 'counter_semantic',
              );
            }
          ),
        ),
        FlatButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                  builder: (context) => Scaffold(
                        appBar: AppBar(
                          title: Text("Second Route"),
                        ),
                        body: Center(
                          child: SecondPage(),
                        ),
                      )),
            );
          },
          child: Text(
            'Go to next route',
            key: Key('next_route_key'),
          ),
        ),
      ],
    ),
  ),
  floatingActionButton: FloatingActionButton(
    // Provide a Key to this button. This allows finding this
    // specific button inside the test suite, and tapping it.
    key: Key('increment'),
    onPressed: () => plusClickSink.add(null),
    tooltip: 'Increment',
    child: Icon(Icons.add),
  ),
);

@widget
Widget secondPage() => ListView(
  padding: const EdgeInsets.all(8.0),
  children: <Widget>[
    Container(
      height: 100,
      color: Colors.amber[600],
      child: const Center(child: Text('This is 2nd route')),
    ),
    Container(
      height: 200,
      color: Colors.amber[500],
      child: const Center(child: Text('Entry B')),
    ),
    Container(
      height: 500,
      color: Colors.amber[100],
      child: const Center(child: Text('Entry C')),
    ),
    Container(
      height: 1000,
      color: Colors.amber[100],
      child: const Center(child: Text('Entry D')),
    ),
    Container(
      height: 1000,
      color: Colors.amber[100],
      child: const Center(
          child: TextField(
        decoration: InputDecoration(
          border: OutlineInputBorder(),
          labelText: 'Sample Input',
        ),
      )),
    ),
  ],
);
Enter fullscreen mode Exit fullscreen mode

Automation Code:

Add maven dependency to pom.xml
<dependency>
    <groupId>io.github.ashwithpoojary98</groupId>
    <artifactId>appium_flutterfinder_java</artifactId>
    <version>1.0.1</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

import io.appium.java_client.AppiumDriver;

public class FlutterFinderExampleTest {
    RemoteWebDriver driver;

    @BeforeMethod
    public void openApp() throws MalformedURLException {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability("deviceName", "emulator-5554");
        capabilities.setCapability("platformName", "Android");
        capabilities.setCapability("noReset", true);
        capabilities.setCapability("app", "");
        capabilities.setCapability("automationName", "Flutter");
        driver = new AppiumDriver(new URL("http://0.0.0.0:4723/wd/hub"), capabilities);
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
    }

    @Test
    public void appiumFlutterTest() {
        FlutterFinder finder = new FlutterFinder(driver);
        WebElement element = finder.byValueKey("increment");
        element.click();
    }

    @AfterMethod
    public void tearDown() {
        if (driver != null) {
            driver.quit();
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

GitHub logo ashwithpoojary98 / javaflutterfinder

Flutter driver with Java implementation

Appium Flutter Finder Java

Flutter appium driver is automation tool with java implementation.

Open Source Love GitHub stars PRs Welcome GitHub forks

maven-plugin

Build Status

Setup

Add maven dependency to pom.xml

<dependency>
    <groupId>io.github.ashwithpoojary98</groupId>
    <artifactId>appium_flutterfinder_java</artifactId>
    <version>1.0.1</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Maven Center Repo link

https://mvnrepository.com/artifact/io.github.ashwithpoojary98/appium_flutterfinder_java

Usage

import io.appium.java_client.AppiumDriver
public class FlutterFinderExampleTest {
    RemoteWebDriver driver;

    @BeforeMethod
    public void openApp() throws MalformedURLException {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability("deviceName", "emulator-5554");
        capabilities.setCapability("platformName", "Android");
        capabilities.setCapability("noReset", true);
        capabilities.setCapability("app", "");
        capabilities.setCapability("automationName", "Flutter");
        driver = new AppiumDriver(new URL("http://0.0.0.0:4723/wd/hub"), capabilities);
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
    }

    @Test
    public void appiumFlutterTest
Enter fullscreen mode Exit fullscreen mode

If you have any queries at all, please feel free to reach out.
Gmail: ashwithpoojary98@gmail.com
Insta: ashwith__poojary
Github: https://github.com/ashwithpoojary98

Thank you....

Top comments (0)