appium-flutter-driver
appium-flutter-driver copied to clipboard
feat: add "delay" to get an observatory url after launching an app
i'm finding an issue with appium : the problem that i want the app to reset after each test case : for example here i want the app to reset after the "Empty Fields Test" test case to begin the "Invalid Email and Password" test case with a cleaner state to prevent unwanted behaviour like not being in the desired screen or something like this : HERE Is my Code : const find = require('appium-flutter-finder'); describe('Login Flow', () => { it('Empty Fields Test', async () => { await driver.switchContext('FLUTTER'); await driver.execute('flutter:waitFor', find.byText("Sign in"), 3000) const emailField = find.byValueKey("emailValue"); const passwordField = find.byValueKey("passwordValue") const loginButton = find.byValueKey("loginButton"); await driver.elementClick(loginButton) await driver.execute("flutter:waitFor", find.byText("Email is required")) await driver.execute("flutter:waitFor", find.byText("Password is required")) }) it('Invalid Email And Password', async () => { await driver.execute('flutter:waitFor', find.byText("Sign in"), 1000 * 10) const emailField = find.byValueKey("emailValue"); const passwordField = find.byValueKey("passwordValue") const loginButton = find.byValueKey("loginButton"); await driver.elementSendKeys(emailField, "aymen") await driver.elementSendKeys(passwordField, "aymen") await driver.elementClick(loginButton) await driver.execute("flutter:waitFor", find.byText("Please make sure to enter valid email")) await driver.execute("flutter:waitFor", find.byText("Password should contain at least 8 characters")) }) })
@KazuCocoa i tried adding this hook : afterEach(async ()=>{ await driver.terminateApp("com.carnet.carnet"); await driver.activateApp("com.carnet.carnet"); }) but i got an error saying "Encountered internal error running command: Error: Cannot connect to the Dart Observatory URL ws://127.0.0.1:38803/XwAV6GrKP4g=/ws after 10 retries." , and here is the appium log appium.log
In your case, maybe the first attempt got the previous observatory url, then the next one was the expected one. This was because, maybe your app took a bit longer time to start up, so the observatory url printed in the system log a bit late as well. In current implementation, appium flutter driver pick the latest observatory url, so such "delay" could cause this behavior.
[HTTP] --> POST /session/4bb56829-6b7d-4057-bbf8-cb33ae1f666c/appium/device/activate_app
[HTTP] {"appId":"com.carnet.carnet"}
[debug] [FlutterDriver@abee (4bb56829)] Calling AppiumDriver.activateApp() with args: ["com.carnet.carnet",null,null,null,"4bb56829-6b7d-4057-bbf8-cb33ae1f666c"]
[debug] [FlutterDriver] Executing Flutter driver command 'activateApp'
[debug] [AndroidUiautomator2Driver@77db (2b79dfa4)] Activating 'com.carnet.carnet'
[debug] [FlutterDriver] Establishing a connection to the Dart Observatory. Will retry 10 times with 3000ms delay between retries. These values could be customized by changing 'maxRetryCount' and 'retryBackoffTime' capabilities.
[FlutterDriver] Attempt #1 of 10
[debug] [ADB] Forwarding system: 38803 to device: 38803
[debug] [ADB] Running 'C:\Users\LENOVO\AppData\Local\Android\Sdk\platform-tools\adb.exe -P 5037 -s emulator-5554 forward tcp:38803 tcp:38803'
[debug] [ADB] Running 'C:\Users\LENOVO\AppData\Local\Android\Sdk\platform-tools\adb.exe -P 5037 -s emulator-5554 shell cmd package resolve-activity --brief com.carnet.carnet'
[FlutterDriver] {}
[FlutterDriver] Waiting 3000ms before retrying
[debug] [ADB] Running 'C:\Users\LENOVO\AppData\Local\Android\Sdk\platform-tools\adb.exe -P 5037 -s emulator-5554 shell am start-activity -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -f 0x10200000 -n com.carnet.carnet/.MainActivity'
[debug] [AndroidUiautomator2Driver@77db (2b79dfa4)] Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.carnet.carnet/.MainActivity }
[FlutterDriver] Attempt #2 of 10
[FlutterDriver] {}
[FlutterDriver] Waiting 3000ms before retrying
[FlutterDriver] Attempt #3 of 10
[FlutterDriver] {}
[FlutterDriver] Waiting 3000ms before retrying
[FlutterDriver] Attempt #4 of 10
[FlutterDriver] {}
[FlutterDriver] Waiting 3000ms before retrying
[FlutterDriver] Attempt #5 of 10
[FlutterDriver] {}
[FlutterDriver] Waiting 3000ms before retrying
[FlutterDriver] Attempt #6 of 10
[FlutterDriver] {}
[FlutterDriver] Waiting 3000ms before retrying
[FlutterDriver] Attempt #7 of 10
[FlutterDriver] {}
[FlutterDriver] Waiting 3000ms before retrying
[FlutterDriver] Attempt #8 of 10
[FlutterDriver] {}
[FlutterDriver] Waiting 3000ms before retrying
[FlutterDriver] Attempt #9 of 10
[FlutterDriver] {}
[FlutterDriver] Waiting 3000ms before retrying
[FlutterDriver] Attempt #10 of 10
[FlutterDriver] {}
[debug] [FlutterDriver@abee (4bb56829)] Encountered internal error running command: Error: Cannot connect to the Dart Observatory URL ws://127.0.0.1:38803/XwAV6GrKP4g=/ws after 10 retries. Check the server log for more details
[debug] [FlutterDriver@abee (4bb56829)] at connectSocket (C:\Users\LENOVO\node_modules\appium-flutter-driver\lib\sessions\observatory.ts:154:9)
[debug] [FlutterDriver@abee (4bb56829)] at runMicrotasks (<anonymous>)
[debug] [FlutterDriver@abee (4bb56829)] at processTicksAndRejections (node:internal/process/task_queues:96:5)
[debug] [FlutterDriver@abee (4bb56829)] at connectAndroidSession (C:\Users\LENOVO\node_modules\appium-flutter-driver\lib\sessions\android.ts:39:3)
[debug] [FlutterDriver@abee (4bb56829)] at FlutterDriver.reConnectFlutterDriver (C:\Users\LENOVO\node_modules\appium-flutter-driver\lib\sessions\session.ts:19:21)
[debug] [FlutterDriver@abee (4bb56829)] at FlutterDriver.activateApp (C:\Users\LENOVO\node_modules\appium-flutter-driver\lib\driver.ts:119:5)
[HTTP] <-- POST /session/4bb56829-6b7d-4057-bbf8-cb33ae1f666c/appium/device/activate_app 500 27229 ms - 838
[HTTP]
[HTTP] --> POST /session/4bb56829-6b7d-4057-bbf8-cb33ae1f666c/appium/device/activate_app
[HTTP] {"appId":"com.carnet.carnet"}
[debug] [FlutterDriver@abee (4bb56829)] Calling AppiumDriver.activateApp() with args: ["com.carnet.carnet",null,null,null,"4bb56829-6b7d-4057-bbf8-cb33ae1f666c"]
[debug] [FlutterDriver] Executing Flutter driver command 'activateApp'
[debug] [AndroidUiautomator2Driver@77db (2b79dfa4)] Activating 'com.carnet.carnet'
[debug] [FlutterDriver] Establishing a connection to the Dart Observatory. Will retry 10 times with 3000ms delay between retries. These values could be customized by changing 'maxRetryCount' and 'retryBackoffTime' capabilities.
[FlutterDriver] Attempt #1 of 10
[debug] [ADB] Forwarding system: 36403 to device: 36403
[debug] [ADB] Running 'C:\Users\LENOVO\AppData\Local\Android\Sdk\platform-tools\adb.exe -P 5037 -s emulator-5554 forward tcp:36403 tcp:36403'
[debug] [ADB] Running 'C:\Users\LENOVO\AppData\Local\Android\Sdk\platform-tools\adb.exe -P 5037 -s emulator-5554 shell cmd package resolve-activity --brief com.carnet.carnet'
[debug] [ADB] Running 'C:\Users\LENOVO\AppData\Local\Android\Sdk\platform-tools\adb.exe -P 5037 -s emulator-5554 shell am start-activity -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -f 0x10200000 -n com.carnet.carnet/.MainActivity'
[debug] [AndroidUiautomator2Driver@77db (2b79dfa4)] Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.carnet.carnet/.MainActivity }
[FlutterDriver] Connecting to Dart Observatory: ws://127.0.0.1:36403/WAld9nelNUU=/ws
[FlutterDriver] Listing all isolates: [{"type":"@Isolate","id":"isolates/4491848110768655","name":"main","number":"4491848110768655","isSystemIsolate":false,"isolateGroupId":"isolateGroups/2200761780176179117"}]
[debug] [FlutterDriver@abee (4bb56829)] Responding to client with driver.activateApp() result: null
[HTTP] <-- POST /session/4bb56829-6b7d-4057-bbf8-cb33ae1f666c/appium/device/activate_app 200 486 ms - 14
This behavior is expected as current behavior, although to avoid this, maybe... we should define a method like flutter:activateApp(delaye: 100) to set delay before getting the observatory url
thank you for getting back to me , but is there any solution now to resolve the issue ?
also what about the issue of resetting the app before each test case like i mentioned in the first comment i made ? @KazuCocoa
We usually guide users to close the session, then create a new one as reset to clear the device local data etc. The terminate/activate apps just terminate/activate it. The app local data etc could remain.
as i understand there is no built-in algorithm that make driver clean app data and reset the state of the app after each test case @KazuCocoa :( ?
You could try https://github.com/appium/appium-uiautomator2-driver#mobile-clearapp out in NATIVE_APP context. It clear the target's data with am clean command. Some Android devices denies it, then what you can do as "cleanup the app state" is uninstalling the app, and installing it again.
okay i will try it thank you
Note that as WebDriver's design, each session is basically one test case. This driver is also expected to behave.
also i noticed something that may help you in the improvement of the activateApp so the issue of the disconnection with dart observatory does not persist , i did something like this , i entered credentials to the login screen etc and then i started the activity of gmail app and then i got back to the app by tapping the recent app buttom twice with "pressKeyCode"(187) , and i continued testing my app successfully : what i meant here that the appium-flutter-driver continued to work even after launching another app and getting back to the flutter app
The observatory's websocket connection depends on the Dart VM. The only case the connection gets disconnected is usually the app under test's Dart VM closes the socket.
Btw, this driver also provides flutter:connectObservatoryWsUrl, so you could also try the command out after calling activate_app in https://github.com/appium/appium-flutter-driver/issues/542#issuecomment-1685489581 (I noticed this command right now). Maybe it will help without a new feature, delay as a new feature.
Or I wondered if maxRetryCount as 30 or around may help in the https://github.com/appium/appium-flutter-driver/issues/542#issuecomment-1685489581 situation.
I've decreased the count to fail fast in https://github.com/appium/appium-flutter-driver/commit/f5ff626b1289dc6340273717bf5ad7b744b57631 but wondered if it should not do.
do you have any idea why the connection to dart observatory is not established ?
Generally, the app closed the session if the session has been established. The typical reason was when the app process stopped. This is app or OS side's handling.
If it was a fresh connection, the available observatory url is wrong like https://github.com/appium/appium-flutter-driver/issues/542#issuecomment-1685489581 situation.