Xcode录制含WebView的UI测试时崩溃问题咨询
我之前也碰到过完全一样的问题!Xcode 9的UI测试录制器在处理WebView(尤其是Facebook登录这类第三方Auth页面)的时候确实存在一个已知的兼容性bug,咱们来拆解下原因和可行的解决办法:
为什么会崩溃?
从你贴的崩溃日志里的关键信息——NSInternalInconsistencyException和First snapshot has type Other: Other, 0x7f9d8c64aaf0, {{0.0, 0.0}, {0.0, 0.0}}——就能看出问题所在:Xcode的录制器在尝试捕获WebView内部元素的快照时,生成了一个尺寸为0的无效快照,直接触发了内部断言失败,导致Xcode崩溃。
这个问题在Xcode 9.x版本里很常见,因为Xcode的UI测试录制功能原本是针对原生UI元素设计的,对WebView里的网页DOM元素识别支持得非常差,尤其是加载第三方网页的时候,录制器根本没法正确解析Web内容的结构,自然就崩了。
解决办法有这些,按需选:
1. 放弃录制,手动写WebView的测试代码
既然录制用不了,那就直接写代码就行。针对Facebook登录的WebView,你可以用XCUIElementQuery定位WebView里的元素,示例代码如下:
let app = XCUIApplication() app.launch() // 先点击触发Facebook登录的原生按钮 app.buttons["FacebookLoginButton"].tap() // 等待WebView加载完成(给点缓冲时间) let webView = app.webViews.element guard webView.waitForExistence(timeout: 10) else { XCTFail("WebView加载超时") return } // 定位邮箱输入框(注意:这里的标识符要和Facebook登录页的元素name/id对应) let emailField = webView.textFields["email"] emailField.tap() emailField.typeText("your-test-email@example.com") // 定位密码输入框 let passwordField = webView.secureTextFields["pass"] passwordField.tap() passwordField.typeText("your-test-password") // 点击登录按钮 webView.buttons["login"].tap()
小贴士:WebView里的元素标识符可以通过两种方式获取:一是用浏览器打开Facebook登录页,查看元素的name或id;二是用Xcode的Debug View Hierarchy工具(不过有时候WebView的元素可能不会完全显示,这时候浏览器的方法更靠谱)。
2. 升级Xcode到10及以上版本
苹果在Xcode 10里修复了这个WebView录制的bug,优化了录制器对Web内容的识别能力。如果你的项目环境允许升级Xcode,这是最省心的办法——升级之后,录制功能就能正常处理WebView的交互了。
3. 换成原生Facebook登录(推荐如果可行的话)
如果你的应用可以调整登录方式,建议用FBSDKLoginKit的原生登录组件代替WebView登录,比如LoginButton或者LoginManager。原生UI元素是Xcode录制器的强项,根本不会出现崩溃问题。示例代码:
import FBSDKLoginKit // 用LoginManager实现原生登录 let loginManager = LoginManager() loginManager.logIn(permissions: ["public_profile", "email"], from: self) { result, error in if let error = error { // 处理错误 print("登录失败:\(error.localizedDescription)") return } guard let result = result, !result.isCancelled else { print("用户取消登录") return } // 登录成功,获取用户信息 }
总结
这个问题就是Xcode 9的录制器对WebView支持不足导致的,最直接的解决路径要么手动写测试代码,要么升级Xcode;如果能换成原生登录,不仅解决测试问题,用户体验也更好。
内容的提问来源于stack exchange,提问作者A Israfil

