自动化测试就是将手工执行测试转变为使用代码来执行测试,自动化测试能够代替一部分手工测试,提高测试效率
,并且随着项目版本的更新,回归测试压力越来越大,可以借助自动化来进行回归测试
Selenium是用来做Web自动化
的框架
selenium的特点:
总结: 我们的脚本代码会发送一个http请求到驱动,驱动解析请求后操作浏览器执行相对应的操作,待浏览器执行完相应的操作后,会将执行结果返回给驱动,驱动收到结果后,又将结果返回给脚本代码
这里推荐使用Chrome
浏览器
先查看Chrome浏览器的版本
链接: Chrome驱动下载地址
点击上述链接下载对应的驱动版本,并将驱动放在jdk的bin目录
里
创建一个Maven项目,并添加selenium依赖
<dependency>
<groupId>org.seleniumhq.seleniumgroupId>
<artifactId>selenium-javaartifactId>
<version>4.0.0version>
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(); //退出浏览器
}
}
启动运行,发现代码会操作浏览器访问百度网址,说明环境搭建成功
ChromeOptions options = new ChromeOptions(); //创建浏览器参数配置对象
options.addArguments("-headless"); //无头模式
options.addArguments("--remote-allow-origins=*");
ChromeDriver driver = new ChromeDriver(options);
无头模式不会在桌面打开浏览器
定位元素的方式有以下方式:
//获取到页面元素,对应的类型为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")); //通过超链接部分内容
element.sendKeys("庆余年"); //输入
element.click(); //点击
element.getText(); //获取元素的文本信息
element.clear(); //清除输入框内容
element.submit(); //提交
element.getAttribute("type"); //获取标签属性
隐式等待
: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秒)String url = driver.getCurrentUrl(); //获取url
System.out.println(url);
String title = driver.getTitle(); //获取title
System.out.println(title);
关闭浏览器
driver.quit();
driver.close();
区别:
浏览器窗口大小设置
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); //跳转过去
}
}
浏览器的前进后退
//浏览器的前进后退及刷新
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中添加依赖
<dependency>
<groupId>commons-iogroupId>
<artifactId>commons-ioartifactId>
<version>2.6version>
dependency>
截图保存
File file = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); //截图赋值给file
FileUtils.copyFile(file,new File("./0522.png")); //保存在硬盘
弹窗的类型:
弹窗不能使用定位元素的方式定位
操作弹窗的步骤:
accept
,dismiss
,sendKeys("xxx")
,getText
//弹窗的处理
Alert alert = driver.switchTo().alert(); //定位到弹窗
alert.accept(); //确定
alert.dismiss(); //取消
alert.sendKeys("zs"); //输入
alert.accept(); //输入内容后需要确认
String alertText = alert.getText(); //获取弹窗文本内容
说明:
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是Java的
单元测试框架
,此处的版本是JUnit5
在pom.xml中添加JUnit的依赖
<dependency>
<groupId>org.junit.jupitergroupId>
<artifactId>junit-jupiterartifactId>
<version>5.8.2version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.junit.platformgroupId>
<artifactId>junit-platform-suiteartifactId>
<version>1.8.2version>
<scope>testscope>
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 {
}