Switching Between Frames Using Selenium WebDriver in Java – 使用 Java 中的 Selenium WebDriver 在帧之间切换

最后修改: 2023年 11月 13日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.导言

Managing frames and iframes is a crucial skill for test automation engineers. Selenium WebDriver allows us to work with both frames and iframes in the same way.

管理框架和 iframe 是测试自动化工程师的一项重要技能。Selenium WebDriver允许我们以同样的方式处理框架和 iframe。

In this tutorial, we’ll explore a few distinct methods to switch between frames with Selenium WebDriver. These methods include using a WebElement, a name or ID, and an index.

在本教程中,我们将探讨使用 Selenium WebDriver 在之间切换的几种不同方法。这些方法包括使用 WebElement、名称或 ID 以及索引。</span

By the end, we’ll be well-equipped to tackle iframe interactions confidently, enhancing the scope and effectiveness of our automation tests.

最后,我们将能够自信地处理 iframe 交互,从而提高自动化测试的范围和效率。

2. Difference Between Frame and Iframe

2.框架与单帧的区别

The terms frames and iframes are often encountered in web development. Each serves a distinct purpose in structuring and enhancing web content.

框架和 iframe 这两个术语在网页开发中经常会遇到。它们在构建和增强网页内容方面各有特点。

Frames, an older HTML feature, partition a web page into separate sections where each section has its own dedicated HTML document. Although frames are deprecated, they are still encountered on the web.

框架是一种较早的 HTML 功能,它将网页分割成不同的部分,每个部分都有自己专用的 HTML 文档。虽然框架已被淘汰,但在网络上仍会遇到。

Iframes (inline frames) embed a separate HTML document within a single frame on a web page. They are widely used in web pages for various purposes, such as incorporating external content like maps, social media widgets, advertisements, or interactive forms seamlessly.

框架(内联框架) 在网页的单个框架内嵌入独立的 HTML 文档。它们广泛应用于网页中的各种用途,例如无缝整合地图、社交媒体小工具、广告或交互式表单等外部内容。

3. Switch to Frame Using a WebElement

3.使用 WebElement 切换到框架

Switching using a WebElement is the most flexible option. We can find the frame using any selector, like ID, name, CSS selector, or XPath, to find the specific iframe we want:

使用 WebElement 进行切换是最灵活的选择。我们可以使用任何选择器(如 ID、名称、CSS 选择器或 XPath)来查找框架,从而找到我们想要的特定 iframe:

WebElement iframeElement = driver.findElement(By.cssSelector("#frame_selector"));
driver.switchTo().frame(iframeElement);

For a more reliable approach, it’s better to use explicit waits, such as ExpectedConditions.frameToBeAvailableAndSwitchToIt():

要获得更可靠的方法,最好使用显式等待,例如 ExpectedConditions.frameToBeAvailableAndSwitchToIt()

WebElement iframeElement = driver.findElement(By.cssSelector("#frame_selector"));
new WebDriverWait(driver, Duration.ofSeconds(10))
  .until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(iframeElement))

This helps ensure that the iframe is fully loaded and ready for interaction, reducing potential timing issues and making our automation scripts more robust when working with iframes.

这有助于确保 iframe 已完全加载并准备好进行交互,从而减少潜在的时间问题,并使我们的自动化脚本在处理 iframe 时更加强大。

4. Switch to Frame Using a Name or ID

4.使用名称或 ID 切换到框架

Another method to navigate into a frame is by leveraging its name or ID attribute. This approach is straightforward and particularly useful when these attributes are unique:

另一种进入框架的方法是利用其名称或 ID 属性。这种方法简单明了,尤其是当这些属性是唯一的时候:

driver.switchTo().frame("frame_name_or_id");

Using explicit wait ensures that the frame is fully loaded and prepared for interaction:

使用显式等待 确保框架已完全加载并准备好进行交互

new WebDriverWait(driver, Duration.ofSeconds(10))
  .until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("frame_name_or_id"));

5. Switch to Frame Using an Index

5.使用索引切换到框架

Selenium allows us to switch to a frame using a simple numerical index. The first frame has an index of 0, the second has an index of 1, and so on. Switching to frames using an index offers a flexible and convenient approach, especially when an iframe lacks a distinct name or ID.

Selenium 允许我们使用一个简单的数字索引切换到一个框架。第一个框架的索引为 0,第二个框架的索引为 1,以此类推。使用索引切换到框架提供了一种灵活方便的方法,尤其是当 iframe 没有明确的名称或 ID 时

By specifying the index of the frame, we can seamlessly navigate through the frames within a web page:

通过指定框架的索引,我们可以无缝地浏览网页中的框架:

driver.switchTo().frame(0);

Explicit wait makes code more robust:

显式等待使代码更加健壮:

new WebDriverWait(driver, Duration.ofSeconds(10))
  .until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(0));

However, it’s important to use frame indexes with caution because the order of frames can change on a web page. If a frame is added or removed, it can disrupt the index order, leading to potential failures in our automated tests.

但是,必须谨慎使用框架索引,因为框架的顺序可能会在网页上发生变化。如果添加或删除框架,就会扰乱索引顺序,从而导致自动测试可能失败。

6. Switching to a Nested Frame

6.切换到嵌套框架

When frames are nested, it means that one or more frames are embedded within other frames, forming a parent-child relationship. This hierarchy can continue to multiple levels, resulting in complex nested frame structures:

当框架嵌套时,意味着一个或多个框架嵌入到其他框架中,形成父子关系。这种层级关系可以延续到多个层级,从而形成复杂的嵌套框架结构:

<!DOCTYPE html>
<html>
<head>
    <title>Frames Example</title>
</head>
<body>
    <h1>Main Content</h1>
    <p>This is the main content of the web page.</p>

    <iframe id="outer_frame" width="400" height="300">
        <h2>Outer Frame</h2>
        <p>This is the content of the outer frame.</p>

        <iframe id="inner_frame" width="300" height="200">
            <h3>Inner Frame</h3>
            <p>This is the content of the inner frame.</p>
        </iframe>
    </iframe>

    <p>More content in the main page.</p>
</body>
</html>

Selenium provides a straightforward method for handling them. To access an inner frame within a nested frame structure, we should switch from the outermost to the inner one sequentially. This allows us to access the elements within each frame as we go deeper into the hierarchy:

Selenium 提供了一种直接的方法来处理它们。要访问嵌套框架结构中的内部框架,我们应按顺序从最外层切换到内部框架。这样,当我们深入层次结构时,就可以访问每个框架内的元素:

driver.switchTo().frame("outer_frame");
driver.switchTo().frame("inner_frame");

7. Switching Back From Frame or Nested Frame

7.从框架或嵌套框架切换回来

Selenium provides a mechanism to switch back from frames and nested frames with distinct methods. For returning to the main content, we can use the method defaultContent():

Selenium 提供了一种机制,可使用不同的方法从框架和嵌套框架中切换回来。要返回主内容,我们可以使用方法 defaultContent()

driver.switchTo().defaultContent()

It essentially exits all frames and ensures that our subsequent interactions take place in the main context of the web page. This is particularly useful when we’ve completed tasks within frames and need to continue our actions in the main content.

从本质上讲,它可以退出所有框架,并确保我们的后续交互在网页的主上下文中进行。当我们在框架内完成任务后,需要在主内容中继续我们的操作时,这一点尤其有用。

For moving to the parent frame, we can use the parentFrame() method:

要移动到父框架,我们可以使用 parentFrame() 方法:

driver.switchTo().parentFrame()

This method allows us to transition from a child frame back to its immediate parent frame. It’s particularly valuable when we’re working with nested frames, each embedded within another, and we need to move between them.

通过这种方法,我们可以从子框架过渡回直接的父框架。当我们处理嵌套框架(每个框架都嵌入在另一个框架中),需要在它们之间移动时,这种方法尤为重要。

8. Conclusion

8.结论

In this article, we’ve explored frames and how to work with them using Selenium WebDriver. We’ve learned different methods to switch between them using WebElements, names or IDs, and numerical indices. These methods offer flexibility and precision.

在本文中,我们探讨了框架以及如何使用 Selenium WebDriver 处理框架。我们学习了使用 WebElement、名称或 ID 以及数字索引在它们之间切换的不同方法。这些方法既灵活又精确。

By using explicit waits, we’ve ensured reliable interactions with frames, reducing potential issues and making our automation scripts more robust.

通过使用显式等待,我们确保了与帧的可靠交互,减少了潜在问题,并使我们的自动化脚本更加稳健。

We’ve learned how to handle nested frames by sequentially switching from the outermost frame to the inner ones, allowing us to access elements within complex nested frame structures. We also learned how to switch back to the main content as well as move to the parent frame.

我们已经学会了如何通过从最外层框架到内层框架的顺序切换来处理嵌套框架,从而可以访问复杂嵌套框架结构中的元素。我们还学会了如何切换回主要内容以及移动到父框架。

In conclusion, mastering frame and iframe handling with Selenium WebDriver is vital for test automation engineers. With the knowledge and techniques, we’re well-prepared to confidently deal with frames.

总之,掌握使用 Selenium WebDriver 处理框架和 iframe 对测试自动化工程师来说至关重要。有了这些知识和技术,我们就能做好充分准备,自信地处理框架。

As always, the code presented in this article is available over on GitHub.

与往常一样,本文中介绍的代码可在 GitHub 上获取。