Flutter app automate testing with Appium Flutter Driver

netfirms

Taweechai Maklay

Posted on November 2, 2019

Flutter app automate testing with Appium Flutter Driver

As tech person whom adopted flutter in tech portfolio (got much friction around this). The most question I've got is testing automation engineer did not know dart and appium not officialy support flutter, how can they write test for it, how can they do automate test with it? So I will share context about how we can test flutter application with appium-flutter-driver with a practical example.

Project setup

  • Since Flutter did not use native conponents, it's mean you need to define keys in all of your widget to made your widgets visible to appium-flutter-driver (also for normal flutter testing).

Be aware! your testing apk need to be "debug" or "profiling" package.

Example

Text(
  'Welcome to Home Page',
  key: Key('homeGreetingLbl'),
)
Enter fullscreen mode Exit fullscreen mode
  • Add "enableFlutterDriverExtension()" before "runApp()"
void main() {
  enableFlutterDriverExtension();
  runApp(MyApp());
}
Enter fullscreen mode Exit fullscreen mode
  • Add "test" and "flutter-driver" to pubspec.yml
dev_dependencies:
  test: any
  flutter_test:
    sdk: flutter
  flutter_driver:
    sdk: flutter
Enter fullscreen mode Exit fullscreen mode

My tutorial was extended from TruongSinh Tran-Nguyen's tutorial, Big thank you to him. Installation can follow with his tutorial as below.

GitHub logo appium / appium-flutter-driver

Appium Flutter Driver is a test automation tool for Flutter apps on multiple platforms/OSes. Appium Flutter Driver is part of the Appium mobile test automation tool maintained by community

Appium Flutter Driver

NPM version Downloads

Appium Flutter Driver is a test automation tool for Flutter apps on multiple platforms/OSes. Appium Flutter Driver is part of the Appium mobile test automation tool maintained by the community. Feel free to create PRs to fix issues/improve this driver.

Flutter Driver vs Appium Flutter Driver

Even though Flutter comes with superb integration test support, Flutter Driver, it does not fit some specific use cases, such as

  • Writing tests in other languages than Dart
  • Running integration test for Flutter app with embedded webview or native view, or existing native app with embedded Flutter view
  • Running tests on multiple devices simultaneously
  • Running integration tests on device farms that offer Appium support (Please contact the availability for each vendor)

Under the hood, Appium Flutter Driver uses the Dart VM Service Protocol with extension ext.flutter.driver, similar to Flutter Driver, to control the Flutter app-under-test (AUT).

Appium drivers for

Let's test our app with appium-flutter-driver!

I've created demo application for our appium testing in github you can checkout and try

Appium-flutter-driver demo

Flutter example project for appium-flutter-driver.




Project has flutter app project and "appium" directory for testing. In "appium" directory consist of

  • 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": "TruongSinh Tran-Nguyen <i@truongsinh.pro",
  "private": true,
  "license": "MIT"
}
Enter fullscreen mode Exit fullscreen mode
  • test.js - This is 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',
  // @todo support non-unix style path
  app: __dirname +  '/../build/app/outputs/apk/debug/app-debug.apk',
}: 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'), 'test@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('homeGreetingLbl'));
  assert.strictEqual(await driver.getElementText(find.byValueKey('homeGreetingLbl')), 'Welcome to Home Page');

  //Enter Page1
  await driver.elementClick(find.byValueKey('page1Btn'));
  await driver.execute('flutter:waitFor', find.byValueKey('page1GreetingLbl'));
  assert.strictEqual(await driver.getElementText(find.byValueKey('page1GreetingLbl')), 'Page1');
  await driver.elementClick(find.byValueKey('page1BackBtn'));

  //Enter Page2
  await driver.elementClick(find.byValueKey('page2Btn'));
  await driver.execute('flutter:waitFor', find.byValueKey('page2GreetingLbl'));
  assert.strictEqual(await driver.getElementText(find.byValueKey('page2GreetingLbl')), 'Page2');
  await driver.switchContext('NATIVE_APP');
  await driver.back();
  await driver.switchContext('FLUTTER');

  //Logout application
  await driver.elementClick(find.byValueKey('logoutBtn'));
  driver.deleteSession();
})();
Enter fullscreen mode Exit fullscreen mode

Run Appium (Android)

  1. Change directory to "appium" folder.
  2. Start appium server with command "appium" in console.
  3. Start Android emulator (check your emulator address with "adb devices
Taweechais-MBP:~ taweechaimaklay$ adb devices
List of devices attached
emulator-5554   device
Enter fullscreen mode Exit fullscreen mode

install required nodejs package

npm install
Enter fullscreen mode Exit fullscreen mode

and change Android configuration in test.js") and run command

APPIUM_OS=android npm start
Enter fullscreen mode Exit fullscreen mode

to start appium automation.

Testing result

Automated running application with appium-flutter-driver
Appium run flutter app

Console output as below

Others Appium's command which I've tested.

//Enter value to tartget TextInput
await driver.elementSendKeys(find.byValueKey('telphoneEditTxt'), '1234567890')

//Wait for element visible
await driver.execute('flutter:waitFor', find.byValueKey('page2Btn'));

//Screen scrolling
await driver.execute('flutter:scrollIntoView', find.byValueKey('bottomSubmitBtn'), {alignment: 0.1});

//Using Native command and switch context back to flutter
await driver.switchContext('NATIVE_APP');
  driver.back();
await driver.switchContext('FLUTTER');

//Tap on widget element
await driver.elementClick(find.byValueKey('backBtn'));

Enter fullscreen mode Exit fullscreen mode

Conclusion

I did not have strong opinion about appium-flutter-driver is the best way to do flutter app automate testing. But it help QA or automation tester to get familiar with flutter app testing since they can reuse their Appium which already mature to start automate flutter app testing and they can lower their guard about flutter which is very new platform and not much test tooling for it. By the way for flutter developer I think flutter-driver is enough for automate testing (since they already know dart :)). That all from me, comment, question and suggestion is welcome.

💖 💪 🙅 🚩
netfirms
Taweechai Maklay

Posted on November 2, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related