一, 多窗口介绍
1,多窗口处理
- 在一个浏览器中同时打开多个窗口或选项卡。
- 如果不进行窗口切换,就无法在新窗口中进行后续的操作。
2,导入相应的依赖
<!-- 版本配置-->
<properties>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>17</java.version>
<junit.jupiter.version>5.9.2</junit.jupiter.version>
<maven.compiler.version>3.11.0</maven.compiler.version>
<maven-surefire-plugin.version>3.0.0</maven-surefire-plugin.version>
<!-- log日志 -->
<slf4j.version>2.0.7</slf4j.version>
<logback.version>1.4.6</logback.version>
<!-- allure报告 -->
<allure.version>2.21.0</allure.version>
<aspectj.version>1.9.19</aspectj.version>
<allure.maven.version>2.12.0</allure.maven.version>
<allure.cmd.download.url>
https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline
</allure.cmd.download.url>
<!-- hamcrest断言 -->
<hamcrest.version>2.2</hamcrest.version>
<!-- yaml对应解析 -->
<jackson.version>2.14.2</jackson.version>
<!-- selenium安装 -->
<selenium.verison>4.8.3</selenium.verison>
<webdriver.manager.version>5.3.2</webdriver.manager.version>
</properties>
<dependencyManagement>
<!--junit5 版本管理, 找到对应依赖关系的 pom 文件,为了解决依赖冲突问题-->
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>${junit.jupiter.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- junit 相关依赖下载-->
<!-- junit5 -->
<dependency>
<!-- 组织的名称;仓库中唯一标识一个项目,确保项目的唯一性 -->
<groupId>org.junit.jupiter</groupId>
<!-- 项目的名称或模块的名称 -->
<artifactId>junit-jupiter</artifactId>
<!-- 依赖的作用范围
compile:默认的作用范围,表示在编译阶段和运行时都是可见的
test:表示依赖只在测试阶段 src/test下可见。
provided:表示依赖在编译阶段和测试阶段是可见的。
runtime:表示依赖在编译阶段不可见,但在运行时可见。-->
<scope>test</scope>
</dependency>
<!-- junit5-suite -->
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<scope>test</scope>
</dependency>
<!-- 用做兼容老版本 -->
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<scope>test</scope>
</dependency>
<!-- hamcrest断言 -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<!-- yaml文件解析-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- log日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>compile</scope>
</dependency>
<!-- allure报告-->
<dependency>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-junit5</artifactId>
<version>${allure.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
<!-- selenium安装 -->
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.verison}</version>
</dependency>
<!-- webdrivermanager -->
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>${webdriver.manager.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- maven 命令行执行插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<argLine>
-javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
</argLine>
<includes>
<include>**/*Test</include>
<include>**/Test*</include>
</includes>
</configuration>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.jupiter.version}</version>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit.jupiter.version}</version>
</dependency>
</dependencies>
</plugin>
<!--maven 编译使用插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<parameters>true</parameters>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${maven.compiler.encoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>io.qameta.allure</groupId>
<artifactId>allure-maven</artifactId>
<version>${allure.maven.version}</version>
<configuration>
<reportVersion>${allure.version}</reportVersion>
<allureDownloadUrl>${allure.cmd.download.url}/${allure.version}/allure-commandline-${allure.version}.zip</allureDownloadUrl>
</configuration>
</plugin>
</plugins>
</build>
3,窗口切换代码实现
package windowsHandle;
import io.github.bonigarcia.wdm.WebDriverManager;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertAll;
import java.net.MalformedURLException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class WindowsHandlerTest {
static WebDriver driver;
List<Executable> executableList = new ArrayList<>();
@BeforeAll
static void setupClass() {
ChromeOptions options = new ChromeOptions();
options.addArguments("--remote-allow-origins=*");
//1,使用WebDriverManager创建一个driver对象,WebDriverManager仅支持114版本以下,135不支持
// driver = WebDriverManager.chromedriver().create();
driver = new ChromeDriver(options);
//2,声明隐式等待
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(8));
}
@AfterAll
static void tearDownClass() throws InterruptedException {
Thread.sleep(5000);
driver.quit();
}
@Test
void handlerTest() throws InterruptedException, MalformedURLException {
//3,打开一个网页
driver.get("https://vip.ceshiren.com/#/ui_study/frame");
//4,获取打开页面的句柄
String originHandle = driver.getWindowHandle();
System.out.println("获取第一个页面句柄:" + originHandle);
//5,进行业务操作,打开一个新的窗口
driver.findElement(By.xpath("//*[text()='元素定位']")).click();
//6,获取所有窗口的句柄
Set<String> windowHandles = driver.getWindowHandles();
//获取当前页面标题
String title = driver.getTitle();
System.out.println("当前页面标题为:" + title);
//7,进行窗口切换操作
for(String windowHandle : windowHandles) {
if(!windowHandle.equals(originHandle)) {
driver.switchTo().window(windowHandle);
break;
}
}
//8,新窗口的业务逻辑操作
String title2 = driver.getTitle();
System.out.println("新窗口页面标题为:" + title2);
executableList.add(() ->assertThat(title2,containsString("测试人社区")));
//9,切回默认页面
driver.switchTo().window(originHandle);
String title3 = driver.getTitle();
System.out.println("切回默认窗口页面标题为:" + title3);
executableList.add(() ->assertThat(title3,equalTo("霍格沃兹测试开发")));
assertAll(executableList);
}
}
二, frame 介绍
1,简介
- (1)frame 是 html 中的框架。可以在同一个浏览器中显示不止一个页面。
- (2)frame 标签包含 frameset、frame、iframe 三种。
-
frameset
:frame必须嵌套frameset标签里面,frameset和普通的标签一样,不会影响正常的定位。 -
frame/iframe
:直接嵌套在html里面,可以使用 index、id、name、webelement 任意种方式定位。
-
- (3)如果不进行 frame 切换,就无法定位到 frame 中的元素进行后续的操作。
2,frame嵌套测试页面常见类型
-
单层嵌套frame
-
多层嵌套frame
3,常用方法
4代码示例
@Test
void frameTest(){
//3,打开一个网页
driver.get("https://vip.ceshiren.com/#/ui_study/frame");
//进行业务操作,通过代码直接获取定位元素的文本信息会报错:NoSuchElementException
//必须要切换到对应的frame才能获取到对应元素的文本
driver.switchTo().frame("frame1");
WebElement element = driver.findElement(By.id("frame_btn"));
System.out.println("第1个按钮:" + element.getText());
//切换到第二个frame
//首先切换到父框架
driver.switchTo().parentFrame();
//再切换到第二个frame,方法值为frame标签的id或者name属性的值
driver.switchTo().frame("Main");
WebElement element2 = driver.findElement(By.id("frame_btn"));
System.out.println("第2个按钮:" +element2.getText());
}
//多层嵌套frame:必须一层一层的切换,不然定位不到嵌套层的元素
@Test
void moreFrame(){
//3,打开一个网页
driver.get("https://vip.ceshiren.com/#/ui_study/iframe");
//切换第一层frame "//*[@class='iframe-div']")
WebElement iframe1 = driver.findElement(By.xpath("//*[@class='iframe-div']/iframe"));
driver.switchTo().frame(iframe1);
//切换第二层
WebElement iframe2 = driver.findElement(By.xpath("//*[@class='ma-2 frame2']/iframe"));
driver.switchTo().frame(iframe2);
//定位第二次嵌套frame的按钮元素并获取文本信息
WebElement element = driver.findElement(By.xpath("//*[@class='VPNavBarTitle']"));
System.out.println("嵌套层按钮元素:" + element.getText());
//切换到最外层的frame
driver.switchTo().defaultContent();
//再切换到新窗口并点击新窗口
driver.findElement(By.id("openWindows")).click();
}