selenium学习笔记(二)
文章目录
- 前言
- 设计模式POM
- POM概念
- POM优势
- POM设计原则
- POM的实现
- selenium的常用操作
- 处理动态元素
- 截图操作
- 勾选复选框
- 多层框架/窗口定位
- 操作下拉框
- 上传文件操作
- 处理弹窗
- 切换窗口
- 拖拽操作
- 如何处理浏览器驱动更新导致的问题
- selenium与网站监控
- 监听网页内容变化
- 监控网络请求
- selenium 与性能测试
- 代码示例
- 常见的性能指标
- selenium与TestNG
- 常见面试题
- 原理相关
- 定位元素相关
- 操作相关
- 脚本稳定与优化类相关
前言
1、该文是为了做个笔记,在需要的时候可以方便查找,侵权可删
2、文中的代码均为java
3、回顾前文 selenium学习笔记(一)
设计模式POM
Page Object Model (POM)
将页面分解成独立的对象,每个对象代表一个页面或页面的一部分,有助于组织测试代码和提高可维护性
POM概念
页面对象模型是一种设计模式,它提倡将UI元素抽象成对象,并围绕这些对象组织测试代码。这一模式不仅提升了测试脚本的可读性和可维护性,还促进了代码的重用
POM优势
- 分离关注点:将测试逻辑与页面元素分离,使测试脚本更加清晰。
- 易于维护:页面变化时,只需修改对应的页面对象类,无需改动所有测试案例。
- 代码复用:页面对象可以在多个测试案例中重复使用,减少冗余代码。
- 提高可读性:通过将操作封装成方法,使得测试代码更加易于理解。
- 提高可维护性:减少测试脚本对页面结构变化的敏感度,提高测试代码的可维护性
POM设计原则
- 抽象每一个页面:为每个页面创建一个对应的页面对象类。
- 页面中元素不暴露:仅暴露操作元素的方法,隐藏元素的具体定位细节。
- 页面不应该有繁琐的继承关系:避免页面对象之间的复杂继承结构。
- 页面中不是所有元素都需要涉及到:只对核心业务元素进行建模。
- 把页面划分功能模块:在Page中实现这些功能方法
POM的实现
- 创建页面类:为每个页面创建一个类,该类包含页面的所有元素定位器和操作方法。
- 封装元素操作:在页面类中封装对元素的所有操作,如点击、输入文本等。
- 使用Page Factory:Selenium提供了Page Factory模式,可以进一步简化页面对象的创建和管理
selenium的常用操作
处理动态元素
使用显式等待 和 隐式等待来处理动态元素
-
1、使用WebDriverWait和Expected Conditions
动态元素往往是在页面加载完成后通过JavaScript动态生成的。使用WebDriverWait结合Expected Conditions可以等待元素在页面上可见或可点击后再进行操作
WebDriverWait wait = new WebDriverWait(driver, 10); wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("dynamicElement")));
-
2、根据部分属性值定位
如果元素的ID或class是动态生成的,可以使用XPath中的contains()、starts-with()和ends-with()函数来根据部分属性值定位元素
// 这样可以匹配ID中包含"auto-id"的元素,即使ID是动态生成的
driver.findElement(By.xpath(“//div[contains(@id, ‘auto-id’)]”)); -
3、根据相对关系定位
如果动态元素与其附近的父节点、子节点或兄弟节点有固定的相对关系,可以根据这些固定元素来定位动态元素
-
4、根据DOM顺序index定位
找到元素在DOM中的顺序索引,然后根据索引进行定位。这种方法可能不够稳定,如果可以,还是推荐使用其他方法
-
5、使用CSS选择器
CSS选择器提供了一种灵活的方式来定位元素,尤其是当元素的ID或class是动态生成时。例如,可以使用CSS属性选择器来定位元素
driver.findElement(By.cssSelector(“input[type=‘text’]”)); -
6、结合使用多种定位方法
在某些情况下,可以结合使用多种定位方法来提高定位的准确性和成功率。例如,可以先通过CSS选择器定位到一个父元素,然后再通过相对路径定位到其子元素
-
7、优化等待时间
动态元素的加载可能需要时间,因此合理设置等待时间是提高脚本稳定性的关键。避免使用硬编码的等待时间(如Thread.sleep),而是使用WebDriverWait来动态等待元素加载完成
截图操作
需要导入依赖包,如Commons IO,进行截图操作
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
//浏览器截图
private static void test11() throws InterruptedException, IOException {
WebDriver webDriver = new ChromeDriver();
webDriver.get("https://www.baidu.com/");
webDriver.findElement(By.cssSelector("#kw")).sendKeys("软件测试");
webDriver.findElement(By.cssSelector("#su")).click();
sleep(3000);
//强制转换进行截图以文件形式存储
File file = ((TakesScreenshot)webDriver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(file,new File("d://测试.png"));
}
勾选复选框
private static void page01() {
// 创建一个浏览器驱动
WebDriver webDriver = new ChromeDriver();
// 打开网页
webDriver.get("http://localhost:63342/Test/src/main/page/teste01.html?_ijt=bbsd02k86b9564t8p03vfmeff1&_ij_reload=RELOAD_ON_SAVE");
// 获取到所有的input标签对应的元素
List<WebElement> webElements = webDriver.findElements(By.cssSelector("input"));
// 判断每一个input标签里面type值是checkbox进行点击,否则不点击
for(int i = 0; i < webElements.size(); i++) {
if(webElements.get(i).getAttribute("type").equals("checkbox")) {
webElements.get(i).click();
}
}
}
多层框架/窗口定位
对于一个web 应用,经常会出现框架(iframe) 或窗口(window)的应用,这样如果我们定位元素就不能直接右击copy他的xpath或者是cssselector来定位;但是可以通过switchTo()方法定位到frame下或者window下,然后通过元素css选择器或者xpath定位
private static void page02() {
// 创建浏览器驱动
WebDriver webDriver = new ChromeDriver();
// 打开网页
webDriver.get("http://www.xxx.com");
// 需要先定位到frame下再定位到click
webDriver.switchTo().frame("f1");
webDriver.findElement(By.cssSelector("body > div > div > a")).click();
// 目标元素不在iframe,可以直接获取
// String h3_text = webDriver.findElement(By.cssSelector("body > div > div > h3")).getText();
// System.out.println(h3_text);
}
操作下拉框
下拉框里的内容需要进行两次定位,先定位到下拉框对下拉框进行操作后,再定位到下拉框内里的选项
private static void page03() {
// 创建浏览器驱动
WebDriver webDriver = new ChromeDriver();
// 打开网页
webDriver.get("http://url地址");
// 操作下拉框
Select select = new Select(webDriver.findElement(By.cssSelector("#ShippingMethod")));
// select.selectByValue("12.51");
select.selectByIndex(2);
}
上传文件操作
在selenium webdriver 只要定位上传按钮,通过sendKeys 添加本地文件路径就可以了。
绝对路径和相对路径都可以,关键是上传的文件存在
private static void page05() {
WebDriver webDriver = new ChromeDriver();
webDriver.get("http://url地址");
// 找到按钮(上传文件的按钮),输入一个字符串
webDriver.findElement(By.cssSelector("input")).sendKeys("C:\Users\34085\Desktop\hello.txt");
}
处理弹窗
使用Alert类来处理弹窗:
1.text 返回alert 中的文字信息。
2.accept 点击确认按钮。
3.dismiss 点击取消按钮,如果有的话。
4.sendKeys 输入值,如果alert 没有对话框就不能用了,不然会报错。
private static void page04() throws InterruptedException {
WebDriver webDriver = new ChromeDriver();
webDriver.get("http://url地址");
webDriver.findElement(By.cssSelector("button")).click();
// alert弹窗确定
// webDriver.switchTo().alert().accept();
// alert弹窗取消
// webDriver.switchTo().alert().dismiss();
webDriver.switchTo().alert().sendKeys("你好");
webDriver.switchTo().alert().accept();
}
切换窗口
获取当前窗口句柄并切换到新窗口
// 进入百度页面然后点击新闻进入新闻页面,此时如果我们需要在新闻页面输入相关内容,是不能直接通过选择器定位实现的
// 我们需要先实现页面切换才能在新闻页面搜索内容
//浏览器切换窗口
private static void test10() throws InterruptedException {
WebDriver webDriver = new ChromeDriver();
webDriver.get("https://www.baidu.com/");
//点击新闻页面,在新闻面输入相关信息
webDriver.findElement(By.cssSelector("#s-top-left > a:nth-child(1)")).click();
//getWindowHandles获得所有窗口句柄
//getWindowHandle获取get打开的窗口句柄
// 获取到浏览器所有的窗口句柄
Set<String> handles = webDriver.getWindowHandles();
//遍历所有的窗口句柄
String target_handle = "";
for(String handle:handles) {
//赋值
target_handle = handle;
}
//System.out.println(target_handle);
//在新闻页面搜索新闻联播
webDriver.switchTo().window(target_handle);
sleep(3000);
webDriver.findElement(By.cssSelector("#ww")).sendKeys("新闻联播");
webDriver.findElement(By.cssSelector("#s_btn_wr")).click();
}
拖拽操作
使用Actions类进行复杂的鼠标操作,如拖拽
from selenium.webdriver.common.action_chains import ActionChains
private static void test() {
WebDriver webDriver = new ChromeDriver();
webDriver.get("https://www.URL地址/");
element_to_drag = driver.find_element_by_id("source");
target_element = driver.find_element_by_id("target");
// 方法一:直接将源元素拖拽到目标元素上
actionsA = ActionChains(driver);
actionsA.drag_and_drop(element_to_drag, target_element).perform();
// 方法二:模拟了更细致的拖拽过程,包括按住源元素(click_and_hold)、移动到目标元素位置(move_to_element)、然后释放(release)
actionsB = ActionChains(driver)
actionsB.click_and_hold(element_to_drag).move_to_element(target_element).release().perform()
}
如何处理浏览器驱动更新导致的问题
- 1、确保webdriver与浏览器版本匹配
- 2、手动下载WebDriver并使用Selenium的Service类来加载。这样可以控制WebDriver的版本,避免自动更新带来的问题
- 3、在代码中添加异常处理逻辑,捕获TimeoutException并提供相应的错误信息和日志,以便进行问题定位和调试
- 4、定期更新selenium和webdriver
- 5、避免浏览器自动更新
- 6、在测试开始之前,确保浏览器是干净的,没有被其他扩展或插件干扰。如果浏览器崩溃或被关闭,可以考虑重启浏览器并重新运行测试
selenium与网站监控
监听网页内容变化
通过定期检查网页上特定元素的内容,可以监控网页内容的变化。例如,可以监控商品价格、库存状态或新闻更新等
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
// 这段代码会在指定的网页上查找价格元素,并检测其内容的变化。如果价格发生变化,它会输出新的价格。
// 我们可以结合邮件报警+定时任务,当价格有变动时,可以发送邮件
public class PriceWatcher {
public static void main(String[] args) throws InterruptedException {
System.setProperty("webdriver.chrome.driver", "chromedriver的地址");
WebDriver driver = new ChromeDriver();
driver.get("http://url地址");
String previousPrice = "";
while (true) {
WebElement priceElement = driver.findElement(By.id("price")); // 假设价格的ID是"price"
String currentPrice = priceElement.getText();
if (!currentPrice.equals(previousPrice)) {
System.out.println("价格变动: " + currentPrice);
previousPrice = currentPrice;
}
Thread.sleep(5000); // 每5秒检查一次
}
}
}
补充:如果是监控价格:
(1)可以将每次检查的价格存储到CSV文件或数据库中,以便进行历史价格分析。这可以通过在上述代码中添加文件写入逻辑来实现;
(2)发送通知,如集成邮件报警;
(3)添加异常处理
监控网络请求
Selenium可以结合BrowserMob Proxy或其他工具来监控网络请求。BrowserMob Proxy是一个开源的代理服务器,可以捕获HTTP请求和响应
import net.lightbody.bmp.BrowserMobProxy;
import net.lightbody.bmp.BrowserMobProxyServer;
import net.lightbody.bmp.client.ClientUtil;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import java.util.List;
// 这段代码通过BrowserMob Proxy捕获了浏览器的所有HTTP请求和响应,并打印了请求的URL和响应状态。
// 通过这些方法,Selenium不仅可以用于自动化测试,还可以用于网站监控,帮助开发者和测试人员及时发现和响应网站的变化。
public class MonitorHttpRequests {
public static void main(String[] args) {
// 启动BrowserMob Proxy
BrowserMobProxy proxy = new BrowserMobProxyServer();
proxy.start(0);
// 获取代理的地址
Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);
// 设置WebDriver的代理
ChromeOptions options = new ChromeOptions();
options.setProxy(seleniumProxy);
WebDriver driver = new ChromeDriver(options);
// 启动请求捕获
proxy.newHar("myHar");
// 导航到网页
driver.get("http://url地址");
// 获取请求数据
List<HarEntry> entries = proxy.getHar().getLog().getEntries();
for (HarEntry entry : entries) {
System.out.println("请求网址: " + entry.getRequest().getUrl());
System.out.println("响应状态: " + entry.getResponse().getStatus());
}
// 关闭WebDriver与Proxy
driver.quit();
proxy.stop();
}
}
selenium 与性能测试
代码示例
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
// 配置性能日志记录
public class PerformanceTestSetup {
public static void main(String[] args) {
// 设置ChromeDriver路径
System.setProperty("webdriver.chrome.driver", "chromedriver路径");
// 创建ChromeOptions对象
ChromeOptions options = new ChromeOptions();
// 启用性能日志记录
options.setCapability("perfLoggingPrefs", "{\"enableNetwork\": true, \"enablePage\": true}");
// 将配置应用于WebDriver对象
WebDriver driver = new ChromeDriver(options);
// 打开网页
driver.get("http://example.com");
// 执行操作
// 关闭浏览器
driver.quit();
}
}
import org.openqa.selenium.logging.LogEntries;
import org.openqa.selenium.logging.LogEntry;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
// 获取并分析性能日志
public class PerformanceLogging {
public static void main(String[] args) {
// 设置WebDriver路径
System.setProperty("webdriver.chrome.driver", "path/to/chromedriver");
// 设置Chrome选项
ChromeOptions options = new ChromeOptions();
options.addArguments("--auto-open-devtools-for-tabs");
// 创建WebDriver实例
WebDriver driver = new ChromeDriver(options);
// 获取DevTools实例。 注意:以下代码需要Selenium 4及以上版本
org.openqa.selenium.devtools.DevTools devTools = ((ChromeDriver) driver).getDevTools();
devTools.createSession();
// 启动性能监控
devTools.send(org.openqa.selenium.devtools.v93.performance.Performance.enable());
// 访问目标页面
driver.get("http://example.com");
// 获取性能指标
LogEntries entries = driver.manage().logs().get(org.openqa.selenium.logging.LogType.PERFORMANCE);
for (LogEntry entry : entries) {
System.out.println(entry.getMessage());
}
// 关闭驱动
driver.quit();
}
}
常见的性能指标
- 响应时间(Response Time):客户端发送请求到接收到服务器响应的时间
- 吞吐量(Throughput):指系统在单位时间内能处理的事务或请求的数量。高吞吐量表明系统能够处理大量的请求
- 并发用户数(Concurrent Users):指系统能同时支持的最大用户数量( 这个指标对于理解系统在高负载下的表现非常重要)
- 事务处理速率(Transaction Rate):系统在单位时间内能完成的事务数量。事务可以是任何用户操作,如登录、查询、更新等
- 资源利用率(Resource Utilization):系统资源(如CPU/内存/磁盘I/O/网络带宽)的使用情况。高资源利用率可能表明性能瓶颈
- 错误率(Error Rate):指在一定时间内失败的事务或请求所占的比例。低错误率是系统稳定性的重要指标
- 页面加载时间(Page Load Time):对于Web应用,指从用户点击链接或输入网址到页面完全加载完成所需的时间
- 首次内容绘制(Time to First Contentful Paint, TTFCP):指页面开始加载到首次内容(如文本或图像)被渲染到屏幕上的时间
- 最大内容绘制(Time to Largest Contentful Paint, LTCP):指页面开始加载到最大文本块或图像被渲染到屏幕上的时间
- 交互时间(Time to Interactive, TTI):指页面加载到主要子资源加载完成,且页面能够快速响应用户输入的时间
- 总页面加载时间(Total Page Load Time):从用户开始导航到页面完全加载完成的时间
- 服务器响应时间(Server Response Time):服务器处理请求并返回响应所需的时间
- 网络时间(Network Time):数据在网络中传输的时间,包括请求和响应的往返时间
- 数据库响应时间(Database Response Time):数据库处理请求并返回结果所需的时间
- 系统稳定性(System Stability):在长时间运行或高负载下,系统是否能够保持性能和不出现故障
- 可扩展性(Scalability):系统在增加负载时,性能如何变化,以及是否能够通过增加资源来提高性能
selenium与TestNG
TestNG是一个测试框架,它支持各种测试场景,包括单元测试、集成测试、端到端测试等
-
1、添加依赖
<!-- Selenium --> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>3.141.59</version> </dependency> <!-- TestNG --> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>7.4.0</version> <scope>test</scope> </dependency>
-
2、创建测试类,并使用TestNG的注解来定义测试方法和测试套件
import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; public class SeleniumTestNGExample { private WebDriver driver; @BeforeMethod public void setUp() { // 设置WebDriver路径 System.setProperty("webdriver.chrome.driver", "path/to/chromedriver"); // 初始化WebDriver driver = new ChromeDriver(); } @Test public void testGoogleSearch() { // 打开Google首页 driver.get("https://www.baidu.com"); // 执行测试逻辑 } @AfterMethod public void tearDown() { // 关闭浏览器 driver.quit(); } }
-
3、运行测试
在命令行中运行:testng path/to/your/test-class/SeleniumTestNGExample.java
-
4、TestNG的高级功能
(1)@BeforeSuite 和 @AfterSuite:在测试套件开始前和结束后执行。
(2)@BeforeTest 和 @AfterTest:在每个测试类的所有测试方法执行前和执行后执行。
(3)@BeforeClass 和 @AfterClass:在同一个类中的所有测试方法执行前和执行后执行。
(4)@BeforeMethod 和 @AfterMethod:在每个测试方法执行前和执行后执行。
(5)@Test:标记一个方法为测试方法,可以指定测试的优先级、依赖关系等。
常见面试题
原理相关
-
介绍一下selenium及其工作原理
Selenium 是一个开源的自动化测试框架,专门用于Web应用程序的测试。它支持多种编程语言,如Java、C#、Python、Ruby等,并提供了不同的工具和库来模拟用户在浏览器中的交互行为
selenium的原理涉及到3个部分,分别是:浏览器、driver(一般我们都会下载driver)、client(也就是我们写的代码)
client其实并不知道浏览器是怎么工作的,但是driver知道,在selenium启动以后,driver其实充当了服务器的角色,跟client和浏览器通信,client根据webdriver协议发送请求给driver,driver解析请求,并在浏览器上执行相应的操作,并把执行结果返回给client。这就是selenium工作的大致原理。 -
selenium由哪些组件构成?常见的驱动有哪些
Selenium WebDriver:核心组件,用于编写浏览器自动化脚本,支持多种浏览器。
Selenium Grid:用于在不同机器和浏览器上并行运行测试。
Selenium IDE:Firefox插件,用于记录和回放用户操作,适合创建简单测试。
Page Object Model (POM):设计模式,用于组织和管理测试代码,提高可维护性FireFoxDriver ;InternetExplorerDriver ;ChromeDriver ;SafariDriver ;OperaDriver ;AndroidDriver
-
webdriver的协议是什么
client与driver之间的约定,无论client是使用java实现还是c#实现,只要通过这个约定,client就可以准确的告诉drier它要做什么以及怎么做。
webdriver协议本身是http协议,数据传输使用json -
selenium是如何驱动浏览器做各种操作的呢
1.对于每一条Selenium脚本,一个http请求会被创建并且发送给浏览器的驱动,最开始建立连接时服务端返回一个sessionid给客户端,后续的交互都是通过sessionid进行交互
2.浏览器驱动中包含了一个HTTP Server,用来接收这些http请求
3.HTTP Server接收到请求后根据请求来具体操控对应的浏览器
4.浏览器执行具体的测试步骤
5.浏览器将步骤执行结果返回给HTTP Server
6.HTTP Server又将结果返回给Selenium的脚本,如果是错误的http代码我们就会在控制台看到对应的报错信息。 -
selenium webdriver有什么优点
1.主流浏览器如Chrome、Firefox、IE、Safari等,可以在不同浏览器上运行和测试应用。
2.支持大多数语言,如Java,Python,Ruby,C#等。
3.Selenium提供了丰富的API可以根据测试需求进行扩展,实现定制化的测试用例。
4.Selenium可以很好地与Jenkins,测试管理工具等集成,实现自动化测试的持续集成和持续交付。 -
POM设计模式和page factory
page object:简单来说就是用class去表示被测页面。在class中定义页面上的元素和一些该页面上专属的方法。
Page Factory 实际上是官方给出的java page object的工厂模式实现 -
什么是Selenium Grid?
Selenium-Grid允许在不同的机器上针对不同的浏览器并行运行测试。也就是说,在不同的机器、不同的浏览器和操作系统上同时运行多个测试。本质上,Selenium-Grid支持分布式测试执行
-
举例Selenium中重载的方法
// 方法一:通过 iframe的索引值,在页面中的位置
driver.switchTo().frame(index);
// 方法二:通过 iframe 的name 或者id
driver.switchTo().frame(nameOrId);
// 方法三:通过iframe 对应的webElement
driver.switchTo().frame(frameElement); -
selenium是否支持桌面应用软件的自动化测试
不支持。selenium是根据网页元素的属性来确定范围元素的
定位元素相关
-
selenium中如何判断元素是否存在?
selenium中没有提供原生的方法判断元素是否存在,一般我们可以通过定位元素+异常捕获的方式判断
-
如何查找元素是否显示在屏幕上?
WebDriver通过isDisplayed(), isSelected(), isEnabled(),这三种方法判断Web元素的可见性,这类方法将返回结果是布尔类型;Web元素可以是按钮,下拉框,复选框,单选按钮,标签等。
①isDisplayed(): boolean b1 = driver.findElement(By.id(“XXX”)).isDisplayed();
②isSelected(): boolean b2 = driver.findElement(By.id(“XXX”)).isSelected();
③isEnabled(): boolean b3 = driver.findElement(By.id(“XXX”)).isEnabled(); -
selenium中hidden或者是display = none的元素是否可以定位到?
不可以,selenium不能定位不可见的元素。display=none的元素实际上是不可见元素
-
selenium自动化页面元素找不到存在异常的原因?
① 元素定位错误
② 页面加载时间过慢,需要查找的元素程序已经完成,单页面还未加载,此时可以加载页面等待时间
③ 有可能元素包含在iframe或者frame里面,需要切换。 -
selenium中如何保证操作元素的成功率?即如何保证我点击的元素一定是可以点击的?
1、当网速不好的情况下,使用合适的等待时间;
2、被点击的元素一定要占一定的空间,因为selenium默认会去点这个元素的中心点,不占空间的元素算不出来中心点;
3、被点击的元素不能被其他元素遮挡;
4、被点击的元素不能在viewport之外,也就是说如果元素必须是可见的或者通过滚动条操作使得元素可见;
5、判断元素是否是可以被点击的。 -
id,name,clas,xpath,css selector这些定位器,你最偏爱哪一种,为什么?
xpath和css最为灵活。id、name等需要开发支持
xpath定位时采用遍历页面的方式,性能指标较差。xpath定位有通过绝对路径定位的,有时会不准确;对于动态元素可以使用xpath
css选择器定位比较简洁,运行速度更快,通常用于性能要求严格的场景。 -
selenium为什么不推荐使用xpath定位?
selenium使用xpath定位时采用遍历页面的方式,性能指标较差。另外xpath定位有通过绝对路径定位的,有时会不准确;
而用css选择器定位比较简洁,运行速度更快,通常用于性能要求严格的场景。 -
如何判断一个页面上元素是否存在?
1、用try…except 在代码块加上
2、用elements定义组元素方法 然后根其元素个数len()<1 存在返回True, 不存在则返回False
3、结合WebDriverWait和excepted_conditions条件判断(强烈推荐) 显示等待,每间隔1秒判断一次,30秒超时,存在返回True,不存在则返回False -
一个元素明明定位了,点击无效(也没报错),如何解决?
使用js点击,selenium有时候点击元素时会失效
#js 点击
js = ‘document.getElementById(‘baidu’).click()’
driver.execute_script(js) -
selenium调用js(execute_script),有哪些场景?
① 对input执行输入 ② 对富文本框的操作 ③ 滚动到指定位置操作
-
如何去定位属性动态变化的元素?
属性动态变化是指该element没有固定的属性值,只能通过相对位置定位。
第一种方法:用findelements遍历
第二种方法:通过xpath的轴 parent / following-sibling / precent-sibling一个是属性动态,定位时,若id是动态的,就不要用id定位,用其他定位元素方法
另一个还是这个元素一会在页面上方,一会在下方,飘忽不定,定位方法也是一样,根据元素属性定位(元素的tag name属性是不会变的,动的只是class属性和style属性) -
如何通过子元素定位父元素?
第一种:通过子元素定位父元素,selenium提供了parent方法,但是只能定位到父元素,却不能获取元素属性,也不能操作。
第二种:通过xpath的语法直接定位。 如.//*[@name=”hello”]/… 两个点代表父级元素。 -
findElement和findElements有什么区别?
这两个方法都是WebDriver接口的抽象方法,用于在网页中查找元素。
findElemen():用于查找一个Web元素。它只返回一个WebElement类型。
findElements():用于查找多个Web元素。它返回WebElements集合。 -
selenium中隐藏元素定位,你该如何做?
隐藏元素可以正常定位到,只是不能操作(定位元素和操作元素是两码事,操作元素是指click 、clear 、send_keys等这些方法)。我们可以用js来操作隐藏元素。js和selenium不同,只有页面上有的元素(在dom里面的)都能正常操作。
操作相关
- 如何获取当前页面的url
driver.getCurrentUrl()
- 如何在webdriver中调用应用程序?
driver.get(‘url’) 或者 driver.navigate().to(‘url’)
- 如何使用WebDriver执行右键单击?
// contextClick方法用于模拟右键单击操作。perform方法用于执行链中存储的所有操作
Actions actions = new Actions(driver);
actions.contextClick(element).perform(); - 登录按钮除了click之外还有什么方法
使用submit()方法,但它只能在属性type=submit时使用
- 如何验证复选框/单选框是否被选中
driver.findElement(By.xpath(“元素路径”)).isSelected();
- 如何使用WebDriver执行拖放?
// dragAndDrop方法用于模拟从源元素拖放到目标元素的操作。perform方法用于执行链中存储的所有操作
Actions actions = new Actions(driver);
actions.dragAndDrop(sourceElement, targetElement).perform(); - selenium如何处理web弹窗?js弹窗?
使用driver.switch_to.alert()
- 如何从文本框中获取输入的文本?
String text = driver.findElement(By.xpath("元素路径 ")).getAttribute(“value”));
- 如何截取一个元素的图片,不要截取全部图片?
1、截取当前页面并自定义保存
2、根据要截取元素图片的属性来获取该元素的坐标和大小 ele.location ele.size
3、分别left = ele.location[‘x’] top = ele.location[‘y’] right = ele.location[‘x’] + ele.size[‘width’]
bottom = ele.location[‘y’] + ele.size[‘height’]
4、获取该元素的图片的坐标大小
5、再次打开刚开始保存的,通过image类中的crop方法(相当于拷贝该元素的一个矩形区域),然后做保存操作就可以了。 - 上传图片的几种方式?
send_keys和AutoIT工具实现.
- 截图应当怎么操作?
driver.get_screenshot_as_file(‘C:\test.jpg’)
脚本稳定与优化类相关
- 单斜杠和双斜杠有什么区别
/用于标识直接子节点
//用于在整个结构中查找 - Assert和Verify有什么区别?
Assert和Verify都是用于验证结果。如果测试用例失败,那么Assert将停止测试用例的执行,并且不再往下执行后续的测试步骤。
对于Verify如果测试用例失败,都不会停止当前的程序执行,并且所有测试步骤都将被执行到。 - 如何提高脚本的稳定性?
首先只要页面一直没变过,说明定位方法是没问题的。
优化方向:
① 自己写相对路径,多用id为节点查找,少用右键复制xpath,那种不稳定。
② 第二个影响因素就是等待了,sleep等待尽量少用(影响执行时间) 尽量使用显式等待
③ 定位元素方法重新封装,结合WebDriverWait和excepted_conditions判断元素方法,自己封装一套定位元素方法
④ 尽量使用测试专用环境,避免其他类型的测试同时进行,对数据造成干扰 - 如何提高selenium脚本的执行速度?
1、使用更高配置的电脑和选择更快的网络环境;
2、使用效率更高的语言,比如java执行速度就快过python;
3、优化代码;
4、不要盲目的加sleep,尽量使用显式等待;
5、可以考虑分布式执行(如,配置testNG实现多线程)或者使用selenium grid;
6、对于firefox,考虑使用测试专用的profile,因为每次启动浏览器的时候firefox会创建1个新的profile,对于这个新的profile,所有的静态资源都是从服务器直接下载,而不是从缓存里加载,这就导致网络不好的时候用例运行速度特别慢的问题;
7、chrome浏览器和safari浏览器的执行速度看上去是最快的。 - selenium自动化时,在平时遇到过哪些问题?如何解决的
动态id 、有iframe的情况、没加等待等因素
- selenium中常见的异常
NoSuchElementException - 元素未找到异常
ElementNotVisibleException - 元素不可见异常
ElementNotSelectableException - 元素不可选择异常
NoAlertPresentException - 未找到警报异常
NoSuchAttributeException - 未找到属性异常
NoSuchWindowException - 未找到窗口异常
TimeoutException - 超时异常
WebDriverException - WebDriver异常