flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
166.26k stars 27.51k forks source link

Better error response from Flutter testing/driver APIs #32009

Open adazh opened 5 years ago

adazh commented 5 years ago

Currently when the error occurs when talking to the Flutter testing/driver APIs, the API returns a text containing error message and traces. It would be brittle if Espresso/EarlGrey relies on passing the error text to interpret the error.

Two examples: 1) When no matching UI element is found: JSON-RPC Request sent to uri ws://127.0.0.1:45257/Q-Bxibr0quE=/ws:

{
  "id": "message-2",
  "method": "ext.flutter.driver",
  "params": {
    "isolateId": "isolates/root",
    "text": "Increment2",
    "finderType": "ByTooltipMessage",
    "command": "tap",
    "timeout": 10000
  },
  "jsonrpc": "2.0"
}

JSON-RPC response received:

 {
  "jsonrpc": "2.0",
  "result": {
    "isError": true,
    "response": "Timeout while executing tap: TimeoutException after 0:00:10.000000: Future not completed\n#0      FlutterDriverExtension.call (package:flutter_driver/src/extension/extension.dart:184:31)\n<asynchronous suspension>\n#1      BindingBase.registerServiceExtension.<anonymous closure> (package:flutter/src/foundation/binding.dart:512:32)\n<asynchronous suspension>\n#2      _runExtension (dart:developer-patch/developer.dart:84:23)\n",
    "type": "_extensionType",
    "method": "ext.flutter.driver"
  },
  "id": "message-2"
}

2) When there are multiple UI element matches: JSON-RPC Request sent to uri ws://127.0.0.1:38582/Bc3XMX9_8wk=/ws:

{
  "id": "message-2",
  "method": "ext.flutter.driver",
  "params": {
    "isolateId": "isolates/root",
    "text": "Increment",
    "finderType": "ByTooltipMessage",
    "command": "tap",
    "timeout": 10000
  },
  "jsonrpc": "2.0"
}

JSON-RPC response received:

{
  "jsonrpc": "2.0",
  "result": {
    "isError": true,
    "response": "Uncaught extension error while executing tap: Bad state: Too many elements\n#0      Iterable.single (dart:core/iterable.dart:554:24)\n#1      WidgetController._getElementPoint (package:flutter_test/src/controller.dart:612:47)\n#2      WidgetController.getCenter (package:flutter_test/src/controller.dart:584:12)\n#3      WidgetController.tap (package:flutter_test/src/controller.dart:256:18)\n#4      FlutterDriverExtension._tap (package:flutter_driver/src/extension/extension.dart:324:19)\n<asynchronous suspension>\n#5      FlutterDriverExtension.call (package:flutter_driver/src/extension/extension.dart:181:53)\n<asynchronous suspension>\n#6      BindingBase.registerServiceExtension.<anonymous closure> (package:flutter/src/foundation/binding.dart:512:32)\n<asynchronous suspension>\n#7      _runExtension (dart:developer-patch/developer.dart:84:23)\n",
    "type": "_extensionType",
    "method": "ext.flutter.driver"
  },
  "id": "message-2"
}

Proposal: 1) Using error codes in the responses to better present the errors; 2) Possibly clean up the error messages to make it more user-readable.

adazh commented 5 years ago

@goderbauer

goderbauer commented 5 years ago

Adding error codes sounds good. Unfortunately, most exceptions are currently just caught by a catch-all. It would be very helpful if you can post all exception types you run into on this bug and I can then go through them to give them specific error codes.

adazh commented 5 years ago

A few off the top of my mind: 1) Timeout; 2) No matching widget; 3) Multiple matching; ...

I think we could start with these three.