我是 Appium 的新手,一直在自学。我使用 telegram 和实际的 Android 设备作为学习基础。然而,我遇到了以下顺序的障碍:
在电话号码输入屏幕上,我可以单击国家/地区字段,这会将我带到另一个包含国家/地区列表的屏幕
在此屏幕上,我可以向下滚动找到我想要的国家/地区 选择
我可以点击国家/地区并返回电话号码 输入画面
但是在电话号码输入屏幕上,国家/地区字段仍然存在 未填充,appium 返回并显示 StaleElementReferenceException 错误。
我用谷歌搜索发现 Python Selenium 上的 StaleElementReferenceException ,所以我实现了它但得到了 timeoutException 错误,我增加 webdriverwait超时(从10到20)但它没有解决它。我 尝试了 Appium Inspector、uiautomator 和 xpath 但两者都不起作用。
所以我怀疑有什么东西阻止了电话号码输入屏幕刷新所选国家/地区?或者不知何故 Appium 仍然在旧的电话号码输入屏幕实例上?然后我尝试选择一个不需要滚动的国家/地区(阿尔巴尼亚),因为它位于列表顶部,并且我可以看到它填充在国家/地区字段中。所以不知何故滚动正在影响它,但我不知道为什么以及如何修复它。在我的情况下,一些进一步的谷歌搜索提到“屏幕在等待元素变得可见时正在刷新”,即使在显式等待之后,屏幕也不会刷新所选值。有什么想法吗?
滚动选择一个国家/地区后,该值应反映在国家/地区字段中,我可以断言它是正确的值。
def test_select_country(self):
#navigate to phone num input screen
startMessenging_btn = wait_for_element(self.driver, AppiumBy.ANDROID_UIAUTOMATOR, 'new UiSelector().text("Start Messaging")')
assert startMessenging_btn is not None
startMessenging_btn.click()
#tap and navigate to country selection screen
phone_num_screen_country_element = wait_for_element(self.driver, AppiumBy.ACCESSIBILITY_ID, 'Country')
assert phone_num_screen_country_element is not None
phone_num_screen_country_element.click()
#scroll down to selected country
scroll_to_country = self.driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,
'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("🇧🇪 Belgium").instance(0))'
)
assert scroll_to_country.is_displayed()
# somehow this only works when selecting a country without scrolling, it doesnt work after scrolling is completed,
# I can see the click on device but the next screen doesnt reflect the selected country
select_country = self.driver.find_element(AppiumBy.ANDROID_UIAUTOMATOR,'new UiSelector().text("🇧🇪 Belgium")')
assert select_country.text == "🇧🇪 Belgium"
select_country.click()
# this is where staleelementreferenceexception was found, does appium reloads this screen when it comes back to it?
phone_num_screen_country_populated = wait_for_element(self.driver, AppiumBy.XPATH, '//android.widget.TextView[@text="🇧🇪 Belgium"]')
assert phone_num_screen_country_populated.text == "🇧🇪 Belgium"
def wait_for_element(driver: 'WebDriver', locator: str, value: str, timeout_sec: float = 10) -> 'WebElement':
"""Wait until the element located
Args:
driver: WebDriver instance
locator: Locator like WebDriver, Mobile JSON Wire Protocol
(e.g. `appium.webdriver.common.appiumby.AppiumBy.ACCESSIBILITY_ID`)
value: Query value to locator
timeout_sec: Maximum time to wait the element. If time is over, `TimeoutException` is thrown
Raises:
`selenium.common.exceptions.TimeoutException`
Returns:
The found WebElement
"""
ignored_exceptions=(NoSuchElementException,StaleElementReferenceException,)
return WebDriverWait(driver, timeout_sec, ignored_exceptions=ignored_exceptions).\
until(EC.presence_of_element_located((locator, value)))
所以经过多次尝试和错误,我想我偶然发现了一个迄今为止有效的解决方案:在每个页面的命令末尾,我添加了 time.sleep(),我尝试了 1 或 2 秒,但它没有'不起作用,所以我只是将其增加到 10 并且它起作用了!微调一下,减少到5秒