我们的 UI 测试套件显示了一些意外行为,其中我们的“创建密码”屏幕间歇性地自动完成用户名和密码 - 这会导致测试失败。
过程是这样的:
最后一步失败,因为两个字段中的密码已自动完成。
这种情况大约每十到二十次测试执行中就会发生一次。
我们的理解是,在任何模拟器中都不应该看到密码自动填充,因此看到这一点非常令人困惑。我们可以采取一些措施来额外禁用自动填充,或者以其他方式防止这种情况发生吗?
有同样的问题。对我有用的是模拟器的设置 -> 密码 -> 打开然后关闭自动填充密码。
不确定从一开始是否就是这样,但设置
isSecureTextEntry = true
也足以触发该错误(至少在 Xcode 12.2 中)。
因此,对我有用的解决方法是:
let field = UITextField()
if #available(iOS 11.0, *) {
#if targetEnvironment(simulator)
// Do Not enable '.password' or '.newPassword' or 'isSecureTextEntry' text content type on simulator as it ends up with annoying behaviour:
// 'Strong Password' yellow glitch preventing from editing field.
print("Simulator! not setting password-like text content type")
#else
field.textContentType = .password
field.isSecureTextEntry = true
#endif
}
field.placeholder = "Password"
转到模拟器中的密码设置。 关闭自动填充(如果已关闭打开和关闭)。 点击安全建议并关闭检测泄露的密码。 你可以走了..
您可以使用以下方法在模拟器上禁用密码自动填充:
不确定是否需要所有三个文件,但这就是“设置”应用程序中的开关所发生的变化。
plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/$SIMULATOR_ID/data/Containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles/Library/ConfigurationProfiles/UserSettings.plist
plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/$SIMULATOR_ID/data/Library/UserConfigurationProfiles/EffectiveUserSettings.plist
plutil -replace restrictedBool.allowPasswordAutoFill.value -bool NO ~/Library/Developer/CoreSimulator/Devices/$SIMULATOR_ID/data/Library/UserConfigurationProfiles/PublicInfo/PublicEffectiveUserSettings.plist
您可以从
SIMULATOR_ID
获得
xcrun simctl list
仅在 iOS 16.4 上测试过此功能
虽然您可以在模拟器中手动更改“自动填充密码”,但这对我来说不起作用,因为构建服务器上的自动 UI 测试在每次运行时都会重置,因此默认为打开状态。 另外,我们的一个库没有 x86_64 切片,因此它无法在 iOS13.x 模拟器上运行(iOS14 中提供了 arm64 模拟器支持)。
相反,我发现您可以通过 XCUITest 控制 Settings.app,因此我的测试的第一部分禁用“自动填充密码”,然后运行我自己的测试。
请注意同时使用 Settings.app 和 Springboard,因为密码对话框属于 Springboard。
let settingsApp = XCUIApplication(bundleIdentifier: "com.apple.Preferences")
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
settingsApp.launch()
settingsApp.tables.staticTexts["PASSWORDS"].tap()
let passcodeInput = springboard.secureTextFields["Passcode field"]
passcodeInput.tap()
passcodeInput.typeText("abc\r") // it accepts anything in simulator
settingsApp.tables.cells["PasswordOptionsCell"].buttons["chevron"].tap()
settingsApp.switches["AutoFill Passwords"].tap()
// launch my own app and start UI test
let app = XCUIApplication()
app.launch()
我确实尝试使用
.isSelected
测试开关是否打开,然后才更改它,但是 .isSelected
在开关的 XCUIElement 中似乎已损坏。
我刚刚改进了 @SharkBait 代码,添加了等待并支持多个调用。 谢谢!
private func disableAutoFillPasswords() throws {
let settingsApp = XCUIApplication(bundleIdentifier: "com.apple.Preferences")
let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
settingsApp.launch()
let passRow = settingsApp.tables.staticTexts["PASSWORDS"]
var exists = passRow.waitForExistence(timeout: TimeInterval(5))
if exists {
passRow.tap()
}
let passcodeInput = springboard.secureTextFields["Passcode field"]
exists = passcodeInput.waitForExistence(timeout: TimeInterval(5))
XCTAssertTrue(exists, "")
passcodeInput.tap()
passcodeInput.typeText("abc\r")
let cell = settingsApp.tables.cells["PasswordOptionsCell"].buttons["chevron"]
exists = cell.waitForExistence(timeout: TimeInterval(5))
XCTAssertTrue(exists, "Switcher exists")
cell.tap()
let switche = settingsApp.switches["AutoFill Passwords"]
exists = switche.waitForExistence(timeout: TimeInterval(5))
XCTAssertTrue(exists, "Switcher exists")
let enabledState = switche.value as? String
if enabledState == "1" {
settingsApp.switches["AutoFill Passwords"].tap()
}
}
感谢@SharkBait 提供的解决方案,它确实有助于在运行我的 ui 自动化之前以编程方式设置“自动填充密码”。
希望我完成了关于提到的“.isSelected”部分的最后一篇文章,我认为其目的是为了在点击“自动填充密码”设置之前尽早了解切换状态。
这就是我所做的:
// turn the toggle to OFF only when it's ON
let value = settingsApp.switches["AutoFill Passwords"].value as? String
if value == "1" {
settingsApp.switches["AutoFill Passwords"].tap()
}
设法使用以下命令修复它:
script {
// retrieve the iOS simulator id the tests will be run on
def SIMULATOR_ID = sh (script: "xctrace list devices | grep 'iPhone 14' | grep '17.0.1' | awk -F '[()]' '{print \$4}'", returnStdout: true).trim()
// disable AutoFillPasswords
sh "plutil -replace AutoFillPasswords -bool false '../Library/Developer/CoreSimulator/Devices/$SIMULATOR_ID/data/Library/Preferences/com.apple.WebUI.plist'"
// restart (shutdown if needed and boot) the iOS simulator for the changes to take action
try {
sh "xcrun simctl shutdown $SIMULATOR_ID"
} catch (err) {
echo "Unable to shutdown device as it is already shutdown. Error: ${err.getMessage()}"
}
sh "xcrun simctl boot $SIMULATOR_ID"
}
这是 iOS 14 的一个错误,仅在使用模拟器时出现。
解决方法是安装iOS 13.7:
打开 Xcode,单击“首选项”,然后单击“组件”。
在模拟器上选择、下载并安装 iOS 13.7 操作系统。
然后再次运行您的应用程序。您可以在模拟器顶部标签上查看您的 iOS 版本。它应该显示正确的。