使用窗口和标签页
窗口和标签页
获取窗口句柄
WebDriver 不区分窗口和标签页。如果您的网站打开新的标签页或窗口,Selenium 将允许您使用窗口句柄来操作它。每个窗口都有一个唯一的标识符,该标识符在单个会话中保持不变。您可以使用以下方法获取当前窗口的窗口句柄
// Navigate to Url
driver.get("https://seleniumcn.cn/selenium/web/window_switching_tests/page_with_frame.html");
//fetch handle of this
String currHandle=driver.getWindowHandle();
assertNotNull(currHandle);
driver.current_window_handle
// Navigate to Url
driver.Url="https://seleniumcn.cn/selenium/web/window_switching_tests/page_with_frame.html";
//fetch handle of this
String currHandle = driver.CurrentWindowHandle;
Assert.IsNotNull(currHandle);
driver.window_handle
await driver.getWindowHandle();
driver.windowHandle
切换窗口或标签页
单击在新窗口中打开的链接会将新窗口或标签页聚焦在屏幕上,但 WebDriver 不知道操作系统认为哪个窗口处于活动状态。要使用新窗口,您需要切换到它。为此,我们获取所有窗口句柄,并将它们存储在数组中。数组位置按照窗口启动的顺序填充。因此,第一个位置将是默认浏览器,依此类推。
//click on link to open a new window
driver.findElement(By.linkText("Open new window")).click();
//fetch handles of all windows, there will be two, [0]- default, [1] - new window
Object[] windowHandles=driver.getWindowHandles().toArray();
driver.switchTo().window((String) windowHandles[1]);
//assert on title of new window
String title=driver.getTitle();
assertEquals("Simple Page",title);
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
with webdriver.Firefox() as driver:
# Open URL
driver.get("https://seleniumhq.github.io")
# Setup wait for later
wait = WebDriverWait(driver, 10)
# Store the ID of the original window
original_window = driver.current_window_handle
# Check we don't have other windows open already
assert len(driver.window_handles) == 1
# Click the link which opens in a new window
driver.find_element(By.LINK_TEXT, "new window").click()
# Wait for the new window or tab
wait.until(EC.number_of_windows_to_be(2))
# Loop through until we find a new window handle
for window_handle in driver.window_handles:
if window_handle != original_window:
driver.switch_to.window(window_handle)
break
# Wait for the new tab to finish loading content
wait.until(EC.title_is("SeleniumHQ Browser Automation"))
//click on link to open a new window
driver.FindElement(By.LinkText("Open new window")).Click();
//fetch handles of all windows, there will be two, [0]- default, [1] - new window
IList<string> windowHandles = new List<string>(driver.WindowHandles);
driver.SwitchTo().Window(windowHandles[1]);
//assert on title of new window
String title = driver.Title;
Assert.AreEqual("Simple Page", title);
# Store the ID of the original window
original_window = driver.window_handle
# Check we don't have other windows open already
assert(driver.window_handles.length == 1, 'Expected one window')
# Click the link which opens in a new window
driver.find_element(link: 'new window').click
# Wait for the new window or tab
wait.until { driver.window_handles.length == 2 }
#Loop through until we find a new window handle
driver.window_handles.each do |handle|
if handle != original_window
driver.switch_to.window handle
break
end
end
#Wait for the new tab to finish loading content
wait.until { driver.title == 'Selenium documentation'}
//Store the ID of the original window
const originalWindow = await driver.getWindowHandle();
//Check we don't have other windows open already
assert((await driver.getAllWindowHandles()).length === 1);
//Click the link which opens in a new window
await driver.findElement(By.linkText('new window')).click();
//Wait for the new window or tab
await driver.wait(
async () => (await driver.getAllWindowHandles()).length === 2,
10000
);
//Loop through until we find a new window handle
const windows = await driver.getAllWindowHandles();
windows.forEach(async handle => {
if (handle !== originalWindow) {
await driver.switchTo().window(handle);
}
});
//Wait for the new tab to finish loading content
await driver.wait(until.titleIs('Selenium documentation'), 10000);
//Store the ID of the original window
val originalWindow = driver.getWindowHandle()
//Check we don't have other windows open already
assert(driver.getWindowHandles().size() === 1)
//Click the link which opens in a new window
driver.findElement(By.linkText("new window")).click()
//Wait for the new window or tab
wait.until(numberOfWindowsToBe(2))
//Loop through until we find a new window handle
for (windowHandle in driver.getWindowHandles()) {
if (!originalWindow.contentEquals(windowHandle)) {
driver.switchTo().window(windowHandle)
break
}
}
//Wait for the new tab to finish loading content
wait.until(titleIs("Selenium documentation"))
关闭窗口或标签页
当您完成窗口或标签页的操作,并且它不是浏览器中打开的最后一个窗口或标签页时,您应该关闭它并切换回您之前使用的窗口。假设您遵循了上一节中的代码示例,您将把之前的窗口句柄存储在一个变量中。将它们放在一起,您将得到
//closing current window
driver.close();
//Switch back to the old tab or window
driver.switchTo().window((String) windowHandles[0]);
#Close the tab or window
driver.close()
#Switch back to the old tab or window
driver.switch_to.window(original_window)
//closing current window
driver.Close();
//Switch back to the old tab or window
driver.SwitchTo().Window(windowHandles[0]);
#Close the tab or window
driver.close
#Switch back to the old tab or window
driver.switch_to.window original_window
//Close the tab or window
await driver.close();
//Switch back to the old tab or window
await driver.switchTo().window(originalWindow);
//Close the tab or window
driver.close()
//Switch back to the old tab or window
driver.switchTo().window(originalWindow)
如果在关闭窗口后忘记切换回另一个窗口句柄,将导致 WebDriver 在现在已关闭的页面上执行,并会触发 No Such Window Exception 错误。您必须切换回有效的窗口句柄才能继续执行。
创建新窗口(或)新标签页并切换
创建一个新的窗口(或)标签页,并将新窗口或标签页聚焦在屏幕上。您无需切换即可使用新的窗口(或)标签页。如果除了新窗口之外,您还打开了两个以上的窗口(或)标签页,您可以循环遍历 WebDriver 可以看到的所有窗口或标签页,并切换到不是原始窗口或标签页的那个。
注意:此功能适用于 Selenium 4 及更高版本。
//Opens a new tab and switches to new tab
driver.switchTo().newWindow(WindowType.TAB);
assertEquals("",driver.getTitle());
//Opens a new window and switches to new window
driver.switchTo().newWindow(WindowType.WINDOW);
assertEquals("",driver.getTitle());
# Opens a new tab and switches to new tab
driver.switch_to.new_window('tab')
# Opens a new window and switches to new window
driver.switch_to.new_window('window')
//Opens a new tab and switches to new tab
driver.SwitchTo().NewWindow(WindowType.Tab);
Assert.AreEqual("", driver.Title);
//Opens a new window and switches to new window
driver.SwitchTo().NewWindow(WindowType.Window);
Assert.AreEqual("", driver.Title);
打开一个新标签页并切换到新标签页
driver.switch_to.new_window(:tab)
打开一个新窗口并切换到新窗口
driver.switch_to.new_window(:window)
await driver.switchTo().newWindow('tab');
await driver.switchTo().newWindow('window');
// Opens a new tab and switches to new tab
driver.switchTo().newWindow(WindowType.TAB)
// Opens a new window and switches to new window
driver.switchTo().newWindow(WindowType.WINDOW)
在会话结束时退出浏览器
当您完成浏览器会话时,您应该调用 quit,而不是 close
//quitting driver
driver.quit(); //close all windows
driver.quit()
//quitting driver
driver.Quit(); //close all windows
driver.quit
await driver.quit();
driver.quit()
- Quit 将会
- 关闭与该 WebDriver 会话关联的所有窗口和标签页
- 关闭浏览器进程
- 关闭后台驱动程序进程
- 通知 Selenium Grid 浏览器不再使用,因此可以被另一个会话使用(如果您正在使用 Selenium Grid)
未能调用 quit 将会在您的机器上留下额外的后台进程和端口运行,这可能会在以后给您带来问题。
一些测试框架提供了方法和注解,您可以在测试结束时挂钩到这些方法和注解中以进行清理。
/**
* Example using JUnit
* https://junit.cn/junit5/docs/current/api/org/junit/jupiter/api/AfterAll.html
*/
@AfterAll
public static void tearDown() {
driver.quit();
}
# unittest teardown
# https://docs.pythonlang.cn/3/library/unittest.html?highlight=teardown#unittest.TestCase.tearDown
def tearDown(self):
self.driver.quit()
/*
Example using Visual Studio's UnitTesting
https://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.aspx
*/
[TestCleanup]
public void TearDown()
{
driver.Quit();
}
# UnitTest Teardown
# https://www.rubydoc.info/github/test-unit/test-unit/Test/Unit/TestCase
def teardown
@driver.quit
end
/**
* Example using Mocha
* https://mocha.node.org.cn/#hooks
*/
after('Tear down', async function () {
await driver.quit();
});
/**
* Example using JUnit
* https://junit.cn/junit5/docs/current/api/org/junit/jupiter/api/AfterAll.html
*/
@AfterAll
fun tearDown() {
driver.quit()
}
如果不在测试上下文中运行 WebDriver,您可以考虑使用大多数语言提供的 try / finally
,以便异常仍然会清理 WebDriver 会话。
try {
//WebDriver code here...
} finally {
driver.quit();
}
try:
#WebDriver code here...
finally:
driver.quit()
try {
//WebDriver code here...
} finally {
driver.Quit();
}
begin
#WebDriver code here...
ensure
driver.quit
end
try {
//WebDriver code here...
} finally {
await driver.quit();
}
try {
//WebDriver code here...
} finally {
driver.quit()
}
Python 的 WebDriver 现在支持 python 上下文管理器,当使用 with
关键字时,可以在执行结束时自动退出驱动程序。
with webdriver.Firefox() as driver:
# WebDriver code here...
# WebDriver will automatically quit after indentation
窗口管理
屏幕分辨率会影响 Web 应用程序的呈现方式,因此 WebDriver 提供了移动和调整浏览器窗口大小的机制。
获取窗口大小
以像素为单位获取浏览器窗口的大小。
//Access each dimension individually
int width = driver.manage().window().getSize().getWidth();
int height = driver.manage().window().getSize().getHeight();
//Or store the dimensions and query them later
Dimension size = driver.manage().window().getSize();
int width1 = size.getWidth();
int height1 = size.getHeight();
# Access each dimension individually
width = driver.get_window_size().get("width")
height = driver.get_window_size().get("height")
# Or store the dimensions and query them later
size = driver.get_window_size()
width1 = size.get("width")
height1 = size.get("height")
//Access each dimension individually
int width = driver.Manage().Window.Size.Width;
int height = driver.Manage().Window.Size.Height;
//Or store the dimensions and query them later
System.Drawing.Size size = driver.Manage().Window.Size;
int width1 = size.Width;
int height1 = size.Height;
# Access each dimension individually
width = driver.manage.window.size.width
height = driver.manage.window.size.height
# Or store the dimensions and query them later
size = driver.manage.window.size
width1 = size.width
height1 = size.height
const { width, height } = await driver.manage().window().getRect();
const rect = await driver.manage().window().getRect();
const windowWidth = rect.width;
const windowHeight = rect.height;
//Access each dimension individually
val width = driver.manage().window().size.width
val height = driver.manage().window().size.height
//Or store the dimensions and query them later
val size = driver.manage().window().size
val width1 = size.width
val height1 = size.height
设置窗口大小
恢复窗口并设置窗口大小。
driver.manage().window().setSize(new Dimension(1024, 768));
driver.set_window_size(1024, 768)
driver.Manage().Window.Size = new Size(1024, 768);
driver.manage.window.resize_to(1024,768)
await driver.manage().window().setRect({ width: 1024, height: 768 });
driver.manage().window().size = Dimension(1024, 768)
获取窗口位置
获取浏览器窗口左上角的坐标。
// Access each dimension individually
int x = driver.manage().window().getPosition().getX();
int y = driver.manage().window().getPosition().getY();
// Or store the dimensions and query them later
Point position = driver.manage().window().getPosition();
int x1 = position.getX();
int y1 = position.getY();
# Access each dimension individually
x = driver.get_window_position().get('x')
y = driver.get_window_position().get('y')
# Or store the dimensions and query them later
position = driver.get_window_position()
x1 = position.get('x')
y1 = position.get('y')
//Access each dimension individually
int x = driver.Manage().Window.Position.X;
int y = driver.Manage().Window.Position.Y;
//Or store the dimensions and query them later
Point position = driver.Manage().Window.Position;
int x1 = position.X;
int y1 = position.Y;
#Access each dimension individually
x = driver.manage.window.position.x
y = driver.manage.window.position.y
# Or store the dimensions and query them later
rect = driver.manage.window.rect
x1 = rect.x
y1 = rect.y
const { x, y } = await driver.manage().window().getRect();
const rect = await driver.manage().window().getRect();
const x1 = rect.x;
const y1 = rect.y;
// Access each dimension individually
val x = driver.manage().window().position.x
val y = driver.manage().window().position.y
// Or store the dimensions and query them later
val position = driver.manage().window().position
val x1 = position.x
val y1 = position.y
设置窗口位置
将窗口移动到选定的位置。
// Move the window to the top left of the primary monitor
driver.manage().window().setPosition(new Point(0, 0));
# Move the window to the top left of the primary monitor
driver.set_window_position(0, 0)
// Move the window to the top left of the primary monitor
driver.Manage().Window.Position = new Point(0, 0);
driver.manage.window.move_to(0,0)
// Move the window to the top left of the primary monitor
await driver.manage().window().setRect({ x: 0, y: 0 });
// Move the window to the top left of the primary monitor
driver.manage().window().position = Point(0,0)
最大化窗口
放大窗口。对于大多数操作系统,窗口将填充屏幕,而不会阻止操作系统自身的菜单和工具栏。
driver.manage().window().maximize();
driver.maximize_window()
driver.Manage().Window.Maximize();
driver.manage.window.maximize
await driver.manage().window().maximize();
driver.manage().window().maximize()
最小化窗口
最小化当前浏览上下文的窗口。此命令的确切行为特定于各个窗口管理器。
最小化窗口通常会将窗口隐藏在系统托盘中。
注意:此功能适用于 Selenium 4 及更高版本。
driver.manage().window().minimize();
driver.minimize_window()
driver.Manage().Window.Minimize();
driver.manage.window.minimize
await driver.manage().window().minimize();
driver.manage().window().minimize()
全屏窗口
填充整个屏幕,类似于在大多数浏览器中按 F11。
driver.manage().window().fullscreen();
driver.fullscreen_window()
driver.Manage().Window.FullScreen();
driver.manage.window.full_screen
await driver.manage().window().fullscreen();
driver.manage().window().fullscreen()
TakeScreenshot
用于捕获当前浏览上下文的屏幕截图。WebDriver 端点 screenshot 返回以 Base64 格式编码的屏幕截图。
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.chrome.ChromeDriver;
import java.io.*;
import org.openqa.selenium.*;
public class SeleniumTakeScreenshot {
public static void main(String args[]) throws IOException {
WebDriver driver = new ChromeDriver();
driver.get("http://www.example.com");
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("./image.png"));
driver.quit();
}
}
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://www.example.com")
# Returns and base64 encoded string into image
driver.save_screenshot('./image.png')
driver.quit()
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
var driver = new ChromeDriver();
driver.Navigate().GoToUrl("http://www.example.com");
Screenshot screenshot = (driver as ITakesScreenshot).GetScreenshot();
screenshot.SaveAsFile("screenshot.png", ScreenshotImageFormat.Png); // Format values are Bmp, Gif, Jpeg, Png, Tiff
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'https://example.com/'
# Takes and Stores the screenshot in specified path
driver.save_screenshot('./image.png')
end
// Captures the screenshot
let encodedString = await driver.takeScreenshot();
// save screenshot as below
// await fs.writeFileSync('./image.png', encodedString, 'base64');
import com.oracle.tools.packager.IOUtils.copyFile
import org.openqa.selenium.*
import org.openqa.selenium.chrome.ChromeDriver
import java.io.File
fun main(){
val driver = ChromeDriver()
driver.get("https://www.example.com")
val scrFile = (driver as TakesScreenshot).getScreenshotAs<File>(OutputType.FILE)
copyFile(scrFile, File("./image.png"))
driver.quit()
}
TakeElementScreenshot
用于捕获当前浏览上下文中元素的屏幕截图。WebDriver 端点 screenshot 返回以 Base64 格式编码的屏幕截图。
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import java.io.File;
import java.io.IOException;
public class SeleniumelementTakeScreenshot {
public static void main(String args[]) throws IOException {
WebDriver driver = new ChromeDriver();
driver.get("https://www.example.com");
WebElement element = driver.findElement(By.cssSelector("h1"));
File scrFile = element.getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("./image.png"));
driver.quit();
}
}
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("http://www.example.com")
ele = driver.find_element(By.CSS_SELECTOR, 'h1')
# Returns and base64 encoded string into image
ele.screenshot('./image.png')
driver.quit()
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
// Webdriver
var driver = new ChromeDriver();
driver.Navigate().GoToUrl("http://www.example.com");
// Fetch element using FindElement
var webElement = driver.FindElement(By.CssSelector("h1"));
// Screenshot for the element
var elementScreenshot = (webElement as ITakesScreenshot).GetScreenshot();
elementScreenshot.SaveAsFile("screenshot_of_element.png");
# Works with Selenium4-alpha7 Ruby bindings and above
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome
begin
driver.get 'https://example.com/'
ele = driver.find_element(:css, 'h1')
# Takes and Stores the element screenshot in specified path
ele.save_screenshot('./image.jpg')
end
let header = await driver.findElement(By.css('h1'));
// Captures the element screenshot
let encodedString = await header.takeScreenshot(true);
// save screenshot as below
// await fs.writeFileSync('./image.png', encodedString, 'base64');
import org.apache.commons.io.FileUtils
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.*
import java.io.File
fun main() {
val driver = ChromeDriver()
driver.get("https://www.example.com")
val element = driver.findElement(By.cssSelector("h1"))
val scrFile: File = element.getScreenshotAs(OutputType.FILE)
FileUtils.copyFile(scrFile, File("./image.png"))
driver.quit()
}
执行脚本
在所选框架或窗口的当前上下文中执行 JavaScript 代码片段。
//Creating the JavascriptExecutor interface object by Type casting
JavascriptExecutor js = (JavascriptExecutor)driver;
//Button Element
WebElement button =driver.findElement(By.name("btnLogin"));
//Executing JavaScript to click on element
js.executeScript("arguments[0].click();", button);
//Get return value from script
String text = (String) js.executeScript("return arguments[0].innerText", button);
//Executing JavaScript directly
js.executeScript("console.log('hello world')");
# Stores the header element
header = driver.find_element(By.CSS_SELECTOR, "h1")
# Executing JavaScript to capture innerText of header element
driver.execute_script('return arguments[0].innerText', header)
//creating Chromedriver instance
IWebDriver driver = new ChromeDriver();
//Creating the JavascriptExecutor interface object by Type casting
IJavaScriptExecutor js = (IJavaScriptExecutor) driver;
//Button Element
IWebElement button = driver.FindElement(By.Name("btnLogin"));
//Executing JavaScript to click on element
js.ExecuteScript("arguments[0].click();", button);
//Get return value from script
String text = (String)js.ExecuteScript("return arguments[0].innerText", button);
//Executing JavaScript directly
js.ExecuteScript("console.log('hello world')");
# Stores the header element
header = driver.find_element(css: 'h1')
# Get return value from script
result = driver.execute_script("return arguments[0].innerText", header)
# Executing JavaScript directly
driver.execute_script("alert('hello world')")
// Stores the header element
let header = await driver.findElement(By.css('h1'));
// Executing JavaScript to capture innerText of header element
let text = await driver.executeScript('return arguments[0].innerText', header);
// Stores the header element
val header = driver.findElement(By.cssSelector("h1"))
// Get return value from script
val result = driver.executeScript("return arguments[0].innerText", header)
// Executing JavaScript directly
driver.executeScript("alert('hello world')")
打印页面
在浏览器中打印当前页面。
注意:这需要 Chromium 浏览器处于无头模式
import org.openqa.selenium.print.PrintOptions;
driver.get("https://seleniumcn.cn");
printer = (PrintsPage) driver;
PrintOptions printOptions = new PrintOptions();
printOptions.setPageRanges("1-2");
Pdf pdf = printer.print(printOptions);
String content = pdf.getContent();
from selenium.webdriver.common.print_page_options import PrintOptions
print_options = PrintOptions()
print_options.page_ranges = ['1-2']
driver.get("printPage.html")
base64code = driver.print_page(print_options)
// code sample not available please raise a PR
driver.navigate_to 'https://seleniumcn.cn'
base64encodedContent = driver.print_page(orientation: 'landscape')
await driver.get('https://seleniumcn.cn/selenium/web/alerts.html');
let base64 = await driver.printPage({pageRanges: ["1-2"]});
// page can be saved as a PDF as below
// await fs.writeFileSync('./test.pdf', base64, 'base64');
driver.get("https://seleniumcn.cn")
val printer = driver as PrintsPage
val printOptions = PrintOptions()
printOptions.setPageRanges("1-2")
val pdf: Pdf = printer.print(printOptions)
val content = pdf.content