-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[auick_action_ios] Retries multiple times to not fail ci when there is a flake #3823
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,20 @@ | |
import XCTest | ||
|
||
private let elementWaitingTime: TimeInterval = 30 | ||
// The duration in when pressing the app icon to open the | ||
// quick action menu. This duration is undocumented by Apple. | ||
// The duration will be adjusted with `pressDurationRetryAdjustment` if | ||
// this duration does not result in the quick action menu opened. | ||
private let quickActionPressDuration: TimeInterval = 1.5 | ||
// If the previous try to open quick action menu did not work, | ||
// a new try with adjust the press time by this value. | ||
// The adjusment could be + or - depends on the result of the previous try. | ||
private let pressDurationRetryAdjustment: TimeInterval = 0.2 | ||
// Max number of tries to open the quick action menu if failed. | ||
// This is to deflake a situation where the quick action menu is not present after | ||
// the long press. | ||
// See: https://github.com/flutter/flutter/issues/125509 | ||
private let quickActionMaxRetries: Int = 4; | ||
|
||
class RunnerUITests: XCTestCase { | ||
|
||
|
@@ -25,22 +39,8 @@ class RunnerUITests: XCTestCase { | |
func testQuickActionWithFreshStart() { | ||
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") | ||
let quickActionsAppIcon = springboard.icons["quick_actions_example"] | ||
if !quickActionsAppIcon.waitForExistence(timeout: elementWaitingTime) { | ||
XCTFail( | ||
"Failed due to not able to find the example app from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)" | ||
) | ||
} | ||
|
||
quickActionsAppIcon.press(forDuration: 2) | ||
|
||
let actionTwo = springboard.buttons["Action two"] | ||
if !actionTwo.waitForExistence(timeout: elementWaitingTime) { | ||
XCTFail( | ||
"Failed due to not able to find the actionTwo button from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)" | ||
) | ||
} | ||
|
||
actionTwo.tap() | ||
findAndTapQuickActionButton(buttonName: "Action two", quickActionsAppIcon: quickActionsAppIcon, springboard: springboard); | ||
|
||
let actionTwoConfirmation = exampleApp.otherElements["action_two"] | ||
if !actionTwoConfirmation.waitForExistence(timeout: elementWaitingTime) { | ||
|
@@ -73,24 +73,50 @@ class RunnerUITests: XCTestCase { | |
) | ||
} | ||
|
||
quickActionsAppIcon.press(forDuration: 2) | ||
findAndTapQuickActionButton(buttonName: "Action one", quickActionsAppIcon: quickActionsAppIcon, springboard: springboard); | ||
|
||
let actionOne = springboard.buttons["Action one"] | ||
if !actionOne.waitForExistence(timeout: elementWaitingTime) { | ||
let actionOneConfirmation = exampleApp.otherElements["action_one"] | ||
if !actionOneConfirmation.waitForExistence(timeout: elementWaitingTime) { | ||
XCTFail( | ||
"Failed due to not able to find the actionOne button from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)" | ||
"Failed due to not able to find the actionOneConfirmation in the app with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)" | ||
) | ||
} | ||
|
||
actionOne.tap() | ||
XCTAssert(actionOneConfirmation.exists) | ||
} | ||
|
||
let actionOneConfirmation = exampleApp.otherElements["action_one"] | ||
if !actionOneConfirmation.waitForExistence(timeout: elementWaitingTime) { | ||
private func findAndTapQuickActionButton(buttonName: String, quickActionsAppIcon: XCUIElement, springboard: XCUIElement) { | ||
var actionButton: XCUIElement? | ||
var pressDuration = quickActionPressDuration | ||
for _ in 1...quickActionMaxRetries { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. may wanna write a helper function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
if !quickActionsAppIcon.waitForExistence(timeout: elementWaitingTime) { | ||
XCTFail( | ||
"Failed due to not able to find the example app from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)" | ||
) | ||
} | ||
quickActionsAppIcon.press(forDuration: pressDuration) | ||
actionButton = springboard.buttons[buttonName] | ||
if actionButton!.waitForExistence(timeout: elementWaitingTime) { | ||
// find the button, exit the retry loop. | ||
break | ||
} | ||
let deleteButton = springboard.buttons["DeleteButton"] | ||
if deleteButton.waitForExistence(timeout: elementWaitingTime) { | ||
// Found delete button instead, we pressed too long, reduce the press time. | ||
pressDuration -= pressDurationRetryAdjustment | ||
} else { | ||
// Neither action button nor delete button was found, we need a longer press. | ||
pressDuration += pressDurationRetryAdjustment | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This makes sense to me. though the drawback is that it makes the test a bit complicated, as test code itself is not tested. i would simply try like 1, 1.33, 1.66 and 2. but up to you. |
||
} | ||
// Reset to previous state. | ||
XCUIDevice.shared.press(XCUIDevice.Button.home) | ||
} | ||
if (!actionButton!.exists) { | ||
XCTFail( | ||
"Failed due to not able to find the actionOneConfirmation in the app with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)" | ||
"Failed due to not able to find the \(buttonName) button from springboard with \(elementWaitingTime) seconds. Springboard debug description: \(springboard.debugDescription)" | ||
) | ||
} | ||
|
||
XCTAssert(actionOneConfirmation.exists) | ||
actionButton!.tap(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add a short explanation why we need to retry?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done