Automating Flutter App Using Flutter Appium driver
Tags: fultterappautomation, appium, java, appautomation
Published: 2023-07-08 10:07:59



![Flutter App Automation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v2nj6eecffrr8wpb22lb.png)
**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
```
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");
    });
```
**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
```
```
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',
        ),
      )),
    ),
  ],
);
```

**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>
```

```

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();
        }
    }
}
```
{% embed https://github.com/ashwithpoojary98/javaflutterfinder %}

__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....