autorenew

Webdriver | Webdriver

用于浏览器自动化的开源框架,支持跨各种浏览器和操作系统对网页进行自动化测试。

相关术语

另请参阅:

关于 WebDriver 有疑问吗?

基础知识和重要性

Selenium 中的 WebDriver 是什么?

selenium 中的WebDriver 是一个API,它提供了一个编程接口来控制和操作Web 浏览器。它允许测试脚本 直接与浏览器通信,从而实现用户操作的自动化,例如单击、键入和浏览网页。与selenium RC相比,WebDriver旨在提供更简单、更简洁的编程接口,因为它直接与浏览器交互,而不需要中间服务器。 要使用WebDriver,您需要为要自动化的浏览器实例化特定的驱动程序对象。例如,要自动化 Chrome,您可以使用 ChromeDriver

  WebDriver driver = new ChromeDriver();

WebDriver 提供了模拟浏览器操作的方法,例如 get() 用于导航到 URL、click() 用于单击元素以及 sendKeys() 用于输入文本。它还提供了处理复杂用户交互、管理浏览器窗口和执行 JavaScript 的方法。 WebDriver 支持多种编程语言,包括 Java、C#、Python 和 Ruby,允许集成到各种测试框架中。它是 selenium 2.0 和 3.0 套件的一部分,随着 selenium 4 的发布,WebDriver 通过附加特性和功能得到了进一步增强。 为了确保稳健可靠的自动化,WebDriver 提供了各种策略来定位元素(例如,通过 ID、名称、CSS、XPath),并且它提供了处理异步行为的机制,例如用于将测试与 Web 应用程序的动态特性同步的不同等待命令。

为什么 WebDriver 在自动化测试中很重要?

WebDriver 在自动化测试中至关重要,因为它充当标准化接口来控制 Web 浏览器并模拟用户交互。它允许以独立于任何特定浏览器的方式编写测试,从而启用**跨浏览器测试策略**。 WebDriver 的重要性在于它能够在低级别与网络元素进行交互,这非常模仿真实的用户操作。 通过为浏览器自动化提供通用平台WebDriver 促进了可靠可重复可维护 测试脚本 的开发。它支持多种编程语言,允许团队利用现有的编码技能并与各种测试框架集成。 WebDriver 与浏览器API直接通信 确保测试快速高效地执行,而无需像selenium RC 等旧工具那样产生中间服务器的开销。这种直接交互还意味着WebDriver可以更有效地处理复杂的基于AJAX的UI元素和动态内容,从而获得更准确的测试结果。 此外,WebDriver 支持高级用户交互,例如拖放和复杂的鼠标移动,允许复杂的用户场景的自动化。它管理浏览器会话、cookie 和对话框的能力进一步扩展了其在创建涵盖广泛用户行为的全面测试套件 方面的实用性。 总之,WebDriver 是现代测试自动化 策略的基石,提供了强大而灵活的工具集,用于确保跨不同浏览器和平台的 Web 应用程序质量。

WebDriver 的主要功能是什么?

WebDriver 的主要功能包括:

  • 跨浏览器兼容性:支持各种浏览器,如 Chrome、Firefox、Internet Explorer、Safari 和 Edge。
  • 语言支持:适用于多种编程语言,例如 Java、C#、Python、Ruby 和 JavaScript。
  • 操作系统支持:与 Windows、macOS 和 Linux 兼容。
  • 移动测试:可以通过 Appium 或 Selendroid 自动化移动浏览器。
  • 无头浏览器测试:支持 Chrome 和 Firefox 的无头版本,以加快执行速度。
  • 事件触发:允许监听事件,例如单击之前、单击之后、导航之前和导航之后。
  • 窗口和选项卡管理:提供在窗口和选项卡之间切换的方法。
  • 框架处理:提供在 iframe 之间切换上下文的简单方法。
  • 高级用户交互:促进复杂的用户手势,例如拖放、鼠标移动和键盘操作。
  • 屏幕截图功能:可以捕获当前页面或特定元素的屏幕截图。
  • Cookie 管理:允许读取、添加和删除浏览器 cookie。
  • JavaScript 执行 :在当前页面或框架的上下文中执行任意 JavaScript 代码。
  • 代理支持:配置 WebDriver 以使用浏览器会话代理。
  • 可扩展性:可以使用各种插件和库进行扩展以增强功能。
  • 速度和性能:通常比其前身 Selenium RC 更快、更高效。 这些功能使 WebDriver 能够为自动化 Web 浏览器提供强大且多功能的平台,从而允许创建模拟真实用户交互的全面测试脚本

WebDriver 如何与浏览器交互?

WebDriver 通过一系列步骤与浏览器交互,这些步骤涉及WebDriver 客户端和浏览器对自动化的本机支持之间的通信。以下是该过程的简要说明:

  1. 初始化:当创建WebDriver实例时,它会与浏览器驱动程序建立连接(例如,ChromeDriver用于Chrome,GeckoDriver用于Firefox)。
  2. 命令执行测试脚本WebDriver 发送命令,然后客户端库将命令格式化为 RESTful HTTP 请求。
  3. HTTP 请求:格式化的命令通过 HTTP 发送到浏览器驱动程序。
  4. 浏览器驱动程序:浏览器驱动程序接收HTTP请求并将其翻译成浏览器可以理解的一系列动作。
  5. 操作:浏览器执行请求的操作,例如导航到 URL、单击元素或输入文本。
  6. 响应:执行操作后,浏览器驱动程序将 HTTP 响应发送回 WebDriver 客户端。此响应包含命令执行的结果,例如成功状态、元素属性或任何错误。
  7. 结果处理WebDriver 客户端处理响应并将结果返回给测试脚本,然后测试脚本 可以继续执行进一步的操作或断言。 在整个交互过程中,WebDriver 使用**WebDriver 协议**,这是一种自动化 Web 浏览器交互的标准。该协议确保命令和响应在不同的浏览器和驱动程序中保持一致,从而允许使用相同的脚本跨浏览器测试

Selenium RC 和 WebDriver 有什么区别?

selenium RC(远程控制)和WebDriver 都是用于浏览器自动化的selenium 套件的一部分,但它们的架构和与Web 应用程序的交互有很大不同。 selenium RC 是一项较旧的技术,需要额外的服务器才能与浏览器交互。运行测试时,它将 JavaScript 代码注入浏览器,然后控制被测试的应用程序。这种方法具有固有的局限性,例如由于额外的层(服务器)而速度较慢,并且对浏览器的直接控制较少,从而导致现代 JavaScript 密集型应用程序出现问题。 另一方面,WebDriver 是一种更现代、更先进的工具。它使用浏览器对自动化的本机支持直接与浏览器通信,无需中间服务器。 WebDriver 提供了与 Web 元素更真实的交互,因为它不依赖 JavaScript 来实现自动化。这种直接控制可以更好地模拟用户操作,并且可以更有效地处理复杂的基于 AJAX 的 Web 元素。 主要区别是:

  • 直接浏览器控制:WebDriver 直接与浏览器交互,而 Selenium RC 通过服务器进行交互。
  • 速度:WebDriver 由于与浏览器直接通信,通常速度更快。
  • API设计 :WebDriver的API更加简洁和面向对象,使其更易于使用和维护。
  • 浏览器支持:WebDriver 对现代浏览器及其功能有更好的支持。
  • JavaScript 依赖性 :Selenium RC 依赖 JavaScript 实现自动化,这可能是一个限制,而 WebDriver 没有这种依赖性。
  • 直接浏览器控制:WebDriver 直接与浏览器交互,而 Selenium RC 通过服务器进行交互。
  • 速度:WebDriver 由于与浏览器直接通信,通常速度更快。
  • API设计 :WebDriver的API更加简洁和面向对象,使其更易于使用和维护。
  • 浏览器支持:WebDriver 对现代浏览器及其功能有更好的支持。
  • JavaScript 依赖性 :Selenium RC 依赖 JavaScript 实现自动化,这可能是一个限制,而 WebDriver 没有这种依赖性。

WebDriver 操作

如何使用 WebDriver 启动浏览器?

要使用 WebDriver 启动浏览器,您需要实例化要自动化的浏览器的特定驱动程序对象。这是分步指南:

  1. 导入测试脚本中必要的 WebDriver 类。

  2. 实例化所需浏览器的驱动程序(例如 ChromeDriver、FirefoxDriver)。

  3. 使用驱动对象 打开浏览器窗口 。 以下是 Chrome 和 Firefox 浏览器的 Java 示例:

  // For Chrome
  import org.openqa.selenium.WebDriver;
  import org.openqa.selenium.chrome.ChromeDriver;
  System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
  WebDriver driver = new ChromeDriver();
  driver.get("http://www.example.com");
  // For Firefox
  import org.openqa.selenium.WebDriver;
  import org.openqa.selenium.firefox.FirefoxDriver;
  System.setProperty("webdriver.gecko.driver", "path/to/geckodriver");
  WebDriver driver = new FirefoxDriver();
  driver.get("http://www.example.com");

确保将 "path/to/chromedriver""path/to/geckodriver" 替换为 ChromeDriver 和 GeckoDriver 可执行文件的实际路径。 注意:运行脚本之前,请确保驱动程序可执行文件已下载并在指定路径中可用。 get() 方法用于在启动浏览器后导航到所需的 URL。 执行脚本后,WebDriver 将启动指定的浏览器并加载给定的 URL。请记住在测试操作完成后使用 driver.quit() 关闭浏览器,以确保没有浏览器实例仍在运行。

  1. 导入测试脚本中必要的 WebDriver 类。

  2. 实例化所需浏览器的驱动程序(例如 ChromeDriver、FirefoxDriver)。

  3. 使用驱动对象 打开浏览器窗口

如何使用 WebDriver 导航到 URL?

要使用 WebDriver 导航到 URL,您通常会使用 WebDriver 实例提供的 get 方法。此方法采用一个参数:您要导航到的 URL。这是 Java 中的一个示例:

  driver.get("http://www.example.com");

在 Python 中,语法类似:

  driver.get("http://www.example.com")

对于 C#,您可以使用:

  driver.Navigate().GoToUrl("http://www.example.com");

在每种情况下,get 方法(或 C# 中的GoToUrl)指示浏览器导航到指定的 URL。该方法将等到页面完全加载后才允许执行任何进一步的命令。这是一个阻塞调用,意味着在页面加载完成之前不会执行下一行代码。 在尝试导航到 URL 之前,请务必确保 WebDriver 实例已初始化并且浏览器会话处于活动状态。这通常是通过首先调用适当的方法来启动浏览器来完成的,例如 Chrome 的 new ChromeDriver() 或 Firefox 的 new FirefoxDriver()。 下面是在完整上下文中导航到 URL 的简洁示例:

  WebDriver driver = new ChromeDriver();
  driver.get("http://www.example.com");
  // Perform actions on the page
  driver.quit(); // Close the browser and end the session

请记住在自动化任务完成后始终使用 driver.quit()driver.close() 关闭浏览器会话以释放系统资源。

如何使用 WebDriver 执行表单输入?

要使用 WebDriver 执行表单输入,您通常需要与文本框、单选按钮、复选框和按钮等 Web 元素进行交互。以下是实现这一目标的方法: 对于 文本字段,使用 sendKeys() 方法来模拟在字段中输入:

  WebElement inputField = driver.findElement(By.id("text-input"));
  inputField.sendKeys("Your text here");

要在发送密钥之前清除文本字段,请使用 clear() 方法:

  inputField.clear();
  inputField.sendKeys("New text");

对于 复选框单选按钮,请使用 click() 方法来切换其状态:

  WebElement checkbox = driver.findElement(By.id("checkbox"));
  checkbox.click(); // This will check or uncheck the checkbox
  WebElement radioButton = driver.findElement(By.id("radio-button"));
  radioButton.click(); // This will select the radio button

从下拉列表中选择一个选项,首先创建一个 Select 对象,然后使用 selectByVisibleText()selectByIndex()selectByValue() 方法:

  Select dropdown = new Select(driver.findElement(By.id("dropdown")));
  dropdown.selectByVisibleText("Option 1");
  // or
  dropdown.selectByIndex(1);
  // or
  dropdown.selectByValue("value1");

对于 按钮,只需使用 click() 方法来提交表单或触发事件:

  WebElement submitButton = driver.findElement(By.id("submit-button"));
  submitButton.click();

请记住始终准确定位元素,并在必要时等待元素可交互,以避免同步问题。使用显式等待可以更好地控制交互的时间。

如何使用 WebDriver 处理警报和弹出窗口?

可以使用Alert 接口来处理WebDriver 中的警报和弹出窗口,该接口提供了与不同类型的警报进行交互的方法。这是一个简洁的指南: 接受警报:

  Alert alert = driver.switchTo().alert();
  alert.accept();

解除警报:

  Alert alert = driver.switchTo().alert();
  alert.dismiss();

获取警报文本:

  Alert alert = driver.switchTo().alert();
  String alertText = alert.getText();

发送文本到提示:

  Alert alert = driver.switchTo().alert();
  alert.sendKeys("Text to enter");

处理意外警报: 对于随机出现的意外警报,您可以使用 UnexpectedAlertBehaviour 功能来定义 WebDriver 应如何反应:

  FirefoxOptions options = new FirefoxOptions();
  options.setCapability(CapabilityType.UNEXPECTED_ALERT_BEHAVIOUR, UnexpectedAlertBehaviour.IGNORE);
  WebDriver driver = new FirefoxDriver(options);

注意: 处理警报时,请确保WebDriver 在执行任何操作之前已切换到警报。另请记住,WebDriver 只能与 JavaScript 警报、提示和确认交互(window.alertwindow.confirmwindow.prompt)。本机操作系统弹出窗口无法直接由 WebDriver 处理。

如何使用 WebDriver 执行拖放操作?

要使用WebDriver 执行拖放操作,您可以利用Actions 类,该类提供了用户友好的API,用于实现与Web 元素的高级用户交互。这是 Java 中的一个简洁示例:

  import org.openqa.selenium.By;
  import org.openqa.selenium.WebDriver;
  import org.openqa.selenium.WebElement;
  import org.openqa.selenium.interactions.Actions;
  public void dragAndDropExample(WebDriver driver) {
      // Locate the elements for drag and drop
      WebElement sourceElement = driver.findElement(By.id("source-element-id"));
      WebElement targetElement = driver.findElement(By.id("target-element-id"));
      // Create an instance of Actions class
      Actions actions = new Actions(driver);
      // Perform the drag and drop action
      actions.dragAndDrop(sourceElement, targetElement).perform();
  }

或者,如果您需要通过指定偏移量而不是目标元素来执行拖放操作,则可以使用 clickAndHold()moveByOffset()release() 方法:

  actions.clickAndHold(sourceElement)
         .moveByOffset(xOffset, yOffset)
         .release()
         .perform();

xOffsetyOffset 分别替换为您想要将元素从当前位置移动的水平和垂直距离。 注意:在执行拖放操作之前,请确保 WebDriver 实例已正确初始化并且元素可交互(可见并启用)。此外,请考虑任何同步问题,例如在执行这些操作之前等待元素准备好进行交互。

定位器和 Web 元素

WebDriver 中的定位器是什么?

WebDriver 中的定位器是用于识别和定位网页上的元素的策略。这些对于在 测试自动化 期间与 Web 元素进行交互至关重要,例如单击按钮、输入文本或读取值。 WebDriver 支持各种定位器策略:

  • ID :通过其唯一 ID 查找元素。
    driver.findElement(By.id("element-id"));
  • 名称:通过以下方式定位元素 name 属性。
    driver.findElement(By.name("element-name"));
  • 类名称:对于具有特定类属性的元素。
    driver.findElement(By.className("class-name"));
  • 标签名称:通过标签名称识别元素。
    driver.findElement(By.tagName("tag-name"));
  • 链接文本:用于通过确切的文本定位链接。
    driver.findElement(By.linkText("link text"));
  • 部分链接文本:与链接文本类似,但匹配部分链接文本。
    driver.findElement(By.partialLinkText("part-of-link-text"));
  • CSS 选择器:允许使用 CSS 选择器进行复杂查询。
    driver.findElement(By.cssSelector("css-selector"));
  • XPath :使用 XML 路径表达式的强大定位器。
    driver.findElement(By.xpath("//tag[@attribute='value']"));

选择正确的定位器取决于具体场景和元素的属性。 IDName 通常因其简单性和性能而受到青睐,但 CSS SelectorXPath 为复杂或动态元素提供了更大的灵活性。使用可靠且不太可能更改的定位器对于确保稳定的自动化脚本至关重要。

  • ID :通过其唯一 ID 查找元素。
    driver.findElement(By.id("element-id"));
  • 名称:通过以下方式定位元素 name 属性。
    driver.findElement(By.name("element-name"));
  • 类名称:对于具有特定类属性的元素。
    driver.findElement(By.className("class-name"));
  • 标签名称:通过标签名称识别元素。
    driver.findElement(By.tagName("tag-name"));
  • 链接文本:用于通过确切的文本定位链接。
    driver.findElement(By.linkText("link text"));
  • 部分链接文本:与链接文本类似,但匹配部分链接文本。
    driver.findElement(By.partialLinkText("part-of-link-text"));
  • CSS 选择器:允许使用 CSS 选择器进行复杂查询。
    driver.findElement(By.cssSelector("css-selector"));
  • XPath :使用 XML 路径表达式的强大定位器。
    driver.findElement(By.xpath("//tag[@attribute='value']"));

如何使用 WebDriver 定位元素?

要使用 WebDriver 定位元素,您可以利用各种定位器策略。每个策略都针对网页上 HTML 元素的不同属性或方面。以下是常用的方法:

  • By.id :通过元素的唯一 ID 查找元素。
  driver.findElement(By.id("elementId"));
  • By.name :通过 NAME 属性定位元素。
  driver.findElement(By.name("elementName"));
  • By.className :通过元素的类属性来定位元素。
  driver.findElement(By.className("elementClass"));
  • By.tagName :按标签名称查找元素。
  driver.findElement(By.tagName("elementTag"));
  • By.cssSelector :使用 CSS 选择器来定位元素,允许复杂的查询。
  driver.findElement(By.cssSelector("cssSelector"));
  • By.xpath :使用 XPath 表达式在 DOM 中的元素和属性中导航。
  driver.findElement(By.xpath("xpathExpression"));
  • By.linkText :通过链接元素显示的确切文本查找链接元素。
  driver.findElement(By.linkText("linkText"));
  • By.partialLinkText :定位包含指定文本的链接元素。
  driver.findElement(By.partialLinkText("partialLinkText"));

请记住在找不到元素时处理潜在的异常,例如NoSuchElementException。此外,请考虑定位器策略的性能和可维护性,因为与 ID 或 CSS 选择器等其他方法相比,XPath 等某些方法可能更慢且更脆弱。

  • By.id :通过元素的唯一 ID 查找元素。
  • By.name :通过 NAME 属性定位元素。
  • By.className :通过元素的类属性来定位元素。
  • By.tagName :按标签名称查找元素。
  • By.cssSelector :使用 CSS 选择器来定位元素,允许复杂的查询。
  • By.xpath :使用 XPath 表达式在 DOM 中的元素和属性中导航。
  • By.linkText :通过链接元素显示的确切文本查找链接元素。
  • By.partialLinkText :定位包含指定文本的链接元素。

findElement() 和 findElements() 方法有什么区别?

selenium WebDriver 中,findElement()findElements() 都是用于定位网页上的元素的方法,但它们的返回类型和行为有所不同:

  • findElement() :当您希望定位器与某个位置匹配时,使用此方法 单一元素在页面上。它返回 第一个 Web 元素与给定的定位器匹配。如果没有找到元素,它会抛出一个 NoSuchElementException
  WebElement element = driver.findElement(By.id("uniqueElementId"));
  • findElements() :当您希望定位器匹配时使用此方法 多个元素在页面上。它返回一个 Web 元素列表与给定的定位器匹配。如果没有找到元素,则返回一个 空列表而不是抛出异常。
  List<WebElement> elements = driver.findElements(By.className("multipleElementsClass"));

主要区别

  • 返回类型findElement() 返回单个 WebElement ; findElements() 返回一个 List<WebElement>

  • 异常处理findElement() 如果没有找到元素则抛出异常; findElements() 返回一个空列表。

  • 用例 :使用 findElement() 当您需要与单个元素交互时;使用 findElements() 当您需要与共享同一定位器的多个元素进行交互时。 根据您希望使用一个还是多个元素以及您希望如何处理未找到元素的情况来选择方法。

  • findElement() :当您希望定位器与某个位置匹配时,使用此方法 单一元素在页面上。它返回 第一个 Web 元素与给定的定位器匹配。如果没有找到元素,它会抛出一个 NoSuchElementException

  • findElements() :当您希望定位器匹配时使用此方法 多个元素在页面上。它返回一个 Web 元素列表与给定的定位器匹配。如果没有找到元素,则返回一个 空列表而不是抛出异常。

  • 返回类型findElement() 返回单个 WebElement ; findElements() 返回一个 List<WebElement>

  • 异常处理findElement() 如果没有找到元素则抛出异常; findElements() 返回一个空列表。

  • 用例 :使用 findElement() 当您需要与单个元素交互时;使用 findElements() 当您需要与共享同一定位器的多个元素进行交互时。

如何使用 WebDriver 处理动态元素?

由于属性不断变化,处理 WebDriver 中的动态元素可能具有挑战性。为了有效地与这些元素交互,您可以使用多种策略: 1. XPath 包含、开头为或结尾为: 动态元素通常具有包含一致子字符串的属性。 contains()starts-with()ends-with() 等 XPath 函数可以根据部分属性值匹配元素。

  WebElement element = driver.findElement(By.xpath("//tag[contains(@attribute, 'value')]"));

2.具有子字符串匹配的 CSS 选择器: 与 XPath 类似,CSS 选择器可以使用 ^$* 基于属性值的子字符串来匹配元素。

  WebElement element = driver.findElement(By.cssSelector("tag[attribute*='value']"));

3.动态等待: 使用 显式等待 等待某些条件,例如元素的可见性或具有特定属性的元素的存在。

  WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
  WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("dynamicElement")));

4. JavaScript 执行: 当标准方法失败时,执行 JavaScript 可以直接与难以定位的元素进行交互。

  JavascriptExecutor js = (JavascriptExecutor) driver;
  WebElement element = (WebElement) js.executeScript("return document.querySelector('selector');");

5.重试元素位置: 在元素不能立即可用的情况下,可以实施重试机制,以便在测试失败之前多次尝试定位该元素。 6。定制预期条件: 创建自定义ExpectedConditions来处理内置条件未涵盖的更复杂的场景。 通过结合这些策略,您可以有效地处理WebDriver中的动态元素,确保您的自动化脚本稳健,并且不易因元素属性更改或计时问题而失败。

如何使用 WebDriver 与下拉菜单交互?

WebDriver 中的下拉列表交互通常使用 Select 类来完成,该类提供了选择和取消选择选项的方法。以下是使用下拉菜单的方法:

  1. 识别下拉元素使用任何 WebDriver 定位器,例如 By.id , By.name , By.xpath
  WebElement dropdownElement = driver.findElement(By.id("dropdownId"));
  1. 创建Select类的实例通过将下拉元素传递给其构造函数。
  Select dropdown = new Select(dropdownElement);
  1. 选择一个选项从下拉菜单中。您可以按索引、值或可见文本进行选择。
  • 按索引 (从零开始):
  dropdown.selectByIndex(1); // selects the second option
  • 按价值
  dropdown.selectByValue("optionValue"); // selects the option with value="optionValue"
  • 通过可见文本
  dropdown.selectByVisibleText("Option Text"); // selects the option with the displayed text
  1. 取消选择选项如果它是一个多选下拉菜单。取消选择选项也有类似的方法:
  dropdown.deselectByIndex(1);
  dropdown.deselectByValue("optionValue");
  dropdown.deselectByVisibleText("Option Text");
  1. 检索所选选项使用 getOptions() , getAllSelectedOptions() , 或 getFirstSelectedOption() 如果需要的话。
  List<WebElement> allOptions = dropdown.getOptions();
  List<WebElement> selectedOptions = dropdown.getAllSelectedOptions();
  WebElement firstSelectedOption = dropdown.getFirstSelectedOption();

如果下拉列表不存在或找不到指定的选项,请记住处理异常,例如NoSuchElementException

  1. 识别下拉元素使用任何 WebDriver 定位器,例如 By.id , By.name , By.xpath

  2. 创建Select类的实例通过将下拉元素传递给其构造函数。

  3. 选择一个选项从下拉菜单中。您可以按索引、值或可见文本进行选择。

  • 按索引 (从零开始):

  • 按价值

  • 通过可见文本

  1. 取消选择选项如果它是一个多选下拉菜单。取消选择选项也有类似的方法:

  2. 检索所选选项使用 getOptions() , getAllSelectedOptions() , 或 getFirstSelectedOption() 如果需要的话。

等待命令

WebDriver 中的等待命令有哪些不同类型?

WebDriver 提供了几个等待命令来处理 测试自动化 中的同步:

  • 隐式等待:如果未找到元素,则在抛出 NoSuchElementException 之前自动等待指定的时间。它是为 WebDriver 的整个会话设置的。
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
  • 显式等待:在继续执行之前等待特定条件发生。它比隐式等待更灵活,因为它允许您指定条件。
    WebDriverWait wait = new WebDriverWait(driver, 10);
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("elementId")));
  • 流畅等待:与显式等待类似,但有更多选项。您可以定义等待条件的最长时间以及检查条件的频率。您还可以在等待时忽略特定类型的异常。
    Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
        .withTimeout(Duration.ofSeconds(30))
        .pollingEvery(Duration.ofSeconds(5))
        .ignoring(NoSuchElementException.class);
    WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
       public WebElement apply(WebDriver driver) {
         return driver.findElement(By.id("foo"));
       }
     });
  • 睡眠:简单的暂停,将执行暂停指定的时间。通常不鼓励这样做,因为它可能导致不必要的等待,并且可能使测试运行的时间超过所需的时间。
    Thread.sleep(1000); // Sleep for 1 second

建议使用显式且流畅的等待而不是隐式等待,以获得更好的测试稳定性并避免不必要的延迟。除非绝对必要,否则应避免睡觉。

  • 隐式等待:如果未找到元素,则在抛出 NoSuchElementException 之前自动等待指定的时间。它是为 WebDriver 的整个会话设置的。
    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
  • 显式等待:在继续执行之前等待特定条件发生。它比隐式等待更灵活,因为它允许您指定条件。
    WebDriverWait wait = new WebDriverWait(driver, 10);
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("elementId")));
  • 流畅等待:与显式等待类似,但有更多选项。您可以定义等待条件的最长时间以及检查条件的频率。您还可以在等待时忽略特定类型的异常。
    Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
        .withTimeout(Duration.ofSeconds(30))
        .pollingEvery(Duration.ofSeconds(5))
        .ignoring(NoSuchElementException.class);
    WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
       public WebElement apply(WebDriver driver) {
         return driver.findElement(By.id("foo"));
       }
     });
  • 睡眠:简单的暂停,将执行暂停指定的时间。通常不鼓励这样做,因为它可能导致不必要的等待,并且可能使测试运行的时间超过所需的时间。
    Thread.sleep(1000); // Sleep for 1 second

隐式等待和显式等待有什么区别?

隐式等待和显式等待是将应用程序的状态与 测试脚本 的操作同步的两种不同策略。 隐式等待WebDriver 实例的整个生命周期中设置默认等待时间。当您设置隐式等待时,WebDriver 在尝试查找一个或多个元素(如果它们不立即可用)时会在一定时间内轮询 DOM。默认设置为 0。设置后,隐式等待在 WebDriver 会话期间有效。

  driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

另一方面,显式等待用于停止执行,直到满足特定条件。它是针对特定实例配置的,而不是像隐式等待那样的全面默认值。当在继续之前需要满足某些条件时使用显式等待,例如等待元素变得可见或可单击。它们通常与预期条件结合使用。

  WebDriverWait wait = new WebDriverWait(driver, 10);
  wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("elementId")));

主要区别是:

  • 范围:为整个会话设置隐式等待,而为特定条件设置显式等待。
  • 灵活性:显式等待允许更复杂的条件,而隐式等待仅等待元素出现。
  • 性能:通常建议使用显式等待,因为它允许更优化的等待策略,减少隐式等待可能引入的不必要的等待时间。 实际上,对于大多数复杂的同步问题,依赖显式等待是更可取的,因为它允许对等待条件进行更精细的控制,并且可以导致更可靠和更高效的测试。

如何在 WebDriver 中实现流畅的等待?

要在WebDriver中实现流畅的等待,您可以使用FluentWait类,它允许您配置等待条件的最长时间,以及检查条件的频率。此外,您可以在等待时忽略特定类型的异常,例如在页面上搜索元素时的NoSuchElementExceptions。 这是 Java 中的一个基本示例:

  WebDriver driver = new ChromeDriver();
  driver.get("http://example.com");
  // Initialize FluentWait with a timeout of 30 seconds and polling every 5 seconds.
  FluentWait<WebDriver> wait = new FluentWait<>(driver)
          .withTimeout(Duration.ofSeconds(30))
          .pollingEvery(Duration.ofSeconds(5))
          .ignoring(NoSuchElementException.class);
  // Use FluentWait to wait for a specific condition (element to be clickable).
  WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
      public WebElement apply(WebDriver driver) {
          return driver.findElement(By.id("foo"));
      }
  });
  // Now you can interact with the element
  foo.click();

使用 Java 8 lambda 表达式的更简洁方法:

  WebElement foo = new FluentWait<>(driver)
          .withTimeout(Duration.ofSeconds(30))
          .pollingEvery(Duration.ofSeconds(5))
          .ignoring(NoSuchElementException.class)
          .until(driver -> driver.findElement(By.id("foo")));
  foo.click();

请记住导入必要的类:

  import org.openqa.selenium.support.ui.FluentWait;
  import org.openqa.selenium.WebDriver;
  import org.openqa.selenium.WebElement;
  import org.openqa.selenium.By;
  import org.openqa.selenium.NoSuchElementException;
  import java.time.Duration;
  import java.util.function.Function;

当处理由于 AJAX 和 JavaScript 操作等各种因素可能需要一些时间才能出现或变得可交互的元素时,此方法特别有用。

如何使用 wait 命令处理同步问题?

要处理 测试自动化 中的同步问题,等待命令必不可少。它们允许您的测试在继续之前等待满足某些条件,以确保元素已准备好进行交互。 隐式等待WebDriver 实例的整个生命周期中设置默认等待时间。如果元素不是立即可用,WebDriver 将在抛出 NoSuchElementException 之前轮询 DOM 指定的持续时间。

  driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

显式等待更加细化,当需要满足特定条件才能继续操作时使用。它是使用WebDriverWaitExpectedConditions 来实现的。

  WebDriverWait wait = new WebDriverWait(driver, 10);
  wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("elementId")));

Fluent Wait 允许更复杂的轮询配置,指定等待条件的最长时间,以及检查条件的频率。您还可以在等待时忽略特定类型的异常。

  Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
      .withTimeout(Duration.ofSeconds(30))
      .pollingEvery(Duration.ofSeconds(5))
      .ignoring(NoSuchElementException.class);
  wait.until(new Function<WebDriver, WebElement>() {
      public WebElement apply(WebDriver driver) {
          return driver.findElement(By.id("elementId"));
      }
  });

有策略地使用这些等待命令来将测试与应用程序的状态同步,从而减少不稳定并提高可靠性。请记住避免使用 Thread.sleep() 方法,因为它会强制无条件等待,并可能导致不必要的长时间 测试执行 时间。

WebDriver 中的 sleep() 方法有什么用?

WebDriver 中的sleep() 方法是静态等待的一种形式,它将测试的执行暂停指定的时间。它是 Java 中 Thread 类的一部分,通常在 selenium WebDriver 脚本中用于处理计时问题和同步问题。 以下是如何在 WebDriver 脚本中使用 sleep() 的示例:

  Thread.sleep(5000); // Pauses execution for 5 seconds

此方法接受一个以毫秒为单位的参数,并在该持续时间内停止整个测试执行。使用 sleep() 通常被认为是一种糟糕的做法,因为它引入了硬编码等待,使测试不太可靠并增加了执行时间。 sleep() 的主要问题是它没有考虑应用程序是否准备好继续,从而导致不必要的等待或如果等待时间不足则可能导致不稳定。 建议使用**WebDriver 的等待机制**,例如隐式等待显式等待流畅等待,而不是sleep()。这些等待是动态的,一旦满足必要的条件(例如元素的存在或可见性),测试就可以继续进行,从而使测试更加高效和稳健。

高级 WebDriver 概念

如何使用 WebDriver 处理多个窗口或选项卡?

要处理WebDriver 中的多个窗口或选项卡,请使用getWindowHandles()switchTo().window() 方法。这是一个简洁的方法:

  1. 在打开新窗口或选项卡之前识别当前窗口句柄,以便您可以在需要时返回到它。
    String originalWindow = driver.getWindowHandle();
  1. 执行打开新窗口或选项卡的操作,例如单击在新窗口中打开的链接。
  2. 获取WebDriver实例当前打开的所有窗口句柄
    Set<String> allWindows = driver.getWindowHandles();
  1. 通过迭代 allWindows 集并使用 switchTo().window() 方法和新窗口句柄来切换到新窗口或选项卡
    for (String windowHandle : allWindows) {
        if (!originalWindow.contentEquals(windowHandle)) {
            driver.switchTo().window(windowHandle);
            break;
        }
    }
  1. 根据测试需要在新窗口或选项卡中与内容交互
  2. 如有必要,关闭新窗口或选项卡,然后切换回原始窗口。
    driver.close(); // Closes the new window or tab
    driver.switchTo().window(originalWindow); // Switch back to the original window

请记住处理任何潜在的异常,例如 NoSuchWindowException,并确保您的 测试脚本 考虑到窗口或选项卡可能无法按预期打开的可能性。

  1. 在打开新窗口或选项卡之前识别当前窗口句柄,以便您可以在需要时返回到它。
    String originalWindow = driver.getWindowHandle();
  1. 执行打开新窗口或选项卡的操作,例如单击在新窗口中打开的链接。
  2. 获取WebDriver实例当前打开的所有窗口句柄
    Set<String> allWindows = driver.getWindowHandles();
  1. 通过迭代 allWindows 集并使用 switchTo().window() 方法和新窗口句柄来切换到新窗口或选项卡
    for (String windowHandle : allWindows) {
        if (!originalWindow.contentEquals(windowHandle)) {
            driver.switchTo().window(windowHandle);
            break;
        }
    }
  1. 根据测试需要在新窗口或选项卡中与内容交互
  2. 如有必要,关闭新窗口或选项卡,然后切换回原始窗口。
    driver.close(); // Closes the new window or tab
    driver.switchTo().window(originalWindow); // Switch back to the original window

如何使用 WebDriver 执行鼠标和键盘操作?

要在WebDriver 中执行鼠标和键盘操作,您可以使用Actions 类,该类提供了用户友好的API 用于实现复杂的用户手势。使用方法如下: 鼠标操作:

  Actions actions = new Actions(driver);
  // Move to an element
  actions.moveToElement(element).perform();
  // Right-click (context click) on an element
  actions.contextClick(element).perform();
  // Double-click on an element
  actions.doubleClick(element).perform();
  // Click and hold, move to a new location, and release
  actions.clickAndHold(sourceElement)
         .moveToElement(targetElement)
         .release()
         .perform();
  // Drag and drop
  actions.dragAndDrop(sourceElement, targetElement).perform();

键盘操作:

  // Send keys to an element
  actions.sendKeys(element, "Text to send").perform();
  // Press a key (e.g., CONTROL) without releasing it
  actions.keyDown(Keys.CONTROL).perform();
  // Release a key (e.g., CONTROL)
  actions.keyUp(Keys.CONTROL).perform();
  // Perform a combination of keyboard actions
  actions.keyDown(Keys.CONTROL)
         .sendKeys("a")
         .keyUp(Keys.CONTROL)
         .perform();

链接动作: 您可以在调用 perform() 之前将多个操作链接在一起:

  actions.moveToElement(element)
         .click()
         .sendKeys("Text")
         .keyDown(Keys.SHIFT)
         .sendKeys("More text")
         .keyUp(Keys.SHIFT)
         .perform();

请记住导入必要的类:

  import org.openqa.selenium.interactions.Actions;
  import org.openqa.selenium.Keys;

这些操作模拟复杂的用户与 Web 应用程序的交互,从而允许更全面的测试场景。

如何使用 WebDriver 处理 iframe?

处理 WebDriver 中的 iframe 涉及将上下文从主页切换到 iframe,然后与其中的元素进行交互。在 iframe 中执行任何操作之前,请使用 switchTo() 方法将焦点更改到 iframe。 这是 Java 中的一个简洁示例:

  // Switch to iframe by index
  driver.switchTo().frame(0);
  // Switch to iframe by name or ID
  driver.switchTo().frame("iframeName");
  // Switch to iframe by WebElement
  WebElement iframeElement = driver.findElement(By.tagName("iframe"));
  driver.switchTo().frame(iframeElement);
  // Perform actions within the iframe
  driver.findElement(By.id("inside_iframe")).click();
  // Switch back to the main document when done with the iframe
  driver.switchTo().defaultContent();

要点:

  • 使用识别 iframe 指数 , 姓名 , 身份证号码 , 或 网络元素

  • 使用 driver.switchTo().frame() 切换到 iframe。

  • 与 iframe 交互后,返回主页 driver.switchTo().defaultContent() 。 请记住,如果一个 iframe 嵌套在另一个 iframe 中,则必须按顺序切换到每个 iframe,直到达到所需的级别。完成后始终切换回父框架或主要内容。

  • 使用识别 iframe 指数 , 姓名 , 身份证号码 , 或 网络元素

  • 使用 driver.switchTo().frame() 切换到 iframe。

  • 与 iframe 交互后,返回主页 driver.switchTo().defaultContent()

如何使用 WebDriver 截取屏幕截图?

使用WebDriver 截取屏幕截图非常简单。使用selenium WebDriver 提供的TakesScreenshot 接口。下面是 Java 中的一个简洁示例:

  WebDriver driver = new ChromeDriver(); // Assuming ChromeDriver is being used
  // ... your test code ...
  // Cast driver to TakesScreenshot
  TakesScreenshot screenshotTaker = (TakesScreenshot) driver;
  // Get the screenshot as an image file
  File screenshot = screenshotTaker.getScreenshotAs(OutputType.FILE);
  // Use FileUtils to save the file to a desired location
  FileUtils.copyFile(screenshot, new File("path/to/screenshot.png"));

对于其他编程语言,过程类似。关键是将WebDriver 实例强制转换为TakesScreenshot,然后使用适当的OutputType 调用getScreenshotAs 方法。 在 Python 中,它看起来像这样:

  from selenium import webdriver
  driver = webdriver.Chrome() # Assuming ChromeDriver is being used
  # ... your test code ...
  # Take screenshot and save it to the given path
  driver.save_screenshot('path/to/screenshot.png')

请记住处理任何异常,例如 Java 中的 IOException,这可能在将屏幕截图写入文件时发生。这可确保您的测试脚本 保持稳健且容错。

可以使用manage() 方法来处理WebDriver 中的cookie,该方法提供对Cookie 类的访问。以下是执行常见 cookie 操作的方法: 添加 Cookie:

  Cookie cookie = new Cookie("cookieName", "cookieValue");
  driver.manage().addCookie(cookie);

按名称获取 Cookie:

  Cookie cookie = driver.manage().getCookieNamed("cookieName");

检索所有 Cookie:

  Set<Cookie> allCookies = driver.manage().getCookies();

删除特定 Cookie:

  driver.manage().deleteCookieNamed("cookieName");

删除所有 Cookie:

  driver.manage().deleteAllCookies();

用法示例:

  // Adding a new cookie
  Cookie newCookie = new Cookie("testCookie", "testValue");
  driver.manage().addCookie(newCookie);
  // Retrieving a cookie's value
  String cookieValue = driver.manage().getCookieNamed("testCookie").getValue();
  // Deleting a cookie
  driver.manage().deleteCookieNamed("testCookie");
  // Verifying cookie deletion
  Set<Cookie> cookiesAfterDeletion = driver.manage().getCookies();
  assert cookiesAfterDeletion.isEmpty();

请记住从 selenium WebDriver导入 Cookie 类。另外,请确保您位于尝试操作的 cookie 的域中,因为 WebDriver 不允许您从与当前页面所在的域不同的域添加或删除 cookie。