文章目录
为什么要做自动化测试?
自动化测试就是将手工执行测试转变为使用代码来执行测试,自动化测试能够代替一部分手工测试,提高测试效率
,并且随着项目版本的更新,回归测试压力越来越大,可以借助自动化来进行回归测试
为什么选用Selenium?
Selenium是用来做Web自动化
的框架
selenium的特点:
- 支持多浏览器(Chrome,Firefox,Edge…)
- 支持多系统(Linux,Windows,Mac…)
- 支持多语言(Python,Java,C#…)
- 拥有丰富的API
Selenium的工作原理
总结: 我们的脚本代码会发送一个http请求到驱动,驱动解析请求后操作浏览器执行相对应的操作,待浏览器执行完相应的操作后,会将执行结果返回给驱动,驱动收到结果后,又将结果返回给脚本代码
Selenium+Java环境搭建
这里推荐使用Chrome
浏览器
先查看Chrome浏览器的版本
链接: Chrome驱动下载地址
点击上述链接下载对应的驱动版本,并将驱动放在jdk的bin目录
里
创建一个Maven项目,并添加selenium依赖
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.0.0</version>
</dependency>
验证环境是否搭建成功:
public class Test {
public static void main(String[] args) {
ChromeOptions options = new ChromeOptions();
//允许所有请求
options.addArguments("--remote-allow-origins=*");
WebDriver driver = new ChromeDriver(options);
driver.get("https://www.baidu.com"); //访问百度网址
driver.quit(); //退出浏览器
}
}
启动运行,发现代码会操作浏览器访问百度网址,说明环境搭建成功
Selenium常用API
浏览器参数配置
ChromeOptions options = new ChromeOptions(); //创建浏览器参数配置对象
options.addArguments("-headless"); //无头模式
options.addArguments("--remote-allow-origins=*");
ChromeDriver driver = new ChromeDriver(options);
无头模式不会在桌面打开浏览器
定位元素
定位元素的方式有以下方式:
- id
- name
- tag name
- class name
- css 选择器(#id,.class,input,…)
- XPath
- linkText(链接内容)
- partialLinkText(部分链接内容)
//获取到页面元素,对应的类型为WebElement
WebElement element = driver.findElement(By.cssSelector("#kw"));
driver.findElement(By.id("kw")); //通过id
driver.findElement(By.name("wd")); //通过name
driver.findElement(By.tagName("input")); //通过tag name,也就是标签名
driver.findElement(By.className("s_ipt")); //通过类名
driver.findElement(By.cssSelector("#kw")); //通过css选择器
driver.findElement(By.xpath("//*[@id=\"kw\"]")); //通过XPath
driver.findElement(By.linkText("新闻")); //通过超链接内容
driver.findElement(By.partialLinkText("123")); //通过超链接部分内容
操作测试对象
- sendKeys(“str”):向输入框输入内容
- click():模拟鼠标点击
- getText():获取元素的文本内容(首标签与尾标签之间的文本)
- clear():清除输入框输入内容
- submit():提交(只能用于form标签内的元素)
- getAttribute(“str”):获取标签属性值
element.sendKeys("庆余年"); //输入
element.click(); //点击
element.getText(); //获取元素的文本信息
element.clear(); //清除输入框内容
element.submit(); //提交
element.getAttribute("type"); //获取标签属性
时间等待
- 强制等待:Thread.sleep()
隐式等待
:driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3))- 显示等待:显示指定等待某一个元素的加载时间(
只作用于一条查询元素上
)
sleep(3000); //强制等待
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); //隐式等待3秒,作用于driver的整个生命周期
//显示等待
new WebDriverWait(driver,Duration.ofSeconds(3)).until(driver1->driver.findElement(By.cssSelector("#id")));
区别:
- 强制等待会一直等待设置的时间,程序阻塞执行,直到时间结束
- 隐式等待(
等待页面的所有元素都加载好
,),在等待的时间内,如果页面元素加载好了,就会提前结束等待(上述代码最多只等待3秒)
信息打印
- 打印title:getTitle()
- 打印url:getCurrentUrl()
String url = driver.getCurrentUrl(); //获取url
System.out.println(url);
String title = driver.getTitle(); //获取title
System.out.println(title);
对浏览器操作
关闭浏览器
driver.quit();
driver.close();
区别:
- quit关闭整个浏览器,close关闭当前页面
- quit会清除浏览器缓存,close不会清除缓存
浏览器窗口大小设置
- maximize():浏览器最大化
- minimize():浏览器最小化
- fullscreen():浏览器全屏
- setSize(new Dimension(int width,int height)):手动设置浏览器窗口大小
driver.manage().window().maximize(); //窗口最大化
driver.manage().window().minimize(); //窗口最小化
driver.manage().window().fullscreen(); //全屏
driver.manage().window().setSize(new Dimension(1024,600)); //手动设置大小,第一个参数为宽,第二个参数为高
浏览器窗口切换操作
浏览器打开新的标签页的时候,浏览器此时操作元素的时候,还是操作的是跳转之前的页面,如果想操作新打开的标签页面的元素,可进行如下操作
浏览器每次打开一个标签页的时候,会自动的给每个标签页进行标识(句柄
)
Set<String> handles = driver.getWindowHandles(); //获取所有标签的句柄
String curHandle = driver.getWindowHandle(); //获取当前页面(get打开)的句柄
for(String handle : handles){
if(!curHandle.equals(handle)){
//如果当前句柄与遍历的不相等
driver.switchTo().window(handle); //跳转过去
}
}
浏览器的前进后退
- back:浏览器后退
- forward:浏览器前进
- refresh:浏览器刷新
//浏览器的前进后退及刷新
driver.navigate().back(); //后退
driver.navigate().forward(); //前进
driver.navigate().refresh(); //刷新
//访问url除get外的别种写法
driver.navigate().to("https://www.baidu.com");
借助
js代码
操作浏览器滚动条
String js = "document.documentElement.scrollTop=10000"; //scrollTop为距浏览器顶部的距离
((JavascriptExecutor)driver).executeScript(js); //将driver强转为JavascriptExecutor
键盘与鼠标操作
键盘操作
driver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL,"A"); //ctrl+a
driver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL,"C"); //ctrl+c
driver.findElement(By.cssSelector("#kw")).sendKeys(Keys.CONTROL,"V"); //ctrl+v
driver.findElement(By.cssSelector("#kw")).sendKeys(Keys.ENTER); //回车
鼠标操作
WebElement element = driver.findElement(By.cssSelector("#kw")); //定位元素
Actions actions = new Actions(driver); //需要借助Actions,参数据传递浏览器驱动
actions.moveToElement(element).contextClick().perform(); //鼠标移动到元素上,右击
actions.moveToElement(element).doubleClick().perform(); //鼠标移动到元素上,双击
屏幕截图
先在pom.xml中添加依赖
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
截图保存
File file = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); //截图赋值给file
FileUtils.copyFile(file,new File("./0522.png")); //保存在硬盘
弹窗处理
弹窗的类型:
- 警告弹窗
- 确认弹窗
- 提示弹窗
弹窗不能使用定位元素的方式定位
操作弹窗的步骤:
- 将driver对象切换到弹窗上:driver.switchTo().alert()
- 进行确定,取消,输入,获取弹窗文本内容操作:
accept
,dismiss
,sendKeys("xxx")
,getText
//弹窗的处理
Alert alert = driver.switchTo().alert(); //定位到弹窗
alert.accept(); //确定
alert.dismiss(); //取消
alert.sendKeys("zs"); //输入
alert.accept(); //输入内容后需要确认
String alertText = alert.getText(); //获取弹窗文本内容
说明:
- 虽然警告弹窗只有确定按钮,但是accept和dismiss操作都可关闭弹窗
- 虽然警告和确认弹窗没有输入框,但是执行alert.sendkeys操作也不会报错
选择框的处理
- 根据文本选择selectByVisibleText
- 根据属性值选择selectByValue
- 根据序号选择selectByIndex
WebElement element = driver.findElement(By.cssSelector("body > select"));
Select select = new Select(element); //创建选择框对象
select.selectByVisibleText("深圳"); //根据文本选择
select.selectByValue("02"); //根据属性值选择
select.selectByIndex(1); //下标从0开始,1代表第二个
上传文件
//上传文件
WebElement element1 = driver.findElement(By.cssSelector("body > input[type=file]:nth-child(5)"));
element1.sendKeys("文件路径");
JUnit单元测试
JUnit是Java的
单元测试框架
,此处的版本是JUnit5
在pom.xml中添加JUnit的依赖
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.8.2</version>
<scope>test</scope>
</dependency>
注解
@Test
:加在方法上,表示该方法是一个测试用例@Disabled
:加在方法上,表示当前方法不参与测试用例的执行@BeforeEach
:表示当前方法在每个
用例执行前都会执行一次@BeforeAll
:表示当前方法(方法需用static
修饰)在所有
用例执行前执行一次@AfterEach
:表示当前方法在每个用例执行后都会执行一次@AfterAll
:表示当前方法(方法需用static
修饰)在所有用例执行完执行一次
在做UI自动化的时候,一般将驱动的创建,打开的url信息放到@BeforeAll方法里,将浏览器关闭的信息放到@AfterAll方法里
参数化
使用@ParameterizedTest
与@ValueSource
注解进行参数化的设置
单个参数
@ParameterizedTest
@ValueSource(ints = {
1,2,3})
void method2(int i){
System.out.println(i);
}
@ParameterizedTest
@ValueSource(strings = {
"zs","ls","ww"})
void method2(String s){
System.out.println(s);
}
多个参数
使用@CsvSource
,可以给多个参数类型传递参数
@ParameterizedTest
@CsvSource(value = {
"zs,5","li,6","wu,7"})
void method4(String name,int id){
System.out.println(id+":"+name);
}
CSV获取参数
如果参数的用例非常多,则可以将测试的参数放进csv文件中,然后通过csv文件获取参数(每个参数类型对应文件的一列数据,列与列之间用 ,
分割)
@ParameterizedTest
@CsvFileSource(files = "./dir/test01.csv") //文件路径
void method3(String name,int i){
System.out.println(name+":"+i);
}
打印结果:
方法获取参数
public class Test {
@ParameterizedTest
@MethodSource("test111")
void method1(String name,int id){
System.out.println(id+":"+name);
}
static Stream<Arguments> test111(){
return Stream.of(Arguments.arguments("zs",2),
Arguments.arguments("ls",3),
Arguments.arguments("wu",4));
}
}
用例的执行顺序
使用@TestMethodOrde
r与@Order
注解进行排序
//该注解表示当前类下所有的用例需要使用order注解来进行排序
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class Test04 {
@Order(1)
@Test
void test_m1(){
System.out.println("m1");
}
@Order(2)
@Test
void test_m2(){
System.out.println("m2");
}
@Order(3)
@Test
void test_m3(){
System.out.println("m3");
}
}
断言
-
Assertions.
assertEquals
(s1,s2):匹配才通过 -
Assertions.
assertNotEquals
(s1,s2):不匹配才通过 -
Assertions.
assertTrue
(条件):条件为真通过 -
Assertions.
assertFalse
(条件):条件为假才通过 -
Assertions.
assertNull
(xxx):xxx为null才通过 -
Assertions.
assertNotNull
(xxx):xxx不为null才通过
测试套件
通过class运行测试用例
@Suite
//先跑01.class,接着02.class,最后03.class
@SelectClasses({
Test01.class, Test02.class, Test03.class})
public class RunSuit {
}
通过包运行测试用例
@Suite
//先跑autotest1包,再跑autotest2包
@SelectPackages(value = {
"autotest1","autotest2"})
public class RunSuit1 {
}
文章评论