Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Selenium-在每行代码之后等待_Python_Selenium_Webdriver - Fatal编程技术网

Python Selenium-在每行代码之后等待

Python Selenium-在每行代码之后等待,python,selenium,webdriver,Python,Selenium,Webdriver,我正在使用Selenium(python)测试一个web应用程序。但是,有时一行代码会触发错误,因为第一行没有足够的时间运行。例如: ... driver.find_element_by_id("form_widget_date").click() driver.find_element_by_link_text(str(self.day)).click() ... 因此,第二行(有时)找不到链接文本,因为Selenium显然没有时间完成第一行。当我在两行之间放置睡眠时,错误不会发生 我的问题

我正在使用Selenium(python)测试一个web应用程序。但是,有时一行代码会触发错误,因为第一行没有足够的时间运行。例如:

...
driver.find_element_by_id("form_widget_date").click()
driver.find_element_by_link_text(str(self.day)).click()
...
因此,第二行(有时)找不到链接文本,因为Selenium显然没有时间完成第一行。当我在两行之间放置睡眠时,错误不会发生

我的问题是:是否有一种方法可以自动为每行代码等待更长的时间,而不是像这样解决它:

...
time.sleep(2)
driver.find_element_by_id("form_widget_date").click()
time.sleep(2)
driver.find_element_by_link_text(str(self.day)).click()
time.sleep(2) 
...

事实是,您的代码通常会以大量等待结束。你确实想避免使用睡眠思维。看看显式等待的用法。这允许设置一个等待时间段,否则执行将超时,但是,当找到元素时,无论等待时间段中还有多少时间,它都会自动继续执行

从文档中:


有两种等待
显式等待
隐式等待

Dan提供的解决方案是一个显式等待的示例,我认为您正在寻找的是隐式等待

隐式等待是告诉WebDriver轮询DOM一段时间 尝试查找一个或多个元素(如果有)的时间量 目前还没有。默认设置为0。一旦设置,则 为WebDriver对象实例的生命周期设置隐式等待

您可以在开始时定义一次隐式等待时间,如下所示:

driver = webdriver.Firefox()
driver.implicitly_wait(10) # seconds

参考资料:

对于您想做的事情,基本上有三种选择

  • 使用
    time.sleep(…)

    这是现实世界中最糟糕的开发选项。这很糟糕,因为你保证每次都要等待指定的时间。如果您发现有时需要5秒钟才能通过测试,那么如果您等待的条件在1秒内准备就绪,您仍然需要等待5秒钟。在一个实质性的测试套件中,这些等待将加起来,并使运行套件所需的总时间增加几分钟

  • 使用Selenium的隐式等待

    优点是您可以设置隐式等待,然后忘记它。您不必指定wait、after wait、after wait。但问题是隐式等待不能与显式等待混合。关于它们为什么不混合的细节,在本文中有很好的解释。根据我的经验,使用隐式等待只在非常简单的情况下有效。

  • 使用Selenium的显式等待

    如果您的应用程序是动态类型的,如果您有Ajax,如果您动态修改DOM,您迟早要使用显式等待,此时您将不再依赖隐式等待。缺点是您的代码将更加冗长。您可以使用包装器函数来缓解它。假设
    driver
    被设置为
    WebDriver
    对象,下面是一个如何执行此操作的示例:

    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    
    
    class MyDriver(object):
        def __init__(self, driver, default_timeout=2):
            self.driver = driver
            self.timeout = default_timeout
    
        def find_element(self, locator):
            return WebDriverWait(self.driver, self.timeout).until(
                EC.presence_of_element_located(locator))
    
    mydriver = MyDriver(driver)
    foo = mydriver.find_element((By.CSS_SELECTOR, ".foo"))
    

  • 我认为情况也是如此。我仍然需要在我想设置“wait”的每一行代码中使用它。而且,不管怎样,有时我不会打开一个新的url,我只是打开一个对话框或其他什么(例如,我上面的例子),因为我注意到您的代码中会有很多等待。您可以创建一个包装器类,将一个元素传递给它,使其变得更整洁。想一想你想如何模拟你的行为。有些步骤需要等待,而其他步骤则不需要等待。我意识到有时第二行执行,有时不执行,我担心的是,我的代码会大两倍,因为我必须努力保持一致性:/Welcome to the精彩的UI自动化世界。在我的许多页面类中,我有一个简单的方法来执行操作,但它看起来像这样(java):公共字符串CheckListingsPage(){u wait.until(ExpectedConditions.visibilityOf(listingResults));return bodyTag.getAttribute(“id”);}不同的浏览器执行命令的方式不同,因此这可以防止它在一个浏览器中工作和在另一个浏览器中中断,而不会因为睡眠而减慢整个测试的速度。
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    
    
    class MyDriver(object):
        def __init__(self, driver, default_timeout=2):
            self.driver = driver
            self.timeout = default_timeout
    
        def find_element(self, locator):
            return WebDriverWait(self.driver, self.timeout).until(
                EC.presence_of_element_located(locator))
    
    mydriver = MyDriver(driver)
    foo = mydriver.find_element((By.CSS_SELECTOR, ".foo"))