iOS混合应用中EarlGrey无法测试WkWebView内HTML UI元素问题
我之前也碰到过一模一样的情况——EarlGrey对原生UI测试确实顺手,但碰到WKWebView里的Web内容就容易掉链子。你用grey_javaScriptExecution失败的核心原因是:EarlGrey的这个API本质是为UIWebView设计的,对WKWebView的JS执行支持并不完善,而且通过grey_accessibilityID匹配到WKWebView后,执行JS的上下文也没正确关联到Web内容。
下面给你几个靠谱的解决方案,按推荐程度排序:
方案1:直接获取WKWebView实例执行JS
绕过EarlGrey的JS执行API,直接拿到WKWebView的原生实例,调用它自带的evaluateJavaScript方法,这是最稳定的方式:
func testTapWebViewElement() { // 先通过EarlGrey定位到WKWebView实例 var targetWebView: WKWebView? EarlGrey.select(elementWithMatcher: grey_accessibilityID("page_view")) .perform(grey_actionBlock { element, error in targetWebView = element as? WKWebView return true }) // 等待WebView加载完成(可根据实际场景调整等待逻辑) let jsExpectation = self.expectation(description: "JS execution complete") targetWebView?.evaluateJavaScript("document.getElementById('myLegend').click()") { result, error in if let jsError = error { XCTFail("点击元素失败:\(jsError.localizedDescription)") } jsExpectation.fulfill() } waitForExpectations(timeout: 5, handler: nil) }
方案2:给Web元素添加可访问性属性,让EarlGrey识别
如果你的测试更偏向模拟真实用户交互(而非直接执行JS),可以给HTML元素添加ARIA可访问性属性,让EarlGrey能像识别原生控件一样识别它:
首先修改你的HTML代码,给目标元素加上合适的角色和标签:
<div id="myLegend" role="button" aria-label="My Legend Control"></div>
然后在测试代码里直接用EarlGrey的tap动作:
func testTapAccessibleWebElement() { // 匹配Web元素的可访问性标签 EarlGrey.select(elementWithMatcher: grey_accessibilityLabel("My Legend Control")) .perform(grey_tap()) }
⚠️ 注意:要确保你的WKWebView开启了可访问性支持(默认是开启的,但如果有自定义设置要检查),这样Web内容的可访问性元素才会被暴露给原生测试框架。
为什么你的原代码会失败?
grey_javaScriptExecution这个EarlGrey动作是基于UIWebView的stringByEvaluatingJavaScriptFromString方法实现的,而WKWebView的JS执行是异步的,EarlGrey的这个API没有适配WKWebView的异步逻辑,所以执行时会抛出异常。
内容的提问来源于stack exchange,提问作者rlr

