A test driver for Flutter to do QA testing without sharing app source code. It exposes a JSON API using an HTTP server running inside the app. Using these APIs you can write tests in any language for your Flutter app.
Add package to dependencies:
flutter pub add autopilot
Create main_test.dart
along side of your main.dart
file. Make AutoPilot widget parent of your MaterialApp or root widget like below:
import 'package:flutter/material.dart';
import 'package:autopilot/autopilot.dart';
import 'my_app.dart';
void main() {
runApp(
Autopilot(child: MyApp())
);
}
Run your app on device/emulator:
flutter run --release --target lib/main_test.dart
On Android forward port 8080
so that you can access it via localhost
:
adb forward tcp:8080 tcp:8080
Consider following example:
Text(
"Hello World!",
key: Key("txtGreet"),
)
Example of a test in python using pytest
:
# example_test.py
import requests
root = "http://localhost:8080"
def get(path):
return requests.get(root + path).json()
def test_greet():
greet = get("/texts?key=txtGreet")[0]
assert greet["text"] == "Hello World!"
Run it:
python -m pytest example_test.py
Flutter has a really amazing testing suite for Unit, UI and Integration testing. But one problem is that you need to know/learn Dart and you have to share the source code of the app to the person who writes tests. This doesn't work in every work environments.
But Flutter framework is so transparent I was able to tap into its internals and build a JSON API which can provide pretty much everything you need to write UI automation tests.
GET /widgets
Returns entire widget tree
GET /keys
Returns list of all the keyed widgets
GET /texts
Returns list of all text widgets
GET /texts?text=<text>
Returns list of all text widgets with matching text
GET /texts?key=<key>
Returns text widget that matches key
GET /editables
Returns list of all text fields
GET /type?text=<text>
Types given text to the focused text field
GET /tap?x=<x>&y=<y>
Taps at given offset
GET /tap?key=<key>
Taps on widget with given key
GET /tap?text=<text>
Taps on text widget with given text
GET /hold?x=<x>&y=<y>
Tap and hold on given offset
GET /drag?x=<x>&y=<y>&dx=<dx>&dy=<dy>
Taps at (x,y) and drags (dx, dy) offset
GET /scroll?key=<key of scrollable>&dx=<dx>&dy=<dy>
Taps inside scrollable with given key and drags (dx, dy) offset
GET /scroll-into?scrollable-key=<key of scrollable>&key=<key of widget>&dx=<dx>&dy=<dy>&delay=<delay between drags in ms>&timeout=<timeout in ms>
Taps inside widget with given scrollable-key
and drags (dx, dy) offset until given key
is present in the widget tree. If the widget is inside a scrollable it will be made visible.
After one drag action it will pause for delay
milliseconds and then check for the key
. Default value is 500 ms.
Operation times out after timeout
milliseconds. Default value is 5000 ms.
GET /screenshot
Returns screenshot of app in PNG
GET /keyboard
Shows keyboard
DELETE /keyboard
Hides keyboard
POST /keyboard?type=<type>
Submits a keyboard action.
Some actions may not be available on all platforms. See TextInputAction for more information.