使用Appium和Python测试iOS应用时如何等待元素加载?

12 投票
5 回答
14456 浏览
提问于 2025-04-18 09:38

我正在测试一个原生的iOS应用,但在某些测试中需要等一些元素加载出来。现在Appium在某些界面上运行得太快了。

有没有人能给我一个关于如何在Appium iOS测试中使用类似WebDriverWait的等待方式的例子?这里有一个关于Ruby的回答:在使用Appium和Ruby测试iOS应用时等待元素加载?。我想找一个类似的Python例子。

不过,Python客户端的文档似乎没有详细说明等待函数。

谢谢。

5 个回答

0

你可以使用隐式等待。就像这样 remoteWebDriver.implicitlyWait(time, timeUnit) 这段代码是用Java写的。Python里也应该有类似的功能。

1

你可以在 selenium.webdriver.support.expected_conditions 中找到你需要的所有内容。

然后你可以这样做:

def wait_for_element_visible(self, by=By.XPATH, value=None, text=None, wait_time=20):
    if text is not None:
        value = value % text
    wait = WebDriverWait(self.driver, wait_time)
    return wait.until(EC.visibility_of_element_located((by, value)))
1

你可以使用 WaitForElement 类:

class WaitForElement:
    @staticmethod
    def wait(driver, id, time_out=100):
        try:
            WebDriverWait(driver, time_out).until(
                lambda driver: driver.find_element(*id))
        except TimeoutException:
            print('Not able to find ID:' + id)
2

这里是Python的用法:

driver.implicitly_wait(timeToWaitSec)

Selenium的源代码(Python版)

15

在测试的开头导入这些内容。

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

简单来说,这个应该可以工作,不过在等待的部分,你可能需要把 self.driver 改成 driver,这要看你是怎么做的。另外,当然要把 By.XPath 改成你正在使用的定位方式:

wait = WebDriverWait(self.driver, 20)
currently_waiting_for = wait.until(EC.element_to_be_clickable((By.XPATH,'//UIAApplication[1]/UIAWindow[1]/UIAButton[@text="example text"]')))

或者你可以直接告诉驱动程序使用隐式等待。

self.driver.implicitly_wait(10)
myElement = driver.find_element_by_id("fakeid")
myElement.click()

大部分内容在 这里 有详细解释。

下面是一个使用等待来登录安卓应用的例子(我还没在 iOS 上用过,但应该差不多),使用默认的账户选择器,然后确认正确的文本出现。在设置过程中,我是从另一个文件加载我想要的配置。

class TrainUpSmokeTests(unittest.TestCase): 
    def setUp(self):
         desired_caps = desired_capabilities.get_desired_capabilities('app-debug.apk')
         self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)

    def tearDown(self):
        self.driver.quit()

    def example_test(self):
        wd = self.driver

        ## Depending on how you're running the test the first variable may just be driver. Or in my case self.driver which I shortened above. The number is how many seconds it should wait before timing out. 
        wait = WebDriverWait(wd, 20)
        ## Waiting for account selector to be clickable.
        currently_waiting_for = wait.until(EC.element_to_be_clickable((By.XPATH,'//android.widget.CheckedTextView[@text="FakeEmail@example.com"]')))

        ## Locating test account and selecting it.
        account = wd.find_element_by_android_uiautomator('text("FakeEmail@example.com")')
        account.click()
        ok_button = wd.find_element_by_android_uiautomator('text("OK")')
        ok_button.click()

        ## Waiting for an Element on the home screen to be locatable.
        currently_waiting_for = wait.until(EC.presence_of_element_located((By.XPATH,'//android.widget.RelativeLayout[@resource-id="com.name.app:id/overview"]')))
        hero_headline = wd.find_element_by_android_uiautomator('new UiSelector().description("Example Header")')
        self.assertIsNotNone(hero_headline)

if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(TrainUpSmokeTests)
unittest.TextTestRunner(verbosity=2).run(suite)

这是在用 Appium 测试一个网站(而不是一个应用)。把设置改成让 self.driver 打开一个浏览器。

 self.driver = webdriver.Firefox()

然后使用像类名、名称、ID 这样的 By 选择器,比如下面的例子。

currently_waiting_for = wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'search-results')))

这篇 文章 也很有帮助。如果你不知道怎么找到 xpath,可以看看 Appium 自带的 uiautomatorviewer 的设置。

撰写回答