什么是selenium
比较官方的解释
Selenium是一个自动化测试工具,用于在Web应用程序中模拟用户操作。它提供了一组API,可以通过编程方式控制浏览器,并模拟用户的交互行为,例如点击、输入文本和导航等。Selenium支持多种编程语言,包括Java、C#、Python、Ruby、JavaScript等,并可以在多个浏览器和操作系统上运行测试。Selenium的目标是帮助测试人员自动化测试过程,提高测试效率和测试质量。
个人的简单理解
- 浏览器驱动可以操作浏览器,不用selenium也能实现代码控制浏览器的效果,就是需要自己查询浏览器启动提供的功能,
- selenium可以看成是浏览器驱动的工具类,在项目中引入seleniu,就能通过selenium方便的操作浏览器
用途
- 自动化测试
- 爬虫
Java环境搭建
下载浏览器和对应的浏览器驱动器
浏览器和浏览器驱动版本要保持一致(一般前三位一致即可),浏览器和对应的驱动见附件
开启浏览器debug端口
连接到已打开的浏览器,需要浏览器开启debug端口,简单的开启方法如下
-
为chrome.exe创建一个快捷方式
-
chrome.exe创建>>右键>>属性>>目标后面添加
--remote-debugging-port=9222
(注意chrome.exe与新加内容之间有个空格,端口可以自由定义) -
此时双击chrome快捷打开浏览器默认会开启debug端口
-
检查浏览器是否开启了debug端口,访问http://localhost:9222/json,返回以下内容说明浏览器成功开启了debug端口,9222是自定义端口
[ {
"description": "",
"devtoolsFrontendUrl": "/devtools/inspector.html?ws=localhost:9222/devtools/page/B3C592C54EB3552A0F5D76706A6EF844",
"id": "B3C592C54EB3552A0F5D76706A6EF844",
"title": "emp",
"type": "page",
"url": "http://localhost:8080/",
"webSocketDebuggerUrl": "ws://localhost:9222/devtools/page/B3C592C54EB3552A0F5D76706A6EF844"
} ]
引入依赖
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
Selenium测试代码
public class SeleniumTest {
private WebDriver driver;
private WebDriverWait wait;
@SneakyThrows
@Before
public void toChrome() {
connectExistingChrome();
// 访问指定的 URL
driver.navigate().to("http://localhost:8080");
}
@Test
public void hello() {
// 使用显示等待 循环寻找input,如果5秒内找到则返回,如果5秒内未找到则抛出异常
// WebElement nameInput = driver.findElement(By.xpath("/html/body/div[1]/form/div[1]/div/div/input"));
WebElement nameInput = wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("/html/body/div[1]/form/div[1]/div/div/input")));
// 元素操作(WebElement 相关api)
nameInput.sendKeys("张无忌");
/*
* 如果页面相对固定,可以用xpath寻找元素,xpath可以通过浏览器直接复制,详细步骤可参考笔记
* 如果页面变动频繁可以通过tagName找到所有的元素,然后再通过指定属性过滤
*/
List<WebElement> buttons = driver.findElements(By.tagName("button"));
WebElement queryButton = buttons.stream().filter(item -> "查询".equals(item.getText())).findFirst().get();
queryButton.click();
}
/**
* 显示等待
* TimeoutException: Expected condition failed: waiting for presence of element located by: By.id: absentId (tried for 30 second(s) with 500 milliseconds interval)
*/
@Test
public void webDriverWaitTest(){
System.out.println(System.currentTimeMillis());
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("absentId")));
System.out.println(System.currentTimeMillis());
}
/**
* 隐式等待
* NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"#absentId"}
*/
@Test
public void implicitlyWaitTest(){
System.out.println(System.currentTimeMillis());
driver.findElement(By.id("absentId"));
System.out.println(System.currentTimeMillis());
}
/**
* 连接到已经存在的浏览器
* 这里直接连接已经打开的浏览器,不让浏览器启动器新打开窗口,好处如下
* 1. 退出浏览器驱动时不会退出我们已经打开的浏览器网页窗口
* 2. 自己打开的里面有登录的身份信息,新打开的可能没有身份信息,需要登录
* 连接已打开的浏览器需要浏览器开启debug端口,具体开启方法见文档
*/
private void connectExistingChrome() {
// 设置 ChromeDriver 的路径
System.setProperty("webdriver.chrome.driver", "C:\\118.0.5993.70\\chromedriver-win64\\chromedriver.exe");
// 配置 ChromeOptions
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("debuggerAddress", "localhost:9222");
// 创建 ChromeDriver 实例
driver = new ChromeDriver(options);
// 隐式等待(全局等待):每隔一段时间循环寻找元素,如果3秒内找到则返回元素,找不到则抛异常
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
// 显示等待器:如果超时就会抛出异常NoTouchElementException
wait = new WebDriverWait(driver, 30);
}
/**
* 打开一个新浏览器窗口
*/
public void openNewChrome() {
// 设置 ChromeDriver 的路径
System.setProperty("webdriver.chrome.driver", "C:\\118.0.5993.70\\chromedriver-win64\\chromedriver.exe");
// 配置 ChromeOptions
ChromeOptions options = new ChromeOptions();
// 指定特定版本的 Chrome 浏览器路径 浏览器版本和浏览器驱动版本要保持一致(一般前三位一致即可)
options.setBinary("C:\\118.0.5993.70\\chrome-win64\\chrome.exe");
// 可选:无头模式,不打开浏览器窗口 如果做爬虫不打开浏览器某些网站过不去,可能会遇到Enable JavaScript and cookies to continue
// options.addArguments("--headless");
// 解决一些系统的图形化渲染问题
options.addArguments("--disable-gpu");
// 在某些系统上需要添加此参数
options.addArguments("--no-sandbox");
// 解决资源共享内存的问题
options.addArguments("--disable-dev-shm-usage");
// 创建 ChromeDriver 实例
driver = new ChromeDriver(options);
// 为浏览器驱动driver创建一个等待器,循环等待,直到条件达成或者超时,如果条件未达成超时就会跑出异常
wait = new WebDriverWait(driver, 30);
}
@SneakyThrows
@After
public void closeChrome() {
// 退出浏览器驱动程序
driver.quit();
}
}
这里直接连接已经打开的浏览器,不让浏览器驱动器新打开窗口,好处如下
- 退出浏览器驱动时不会退出我们已经打开的浏览器网页窗口
- 浏览器驱动器打开的新窗口可能没有身份信息,需要登录
获取Xpath技巧
- 如果页面元素相对比较固定,可以直接用xpath定位,简单直接,xpath可以直接从浏览器赋值
复制出来的xpath直接粘贴到代码里即可
/html/body/div[2]/div[1]/div/div[1]/div/div/div[1]/div/form/div[2]/div/div[1]/div[1]/textarea
如果前端页面频繁更新,页面元素位置经常变动,就不太适合这种方式了
- 如果页面元素经常变动,但是提示语或者某些属性比较固定,可以拿到所有这个类型的元素,再根据固定的属性过滤
List<WebElement> textareaList = driver.findElements(By.tagName("textarea"));
for (WebElement textarea : textareaList) {
String placeholder = textarea.getAttribute("placeholder");
if (placeholder.contains("内容概要+适用人群+使用场景及目标+其他说明")) {
// 拿到了资源描述文本框
}
}
常用方法
// 请求一个页面,不支持前进和后退切换
driver.get(url);
// 和get类似,支持前进和后退切换
driver.navigate().to(url);
// 退到上一个页面 ,前提必须前进了一个页面才能回退
driver.navigate().back();
// 指前进到下一个页面 ,前提是必须后退后才能前进
driver.navigate().forward();
// 刷新当前页面
driver.navigate().refresh();
// 通用搜索,第一个 , By里包含常用的各种搜索
WebElement findElement(By by);
// 通用搜索,多个,By里包含常用的各种搜索
List<WebElement> findElements(By by);
// 关闭当前窗口,如果它是当前打开的最后一个窗口,则退出浏览器。
driver.close();
// 退出此驱动程序,关闭每个相关窗口。
driver.quit();
WebElement常用方法
元素定位
- 根据id定位
- 根据a标签内容定位
- 根据a标签内容模糊定位
- 根据name属性定位
- 根据标签名字定位
- 根据路径匹配
- 根据类名定位
- 根据css选择器定位
元素操作
- click():点击该元素。
- submit():将表单提交到该元素所在的表单。
- sendKeys(CharSequence… keysToSend):将指定的字符序列发送到该元素。例如向输入框输入文本。
- clear():清除该元素的内容。
- getTagName():获取该元素的标签名称。
- getAttribute(String name):获取该元素指定属性的值。
- getText():获取该元素的文本内容。
- isEnabled():判断该元素是否可用。
- isSelected():判断该元素是否被选中。
- isDisplayed():判断该元素是否可见。
- getLocation():获取该元素在页面中的位置。以
Point
对象表示,包含x
和y
坐标。 - getSize():获取该元素的大小,以
Dimension
对象表示,包含width
和height
。 - getCssValue(String propertyName):获取该元素指定CSS属性的值。
等待机制
- 显示等待
- 隐式等待
显示等待与隐式等待的区别
-
显示等待是指在代码中明确指定等待条件和等待时间,直到条件成立或等待时间到期,程序才会继续执行下一步操作。显示等待可以根据不同的条件进行等待,例如元素的可见性、可点击性、文本内容、属性值等。显示等待可以通过ExpectedConditions类来实现。
-
隐式等待是指在代码中设置一个全局等待时间,在此时间内如果元素没有立即出现,程序将等待指定的时间,等待元素出现。隐式等待适用于整个测试用例,而不是针对某个特定的元素。隐式等待可以通过WebDriver.Timeouts.implicitlyWait()方法来设置。。
selenium实战
基于selenium的crud
- 启动项目
- crud详见代码com.study.selenium.EmpCRUDTest
- 效果见演示视频
码云地址
https://gitee.com/LessAndfaster/study-selenium.git
在线笔记
https://blog.csdn.net/weixin_41883161/article/details/139270612