我一直在尝试添加始终使用隐式和显式等待,同时为我的移动自动化框架设置基本的通用功能,并避免使用Thread.sleep(time)方法来保持更好的设计实践。最近,我一直在使用上下文切换时遇到使用等待的问题。切换上下文后,我得到的错误是TimeoutException,StaleElement引用或NoSuchElement异常,即使我在检查时也知道,我在寻找的元素在视图中。
我并不是完全在寻找解决此问题的建议,但我想知道这与在下面介绍的方案中使用等待是否是一种好方法。
(编辑)方案1(已解决) 我已经制作了一个函数,可以通过调用运行中的应用程序列表来模拟用户是否要恢复活动的应用程序,然后基于调用方法时提供的AccessibilityId,它将根据该ID查找元素,然后选择要恢复的元素到应用程序。 (方案1的代码在下面列出。)
方案2: 我已经创建了一个函数,它将继续沿任何方向(向上或向下)滑动,直到找到用户输入该方法的目标元素为止。由于滑动只能在“本机上下文”中进行,因此我将设置上下文切换为“本机”以进行滑动,然后切换回Web视图,或者使用默认视图搜索目标元素。我还将UIautomator2用作自动化,所以不确定在切换回Webview上下文后是否需要等待更长的时间(下面列出的方案2代码)。
到目前为止,我尝试不使用Thread.sleep(time)的唯一解决方案是在选择应用程序(方案1)之前或在调用findBy()时搜索元素是否会添加明确的等待(方案) 2)。
我在方案1中遇到的情况是,由于它执行click()方法,因此似乎可以找到该元素,但是它一直在寻找该元素并且找不到它,因为在恢复后该id不再存在到应用程序。我最终收到超时异常或某些情况下的陈旧元素异常。我不确定在wait.until()内部使用其他方法是否可以解决搜索元素的问题,直到找到它,然后单击。
(编辑)方案1的代码:(已解决)
void viewActiveAppList() {
driver.pressKey(new KeyEvent(AndroidKey.APP_SWITCH));
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
}
void resumeApp(String appName){
viewActiveAppList();
driver.context("NATIVE_APP");
MobileElement app = (MobileElement) wait.until(ExpectedConditions.elementToBeClickable(MobileBy.AccessibilityId(appName)));
app.click();
driver.context(defaultContext);
wait.waitUntilPageLoaded();
}
方案2代码:
swipeVertical:
void swipeVertical(double startPercentage, double finalPercentage, int duration) {
driver.context(nativeContext);
size = driver.manage().window().getSize();
int width = (int) (size.width/2);
int startPoint = (int) (size.getHeight() * startPercentage);
int endPoint = (int) (size.getHeight() * finalPercentage);
new AndroidTouchAction(driver)
.press(PointOption.point(width, startPoint))
.waitAction(WaitOptions.waitOptions(Duration.ofMillis(duration)))
.moveTo(PointOption.point(width, endPoint))
.release()
.perform();
driver.context(defaultContext);
}
swipeUntilFound:
void swipeUntilFound(By method, int attempts, MobileElement targetElement, Direction dir) {
int limitCount = 0;
double startScrollPoint = 0;
double endScrollPoint = 0;
switch (dir) {
case up:
startScrollPoint = 0.35;
endScrollPoint = 0.8;
break;
case down:
startScrollPoint = 0.8;
endScrollPoint = 0.35;
break;
default:
System.out.println("This method only supports directions up and down");
break;
}
List<MobileElement> searchAfterSwipe = driver.findElements(method);
while (searchAfterSwipe.isEmpty() || limitCount < attempts ) {
swipeVertical(startScrollPoint, endScrollPoint, 3000);
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
searchAfterSwipe = driver.findElements(method);
limitCount++;
}
if(limitCount == attempts) {
System.out.println("Unable to find Specified Element.");
}else {
targetElement = driver.findElement(method);
System.out.println("Element " + method.toString() + " was found.");
}
}
(编辑)对于场景1,我得到了TimeoutExceptions和Stale Element References。我可以通过切换到ExpectedConditions.elementToBeClickable()来解决此问题,因为我只需要找到此元素,直到它变得可单击即可。
对于方案2,这是捕获日志时来自我的远程服务器的日志,我将其修整到因找不到我提供的By方法而找不到该元素的问题。
[HTTP] [37m<-- POST /wd/hub/session/8fd3955f-3ca9-4678-849f-8fac412a6347/elements [39m[32m200[39m [90m385 ms - 108[39m
[HTTP] [90m[39m
[HTTP] [37m-->[39m [37mPOST[39m [37m/wd/hub/session/8fd3955f-3ca9-4678-849f-8fac412a6347/context[39m
[HTTP] [90m{"name":"NATIVE_APP"}[39m
[W3C (8fd3955f)] Calling AppiumDriver.setContext() with args: ["NATIVE_APP","8fd3955f-3ca9-4678-849f-8fac412a6347"]
[AndroidDriver] Available contexts: ["NATIVE_APP","CHROMIUM"]
[W3C (8fd3955f)] Responding to client with driver.setContext() result: null
[HTTP] [37m<-- POST /wd/hub/session/8fd3955f-3ca9-4678-849f-8fac412a6347/context [39m[32m200[39m [90m79 ms - 14[39m
[HTTP] [90m[39m
[HTTP] [37m-->[39m [37mGET[39m [37m/wd/hub/session/8fd3955f-3ca9-4678-849f-8fac412a6347/window/rect[39m
[HTTP] [90m{}[39m
[W3C (8fd3955f)] Calling AppiumDriver.getWindowRect() with args: ["8fd3955f-3ca9-4678-849f-8fac412a6347"]
[WD Proxy] Matched '/window/current/size' to command name 'getWindowSize'
[WD Proxy] Proxying [GET /window/current/size] to [GET http://localhost:8200/wd/hub/session/a0f6efb1-b817-427c-8b44-c79af74b08fe/window/current/size] with body: {}
[WD Proxy] Got response with status 200: "{\"sessionId\":\"a0f6efb1-b817-427c-8b44-c79af74b08fe\",\"status\":0,\"value\":{\"height\":2560,\"width\":1440}}"
[W3C (8fd3955f)] Responding to client with driver.getWindowRect() result: {"width":1440,"height":2560,"x":0,"y":0}
[HTTP] [37m<-- GET /wd/hub/session/8fd3955f-3ca9-4678-849f-8fac412a6347/window/rect [39m[32m200[39m [90m121 ms - 50[39m
[HTTP] [90m[39m
[HTTP] [37m-->[39m [37mPOST[39m [37m/wd/hub/session/8fd3955f-3ca9-4678-849f-8fac412a6347/touch/perform[39m
[HTTP] [90m{"actions":[{"action":"press","options":{"x":720,"y":896}},{"action":"wait","options":{"ms":3000}},{"action":"moveTo","options":{"x":720,"y":2048}},{"action":"release","options":{}}]}[39m
[W3C (8fd3955f)] Calling AppiumDriver.performTouch() with args: [[{"action":"press","options":{"x":720,"y":896}},{"action":"wait","options":{"ms":3000}},{"action":"moveTo","options":{"x":720,"y":2048}},{"action":"release","options":{}}],"8fd3955f-3ca9-4678-849f-8fac412a6347"]
[WD Proxy] Matched '/touch/perform' to command name 'performTouch'
[WD Proxy] Proxying [POST /touch/perform] to [POST http://localhost:8200/wd/hub/session/a0f6efb1-b817-427c-8b44-c79af74b08fe/touch/perform] with body: {"startX":720,"startY":896,"endX":720,"endY":2048,"steps":84}
[WD Proxy] Got response with status 200: {"sessionId":"67b7b41cf15632508b04b6bfc48f62cd","status":0,"value":[{"ELEMENT":"0.6576757443982535-1"}]}
[WD Proxy] Replacing sessionId 67b7b41cf15632508b04b6bfc48f62cd with 2464c639-5ba7-49f5-842a-dadd77f4e596
[HTTP] [37m<-- POST /wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/elements [39m[32m200[39m [90m5157 ms - 108[39m
[HTTP] [90m[39m
[HTTP] [37m-->[39m [37mPOST[39m [37m/wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/context[39m
[HTTP] [90m{"name":"NATIVE_APP"}[39m
[W3C (2464c639)] Calling AppiumDriver.setContext() with args: ["NATIVE_APP","2464c639-5ba7-49f5-842a-dadd77f4e596"]
[AndroidDriver] Available contexts: ["NATIVE_APP","CHROMIUM"]
[W3C (2464c639)] Responding to client with driver.setContext() result: null
[HTTP] [37m<-- POST /wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/context [39m[32m200[39m [90m90 ms - 14[39m
[HTTP] [90m[39m
[HTTP] [37m-->[39m [37mGET[39m [37m/wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/window/rect[39m
[HTTP] [90m{}[39m
[W3C (2464c639)] Calling AppiumDriver.getWindowRect() with args: ["2464c639-5ba7-49f5-842a-dadd77f4e596"]
[WD Proxy] Matched '/window/current/size' to command name 'getWindowSize'
[WD Proxy] Proxying [GET /window/current/size] to [GET http://localhost:8201/wd/hub/session/16c2134a-84d5-4ca7-98d8-9cf96217376d/window/current/size] with body: {}
[WD Proxy] Got response with status 200: "{\"sessionId\":\"16c2134a-84d5-4ca7-98d8-9cf96217376d\",\"status\":0,\"value\":{\"height\":1794,\"width\":1080}}"
[W3C (2464c639)] Responding to client with driver.getWindowRect() result: {"width":1080,"height":1794,"x":0,"y":0}
[HTTP] [37m<-- GET /wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/window/rect [39m[32m200[39m [90m283 ms - 50[39m
[HTTP] [90m[39m
[HTTP] [37m-->[39m [37mPOST[39m [37m/wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/touch/perform[39m
[HTTP] [90m{"actions":[{"action":"press","options":{"x":540,"y":627}},{"action":"wait","options":{"ms":3000}},{"action":"moveTo","options":{"x":540,"y":1435}},{"action":"release","options":{}}]}[39m
[W3C (2464c639)] Calling AppiumDriver.performTouch() with args: [[{"action":"press","options":{"x":540,"y":627}},{"action":"wait","options":{"ms":3000}},{"action":"moveTo","options":{"x":540,"y":1435}},{"action":"release","options":{}}],"2464c639-5ba7-49f5-842a-dadd77f4e596"]
[WD Proxy] Matched '/touch/perform' to command name 'performTouch'
[WD Proxy] Proxying [POST /touch/perform] to [POST http://localhost:8201/wd/hub/session/16c2134a-84d5-4ca7-98d8-9cf96217376d/touch/perform] with body: {"startX":540,"startY":627,"endX":540,"endY":1435,"steps":84}
[WD Proxy] Got response with status 200: {"sessionId":"a0f6efb1-b817-427c-8b44-c79af74b08fe","status":0,"value":true}
[W3C (8fd3955f)] Responding to client with driver.performTouch() result: true
[HTTP] [37m<-- POST /wd/hub/session/8fd3955f-3ca9-4678-849f-8fac412a6347/touch/perform [39m[32m200[39m [90m11402 ms - 14[39m
[HTTP] [90m[39m
[HTTP] [37m-->[39m [37mPOST[39m [37m/wd/hub/session/8fd3955f-3ca9-4678-849f-8fac412a6347/context[39m
[HTTP] [90m{"name":"CHROMIUM"}[39m
[W3C (8fd3955f)] Calling AppiumDriver.setContext() with args: ["CHROMIUM","8fd3955f-3ca9-4678-849f-8fac412a6347"]
[AndroidDriver] Available contexts: ["NATIVE_APP","CHROMIUM"]
[AndroidDriver] Connecting to chrome-backed webview context 'CHROMIUM'
[AndroidDriver] Found existing Chromedriver for context 'CHROMIUM'. Using it.
[WD Proxy] Matched '/url' to command name 'getUrl'
[WD Proxy] Proxying [GET /url] to [GET http://127.0.0.1:8001/wd/hub/session/aa3ae372d50348a0bbe746116f9e04b3/url] with no body
[WD Proxy] Got response with status 200: {"sessionId":"16c2134a-84d5-4ca7-98d8-9cf96217376d","status":0,"value":true}
[W3C (2464c639)] Responding to client with driver.performTouch() result: true
[HTTP] [37m<-- POST /wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/touch/perform [39m[32m200[39m [90m13457 ms - 14[39m
[HTTP] [90m[39m
[HTTP] [37m-->[39m [37mPOST[39m [37m/wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/context[39m
[HTTP] [90m{"name":"CHROMIUM"}[39m
[W3C (2464c639)] Calling AppiumDriver.setContext() with args: ["CHROMIUM","2464c639-5ba7-49f5-842a-dadd77f4e596"]
[AndroidDriver] Available contexts: ["NATIVE_APP","CHROMIUM"]
[AndroidDriver] Connecting to chrome-backed webview context 'CHROMIUM'
[AndroidDriver] Found existing Chromedriver for context 'CHROMIUM'. Using it.
[WD Proxy] Matched '/url' to command name 'getUrl'
[WD Proxy] Proxying [GET /url] to [GET http://127.0.0.1:8000/wd/hub/session/67b7b41cf15632508b04b6bfc48f62cd/url] with no body
[WD Proxy] Got response with status 200: "{\"sessionId\":\"67b7b41cf15632508b04b6bfc48f62cd\",\"status\":0,\"value\":\"https://www.google.com/search?source=hp&ei=StWmXJXmJtHq-gTwkrqwBg&q=star+wars&oq=star+wars&gs_l=mobile-gws-wiz-hp.12..0i131j0j46i131j0j0i131j46i131j0j46.10902.22037..27071...0.0..0.1451.6075.2-2j3j1j1j1j2......0....1.......0..46i275.inyUIvu9Es8\"}"
[W3C (2464c639)] Responding to client with driver.setContext() result: null
[HTTP] [37m<-- POST /wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/context [39m[32m200[39m [90m13084 ms - 14[39m
[HTTP] [90m[39m
[HTTP] [37m-->[39m [37mPOST[39m [37m/wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/timeouts[39m
[HTTP] [90m{"implicit":30000}[39m
[W3C (2464c639)] Driver proxy active, passing request on via HTTP proxy
[WD Proxy] Matched '/wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/timeouts' to command name 'timeouts'
[Protocol Converter] Will send the following request bodies to /timeouts: [{"type":"implicit","ms":30000}]
[WD Proxy] Proxying [POST /wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/timeouts] to [POST http://127.0.0.1:8000/wd/hub/session/67b7b41cf15632508b04b6bfc48f62cd/timeouts] with body: {"type":"implicit","ms":30000}
[WD Proxy] Got response with status 200: {"sessionId":"67b7b41cf15632508b04b6bfc48f62cd","status":0,"value":null}
[WD Proxy] Replacing sessionId 67b7b41cf15632508b04b6bfc48f62cd with 2464c639-5ba7-49f5-842a-dadd77f4e596
[HTTP] [37m<-- POST /wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/timeouts [39m[32m200[39m [90m165 ms - 76[39m
[HTTP] [90m[39m
[HTTP] [37m-->[39m [37mPOST[39m [37m/wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/elements[39m
[HTTP] [90m{"using":"name","value":"q"}[39m
[W3C (2464c639)] Driver proxy active, passing request on via HTTP proxy
[WD Proxy] Matched '/wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/elements' to command name 'findElements'
[WD Proxy] Proxying [POST /wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/elements] to [POST http://127.0.0.1:8000/wd/hub/session/67b7b41cf15632508b04b6bfc48f62cd/elements] with body: {"using":"name","value":"q"}
[WD Proxy] Got response with status 200: {"sessionId":"67b7b41cf15632508b04b6bfc48f62cd","status":0,"value":[{"ELEMENT":"0.5466260018440561-1"}]}
[WD Proxy] Replacing sessionId 67b7b41cf15632508b04b6bfc48f62cd with 2464c639-5ba7-49f5-842a-dadd77f4e596
[HTTP] [37m<-- POST /wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/elements [39m[32m200[39m [90m507 ms - 108[39m
[HTTP] [90m[39m
[HTTP] [37m-->[39m [37mPOST[39m [37m/wd/hub/session/2464c639-5ba7-49f5-842a-dadd77f4e596/context[39m