selenium自动化测试学习心得1

1. 关于测试用例的顺序

首先在你测试的主类上面写@TestMethodOrder(MethodOrderer.OrderAnnotation.class)

然后在测试用例上面, 写@Order(),里面的数字越小,测试的优先级越大

2. 关于getText()和getAttribute("innerText")

getText() 是 Selenium 方法,主要用于获取可见文本,且无需担心是否有隐藏的元素。getAttribute("innerText") 是 JavaScript 方法,获取的是 innerText 属性的值,它会考虑到元素的可见性。

一般获取内容使用getText()足够了,如果获取不到就用getAttribute("innerText")

3. 关于处理Editor.md的文本域

一般我们直接定位,然后sendKeys()是输入不了的

我们需要借助Actions来处理复杂的用户交互操作,点击,键盘输入...

代码

       element = driver.findElement(By.cssSelector("#edit-article > div.CodeMirror.cm-s-default.CodeMirror-wrap > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code > div > pre"));// 向文本框输入内容Actions action = new Actions(driver);action.doubleClick(element).sendKeys(Keys.DELETE).perform();action.sendKeys("我是测试内容!").perform();

具体的解释

 4. 关于页面太大,需要点击滚动条到相应地方去定位元素

发布按钮在页面底部, 因此我们要先滚动到底部才能定位元素

具体代码

   // 滚动页面到底部JavascriptExecutor js = (JavascriptExecutor) driver;js.executeScript("window.scrollTo(0, document.body.scrollHeight);");  // 滚动到底部Thread.sleep(2000);// 滚动到底部// 定位发布按钮WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(2));element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#article_post_submit")));element.click();

解释

5. 关于一些常用的统一工具类

创建驱动, 截图,处理弹窗

package org.xiaobai.forum.testFunction.common;import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.SessionId;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;public class Utils {public static WebDriver driver = null;private static SessionId sessionId;//创建驱动对象public static WebDriver createDriver() {if (driver == null || sessionId == null) {//增加浏览器配置对象,创建驱动对象的时候要强制运行访问所有的链接ChromeOptions options = new ChromeOptions();//表示运行所有的链接options.addArguments("--remote-allow-origins=*");//设置无头模式
//            options.addArguments("-headless");//添加浏览器策略
//        options.setPageLoadStrategy(PageLoadStrategy.NONE);//等待所有页面加载完成//创建浏览器驱动对象,把配置放进驱动对象driver = new ChromeDriver(options);//添加隐式等待,全局元素等待2sdriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));}return driver;}//统一创建驱动对象public Utils() throws InterruptedException {//调用driver对象driver = createDriver();}//屏幕截图public void getScreenShot(String str) throws InterruptedException, IOException {//保存的图片路径: ./src/test/image///                              /2024-08-17///                                          /test01-1743211.png//                                          /test02-1743222.png//                                          /test03-1743245.png//                              /2024-08-18///                                          /test01-1743222.png//                                          /test02-1743442.png//                                          /test03-1743332.png//
//          createDriver();//屏幕截图//设计文件日期格式SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");//参数是年月日SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");//参数时分秒毫秒//生成当前的时间String dirTime = sim1.format(System.currentTimeMillis());String fileTime = sim2.format(System.currentTimeMillis());//拼接文件路径//./src/test/image/2024-08-17/test01-17432.pngString filename = "./src/test/image/" + dirTime + "/" + str + "-" + fileTime + ".png";//方法名-时间.pngFile srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);//把srcFile放到指定位置FileUtils.copyFile(srcFile, new File(filename));}//统一处理弹窗public static void handleAlert() {WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(1));wait.until(ExpectedConditions.alertIsPresent());//处理弹窗Alert alert = driver.switchTo().alert();alert.accept();}
}

6. 关于自动化测试目录结构和使用

目录结构

Utils是统一工具类

testPage里面放测试的页面(测试某个功能)

Runtest 是自动化测试的入口主类

让每个测试page类继承Utils并重写构造方法, 然后定义要跳转的url路径,初始化WebElemnt

写好一个功能后,就去测试主类进行创建并且调用相关的方法

给一个代码例子

Utils类

package org.xiaobai.forum.testFunction.common;import org.apache.commons.io.FileUtils;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.SessionId;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;public class Utils {public static WebDriver driver = null;private static SessionId sessionId;//创建驱动对象public static WebDriver createDriver() {if (driver == null || sessionId == null) {//增加浏览器配置对象,创建驱动对象的时候要强制运行访问所有的链接ChromeOptions options = new ChromeOptions();//表示运行所有的链接options.addArguments("--remote-allow-origins=*");//设置无头模式
//            options.addArguments("-headless");//添加浏览器策略
//        options.setPageLoadStrategy(PageLoadStrategy.NONE);//等待所有页面加载完成//创建浏览器驱动对象,把配置放进驱动对象driver = new ChromeDriver(options);//添加隐式等待,全局元素等待2sdriver.manage().timeouts().implicitlyWait(Duration.ofSeconds(2));}return driver;}//统一创建驱动对象public Utils() throws InterruptedException {//调用driver对象driver = createDriver();}//屏幕截图public void getScreenShot(String str) throws InterruptedException, IOException {//保存的图片路径: ./src/test/image///                              /2024-08-17///                                          /test01-1743211.png//                                          /test02-1743222.png//                                          /test03-1743245.png//                              /2024-08-18///                                          /test01-1743222.png//                                          /test02-1743442.png//                                          /test03-1743332.png//
//          createDriver();//屏幕截图//设计文件日期格式SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");//参数是年月日SimpleDateFormat sim2 = new SimpleDateFormat("HHmmssSS");//参数时分秒毫秒//生成当前的时间String dirTime = sim1.format(System.currentTimeMillis());String fileTime = sim2.format(System.currentTimeMillis());//拼接文件路径//./src/test/image/2024-08-17/test01-17432.pngString filename = "./src/test/image/" + dirTime + "/" + str + "-" + fileTime + ".png";//方法名-时间.pngFile srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);//把srcFile放到指定位置FileUtils.copyFile(srcFile, new File(filename));}//统一处理弹窗public static void handleAlert() {WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(1));wait.until(ExpectedConditions.alertIsPresent());//处理弹窗Alert alert = driver.switchTo().alert();alert.accept();}
}
页面RegisPage 
package org.xiaobai.forum.testFunction.testPage;import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.xiaobai.forum.testFunction.common.Utils;import java.time.Duration;public class RegisPage extends Utils {// 定义传送路径public static String regisPageUrl = "http://127.0.0.1:8080/sign-up.html";public RegisPage() throws InterruptedException {super();}// 创建elementprivate  static WebElement element = null;//TODO 正确public void RegisRight() {// 进入注册页面driver.get(regisPageUrl);// 创建 WebDriverWait 对象WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(2));// 用户名element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#username")));element.sendKeys("lixiaohei");// 昵称element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#nickname")));element.sendKeys("李小黑");// 密码element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#password")));element.sendKeys("123456");// 确认密码element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#passwordRepeat")));element.sendKeys("123456");// 勾选协议element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#policy")));element.click();// 定位注册按钮element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit")));element.click();// 断言注册成功进入了登录页面// 断言当前 URL 是否是登录页面的 标题String pageTitle = driver.getTitle();System.out.println(pageTitle);assert pageTitle.equals("比特论坛 - 用户注册");// 关闭页面driver.quit();}// TODO 注册失败public void RegisFalse(){driver = new ChromeDriver();// TODO 空的情况// 进入注册页面driver.get(regisPageUrl);// 创建 WebDriverWait 对象WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(2));// 只测试用户名为空// 用户名element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#username")));element.sendKeys("");// 昵称element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#nickname")));element.sendKeys("李小黑");// 密码element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#password")));element.sendKeys("123456");// 确认密码element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#passwordRepeat")));element.sendKeys("123456");// 勾选协议element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#policy")));element.click();// 定位注册按钮element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit")));element.click();//定位提示信息element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#signUpForm > div > div:nth-child(2) > div")));assert element.getText().equals("用户名不能为空");// 刷新页面driver.navigate().refresh();// TODO 长度小于6// 用户名element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#username")));element.sendKeys("lixiaohei");// 昵称element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#nickname")));element.sendKeys("李小黑");// 密码(长度<6)element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#password")));element.sendKeys("123");// 确认密码element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#passwordRepeat")));element.sendKeys("123");// 勾选协议element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#policy")));element.click();// 定位注册按钮element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit")));element.click();// 断言是否出现提示信息element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")));assert element.getText().equals("警告");// 刷新页面driver.navigate().refresh();// TODO 包含select// 用户名(包含select)element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#username")));element.sendKeys("selectlixiaohei");// 昵称element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#nickname")));element.sendKeys("李小黑");// 密码element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#password")));element.sendKeys("123456");// 确认密码element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#passwordRepeat")));element.sendKeys("123456");// 勾选协议element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#policy")));element.click();// 定位注册按钮element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("#submit")));element.click();// 断言出现警告element = wait.until(ExpectedConditions.presenceOfElementLocated(By.cssSelector("body > div.jq-toast-wrap.bottom-right > div > h2")));assert element.getText().equals("警告");driver.quit();}}

测试入口类RunTest

package org.xiaobai.forum.testFunction;import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.xiaobai.forum.testFunction.testPage.*;@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class RunTest {@Test@Order(1)void testRegis() throws InterruptedException {//TODO 1. 注册RegisPage regisPage = new RegisPage();// 注册成功regisPage.RegisRight();// 注册失败regisPage.RegisFalse();}@Test@Order(2)void testLogin() throws InterruptedException {//TODO 2. 登录LoginPage loginPage = new LoginPage();// 登录成功loginPage.LoginTrue();// 登录失败loginPage.LoginFalse();}@Test@Order(3)void testPublishPost() throws InterruptedException {//TODO 3. 上传帖子PublishPostPage publishPostPage = new PublishPostPage();// 发布成功publishPostPage.publishSuccess();// 发布失败publishPostPage.publishFail();}@Test@Order(4)void testEditePost() throws InterruptedException {// TODO 4. 修改帖子信息EditPostPage editPostPage = new EditPostPage();editPostPage.EditPost();}@Test@Order(5)void testDetailPost() throws InterruptedException {//TODO 5. 查看帖子详情DetailPostPage detailPostPage = new DetailPostPage();detailPostPage.Detail();}@Test@Order(6)void testDeletePost() throws InterruptedException {//TODO 6. 删除帖子DeletePostPage deletePostPage = new DeletePostPage();deletePostPage.deletePost();}@Test@Order(7)void testEditPerson() throws InterruptedException {//TODO 7. 修改个人信息EditPersonPage editPersonPage = new EditPersonPage();// 编辑成功editPersonPage.EditSuccess();// 编辑失败editPersonPage.EditFail();}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/86195.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring AI 结合DeepSeek使用教程

Spring AI 结合DeepSeek使用教程 一、环境搭建与项目初始化 创建Spring Boot项目 使用IDEA或Spring Initializr创建项目&#xff0c;选择JDK 17或更高版本&#xff08;推荐21&#xff09;。勾选依赖项&#xff1a;Spring Web、Lombok&#xff0c;Maven或Gradle作为构建工具。添…

Android 布局优化:掌握 <include> 与 <merge> 的实战技巧

引言 在 Android 开发中&#xff0c;布局文件是 UI 设计的核心载体&#xff0c;但随着项目复杂度增加&#xff0c;布局冗余、嵌套层级过深等问题会导致性能下降。本文将通过 代码级实战示例&#xff0c;详细解析如何利用 <include> 和 <merge> 标签优化布局&#…

【storage】

文章目录 1、RAM and ROM2、DRAM and SRAM2、Flash Memory&#xff08;闪存&#xff09;4、DDR and SPI NOR Flash5、eMMC6、SPI NOR vs SPI NAND vs eMMC vs SD附录——prototype and demo board附录——U盘、SD卡、TF卡、SSD参考 1、RAM and ROM RAM&#xff08;Random Acce…

Python异步编程-协程

1、引言 在使用多个爬虫脚本进行数据爬取和调用大语言模型返回结果的场景中&#xff0c;涉及到大量的网络IO操作。协程能够让网络IO操作并发执行&#xff0c;极大地提升程序的运行效率。在智能体相关的开源项目中&#xff0c;我们也可以经常看到协程的身影。 2、协程 协程&a…

大语言模型提示词(LLM Prompt)工程系统性学习指南:从理论基础到实战应用的完整体系

文章目录 前言&#xff1a;为什么提示词工程成为AI时代的核心技能一、提示词的本质探源&#xff1a;认知科学与逻辑学的理论基础1.1 认知科学视角下的提示词本质信息处理理论的深层机制图式理论的实际应用认知负荷理论的优化策略 1.2 逻辑学框架下的提示词架构形式逻辑的三段论…

Android音频开发:Speex固定帧与变长帧编解码深度解析

引言 在Android音频开发领域&#xff0c;Speex作为一种开源的语音编解码器&#xff0c;因其优秀的窄带语音压缩能力被广泛应用。在实际开发中&#xff0c;帧处理策略的选择直接影响着音频传输质量、带宽占用和系统资源消耗。本文将深入探讨Speex编解码中固定帧与变长帧的实现差…

Docke启动Ktransformers部署Qwen3MOE模型实战与性能测试

docker运行Ktransformers部署Qwen3MOE模型实战及 性能测试 最开始拉取ktransformers:v0.3.1-AVX512版本&#xff0c;发现无论如何都启动不了大模型&#xff0c;后来发现是cpu不支持avx512指令集。 由于本地cpu不支持amx指令集&#xff0c;因此下载avx2版本镜像&#xff1a; …

算术操作符与类型转换:从基础到精通

目录 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符&#xff1a;、-、*、/、% 赋值操作符&#xff1a;和复合赋值 单⽬操作符&#xff1a;、--、、- 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 在先前的文…

飞腾D2000,麒麟系统V10,docker,ubuntu1804,小白入门喂饭级教程

#下载docker Index of linux/static/stable/ 根据电脑的CPU类型选择&#xff1a; Intel和AMD选x86_64飞腾D2000选aarch64 #选择较新的版本 #在包含下载的docker-XX.X.X.tgz的文件夹中右键->打开终端 # 解压安装包&#xff08;根据实际下载的文件&#xff09; tar -zxvf …

启程:为何选择PHP?

一、写在前面&#xff1a;小公司的生存逻辑与我的困惑 我是一名在小型软件开发公司工作的Java全栈开发者。我们这类团队的现实很直白&#xff1a;接不到“大单子”&#xff0c;日常围绕各类中小项目——企业官网、内部管理系统、定制化小程序——展开。客户预算有限、交付周期…

学习使用YOLO的predict函数使用

YOLO的 result.py #2025.1.3 """ https://docs.ultralytics.com/zh/modes/predict/#inference-arguments 对yolo 目标检测、实例分割、关键点检测结果进行说明https://docs.ultralytics.com/reference/engine/results/#ultralytics.engine.results.Masks.xy 对…

Node.js: express 使用 Open SSL

OpenSSL是一个开源的核心加密工具包&#xff0c;提供行业标准的加密&#xff0c;证书管理和安全通信功能。包含完整的 SSL/TLS 协议实现&#xff0c;被广泛应用于构建互联网安全基础设施。 在 express 中使用 openssl 通常是为了实现 HTTPS 通信&#xff0c;通过 SSL/TLS 加密来…

AI赋能的浏览器自动化:Playwright MCP安装配置与实操案例

以下是对Playwright MCP的简单介绍&#xff1a; Playwright MCP 是一个基于 Playwright 的 MCP 工具&#xff0c;提供浏览器自动化功能不要求视觉模型支持&#xff0c;普通的文本大语言模型就可以通过结构化数据与网页交互支持多种浏览器操作&#xff0c;包括截图、点击、拖动…

【Matlab】连接SQL Server 全过程

文章目录 一、下载与安装1.1 SQL Server1.2 SSMS1.3 OLE DB 驱动程序 二、数据库配置2.1 SSMS2.2 SQL Server里面设置2.3 设置防火墙2.4 设置ODBC数据源 三、matlab 链接测试 一、下载与安装 微软的&#xff0c;所以直接去微软官方下载即可。 1.1 SQL Server 下载最免费的Ex…

Java编程中常见的条件链与继承陷阱

格式错误的if-else条件链 典型结构与常见错误模式 在Java编程中,if-else条件链是一种常见的多条件处理模式,其标准结构如下: if (condition1) {// 处理逻辑1 } else if (condition2) {// 处理逻辑2 } else

scss(sass)中 的使用说明

在 SCSS&#xff08;Sass&#xff09;中&#xff0c;& 符号是一个父选择器引用&#xff0c;它代表当前嵌套规则的外层选择器。主要用途如下&#xff1a; 1. 连接伪类/伪元素 scss 复制 下载 .button {background: blue;&:hover { // 相当于 .button:hoverbackgrou…

C++ 信息学奥赛总复习题答案解析

第一章 答案解析 填空题 .cpp 知识点&#xff1a;C 源文件的命名规范 main () 知识点&#xff1a;C 程序的入口函数 // &#xff0c;/* */ 知识点&#xff1a;C 注释的两种形式 int a; 知识点&#xff1a;变量声明的语法 cout 知识点&#xff1a;输出语句的关键字 判断题…

Jenkins持续集成CI,持续部署CD,Allure报告集成以及发送电子 邮件

文章目录 一、Jenkins 的简介二、Jenkins的安装三、Jenkins 文件夹的作用四、Jenkins 的应用新建 job配置 jobjenkins 集成 Allure 报告。jenkins 集成 HTML 的报告 五、Jenkins 发送电子邮件1&#xff09;安装插件&#xff1a;Email Extension2&#xff09;开启 POP3/SMTP 服务…

算术图片验证码(四则运算)+selenium

一、表达式解析 这里假设已经识别出来表达式&#xff0c;如何识别验证码图片里的表达式&#xff0c;放在下面讲。涉及到的正则表达式的解析放在本篇文章最后面。 import re # 表达式解析&#xff08;支持小数的 -*/ 和中文运算符&#xff09; def parse_math_expression(text)…

使用 Laravel 中的自定义存根简化工作

在开发与外部服务、API 或复杂功能交互的应用程序时&#xff0c;测试几乎总是很困难。简化测试的一种方法是使用存根类。以下是我通常使用它们的方法。 福利简介 存根是接口或类的伪实现&#xff0c;用于模拟真实服务的行为。它们允许您&#xff1a; 无需调用外部服务即可测试…