Web自动化测试(Java语言)
UI自动化的价值
- 回归测试
- 兼容性测试
自动化测试工具选型
框架名称 | 支持语言 | 支持浏览器 | 是否可录制 | 费用 | 入门成本 | IDE | 优缺点 |
---|---|---|---|---|---|---|---|
selenium | 多语言 | 多浏览器 | 支持 | 开源免费 | 中 | selenium IDE | 开源免费,多语言,跨平台,比较重,需要掌握一门编程语言 |
QTP | vbscript | IE、火狐 | 支持 | 商业收费(无限试用) | 易 | UFT | http://www.51testing.com/html/35/n-863435.html |
watir | Ruby | 多浏览器 | 不支持 | 开源免费 | 难 | ruby代码库,无IDE | 小巧灵活、收费、学习成本高 |
sahi | 多语言 | 多浏览器 | 支持 | 开源收费(有免费版) | 难 | Twist | https://sahipro.com/sahi-vs-selenium/ |
- 使用selenium的优势主要是:开源免费、跨语言、跨平台
Selenium介绍
是一个用于Web应用程序测试的工具,直接运行在浏览器中,模拟真实用户操作。
- Selenium 1(又叫Selenium RC或遥控器),需要Selenium RC启动一个Server,将操作Web元素的API调用转化为一段段Javascript,在Selenium内核启动浏览器之后注入这段Javascript。这种Javascript注入技术的缺点是速度不理想,而且稳定性大大依赖于Selenium内核对API翻译成的Javascript质量高低。Selenium 1已被弃用。
- Selenium 2(又叫Selenium WebDriver),是Selenium和WebDriver这两个项目合并而成,主要新功能是集成WebDriver API。除了解决Selenium-RC API中的一些限制之外,WebDriver还旨在提供更简单,更简洁的编程接口。由于使用的是浏览器原生的API,速度大大提高,而且调用的稳定性交给了浏览器厂商本身.然而带来的一些副作用就是,不同的浏览器厂商,对Web元素的操作和呈现多少会有一些差异,这就直接导致了Selenium WebDriver要分浏览器厂商不同,而提供不同的实现。
-
Selenium原理
- 以脚本作为客户端,运行Webdriver.chrome(),启动浏览器作为客户端,并监听对应端口,创建session
- 执行脚本,向浏览器发送HTTP请求,浏览器解析请求作出相应操作,并返回response
环境搭建
IDEA+Maven+selenium+TestNG
-
Java IDE搭建
-
JDK下载: https://www.oracle.com/technetwork/java/javase/downloads/index.html
-
Interlij IDEA下载(社区版是免费的):http://www.jetbrains.com/idea/download/
-
-
Maven下载:
- 官网:https://maven.apache.org/download.cgi
- 配置环境变量:
vim ~/.bash_profile
- 添加下面两行到.bash_profile文件中
# 配置maven export MAVEN_HOME=/Users/leitianxiao/Documents/software/apache-maven-3.6.1 export PATH=$PATH:$MAVEN_HOME/bin`
source ~/.bash_profile
-
selenium搭建
- 使用maven自动下载selenium的jar包,pom.xml添加依赖
<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>3.141.59</version> </dependency>
-
TestNG
- 使用maven自动下载TestNG的jar包,pom.xml添加依赖
<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.14.3</version> <scope>test</scope> </dependency>
浏览器及浏览器驱动
Chrome浏览器+Chrome浏览器驱动
-
查看浏览器版本
地址栏中输入chrome://version
可快速查看浏览器版本 -
对应浏览器版本的浏览器驱动下载
国内镜像网站:https://npm.taobao.org/mirrors/chromedriver
前置知识-HTML、CSS
- 元素
- 按钮、文本输入框、单选框、复选框、链接……
- 属性
- id、name、class、href、style……
- DOM树
- CSS
- chrome的inspect工具-DOM分析工具,可以查看每个控件的属性是什么,依靠这些属性来进行定位元素(可通过F12-Element或鼠标右键-检查呼出)
Demo演示
- 使用IDEA新建一个Maven项目+添加selenium、TestNG的依赖
- 下载Chrom浏览器的对应驱动,放在项目文件下
src/main/resources/driver/
目录下 - 模拟用户操作步骤:
- 启动浏览器
- 输入网址,打开网页
- 找到要操作的元素
- 进行操作:清空/输入/点击等
- 关闭浏览器
public class FirstDemo {
public static void main(String[] args) {
//设置系统变量(浏览器驱动名称,相对路径)
System.setProperty("webdriver.chrome.driver","src/main/resources/driver/chromedriver");
//实例化WebDriver,启动浏览器
WebDriver driver = new ChromeDriver();
//在浏览器中输入网址,并打开网页
driver.get("https://www.jianshu.com/");
//找到要操作的元素,该元素的id是sign_up
WebElement welcome =driver.findElement(By.id("sign_up"));
//点击该元素
welcome.click();
//关闭浏览器
driver.quit();
//关闭浏览器驱动
driver.close();
}
}
元素定位基础
通过id定位
- driver.findElement(By.id("sign_up"));
- id是整个页面唯一的,不会重复
通过name定位
- driver.findElement(By.name("q"));
- name一般用在服务端
通过classname定位
- driver.findElement(By.className("search-btn"));
- class一般用来设置样式
通过linkText定位
- linkText即
<a>
链接标签里的文本 - driver.findElement(By.linkText("登录"));
WebDriver基础API
动作-无返回值
- clean 清空
- click 点击
- sendKeys 输入文本
获取属性值-有返回值
- getText
- getValue
- getAttribute
自动化流程控制
-
为什么引入显式等待和隐式等待
大多数Web应用程序都是使用Ajax和Javascript开发的。当浏览器加载页面时,我们想要与之交互的元素可能以不同的时间间隔加载。跨页面的情况下,找不到元素的情况较多,此时需要使用显式等待或隐式等待。
selenium框架有两种处理时间同步的方法,隐式等待和显示等待,前者是对全局页面元素操作有效,会先设置等待时间,一直等待元素的出现,直到超时再抛出异常,后者只对当前指定页面元素等待有效,同样也有设置一个等待时间,但是它有期望条件:elementToBeClickable、presenceOfElementLocated、titleContains、visibilityOfElementLocated,直到不满足条件再抛出异常。 -
线程休眠:不推荐使用。固定等待10秒,找不到元素报异常,找到元素继续。
try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); }
-
隐式等待
-
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
-
在设置的时间内找到元素就继续,找不到就抛出异常
-
一次设置,对全局页面元素操作有效,所以一般写在代码最开始处,在整个driver等生命周期都有效。服务端会帮你轮询查找,全局性的。
//实例化WebDriver,启动浏览器 WebDriver driver = new ChromeDriver(); //设置隐式等待 driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
-
-
显式等待
-
客户端轮询查找 每找一次元素,等待一个间隔再次查找,知道条件匹配,一次性的
-
selenium有提供一个等待的类:WebDriverWait,每次需要设置必先创建对象调用
WebDriverWait wait = new WebDriverWait(driver, timeout); wait.until(ExpectedConditions.titleContains(locator));
-
再来对显示等待时间设置的期望条件进行封装,封装条件常用的有:
visibilityOfElementLocated
和elementToBeClickable
WebDriverWait wait = new WebDriverWait(driver, timeout); //等待locator定位的元素出现后再继续 wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
-
visibilityOf
-
visibilityOfAllElement
-
使用:所有定位都可以加上显式等待,但是一般认知上,如登录页面,当用户名输入框加载出来,一般密码输入框、提交按钮也加载出来了,所以可以仅在页面跳转后的第一条定位应该加上显示等待。具体根据实际的情况决定如何使用。
-
小练习
使用上面的知识进入testerhome社区,输入用户名、密码进行登录。
public class SecondDemo {
public static void main(String[] args) {
//设置系统变量(浏览器驱动名称,相对路径)
System.setProperty("webdriver.chrome.driver","src/main/resources/driver/chromedriver");
//实例化WebDriver,启动浏览器
WebDriver driver = new ChromeDriver();
//设置隐式等待
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
//在浏览器中输入网址,并打开网页
driver.get("https://testerhome.com/");
//进入登录页面
driver.findElement(By.linkText("登录")).click();
//用户名
//设置隐式等待
try {
WebDriverWait wait = new WebDriverWait(driver, 3);
WebElement name=wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("user_login")));
name.clear();
name.sendKeys("leitianxiao");
}catch (Exception e){
System.out.println("找不到元素,错误信息为:"+e);
}
//密码
WebElement pwd=driver.findElement(By.id("user_password"));
pwd.clear();
//打码了,自己填入自己的密码
pwd.sendKeys("*******");
//点击提交登录信息
driver.findElement(By.name("commit")).click();
//关闭浏览器
driver.quit();
//打印是否执行完所有代码
System.out.println("passed");
}
}
Chrome Headless模式(无头浏览器)
-
Headless模式
headless模式是缺少显示设备,键盘或鼠标的系统配置。在自动化测试和爬虫领域应用广泛。我们在通过Selenium运行自动化测试时,必须要启动浏览器,浏览器的启动与关闭必然会影响执行效率,而且还会干扰你做其它事情(本机运行的话)。 -
Chrome Headless 模式
Google 针对 Chrome 浏览器59版开始新增加的一种模式,可以让你不打开UI界面的情况下使用 Chrome 浏览器,所以运行效果与 Chrome 保持一致。 -
使用Chrome Headless 模式
//设置ChromeOptions ChromeOptions chromeOptions = new ChromeOptions(); chromeOptions.addArguments("--headless"); //实例化,启动浏览器 WebDriver driver = new ChromeDriver(chromeOptions);
- 示例
public class HeadlessDemo { public static void main(String[] args) { //设置系统变量(浏览器驱动名称,相对路径) System.setProperty("webdriver.chrome.driver","src/main/resources/driver/chromedriver"); //设置ChromeOptions,headless模式 ChromeOptions chromeOptions = new ChromeOptions(); chromeOptions.addArguments("--headless"); //实例化,启动浏览器 WebDriver driver = new ChromeDriver(chromeOptions); //设置隐式等待 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); //在浏览器中输入网址,并打开网页 driver.get("https://testerhome.com/"); //进入登录页面 driver.findElement(By.linkText("登录")).click(); //用户名 WebElement name=driver.findElement(By.id("user_login")); name.clear(); name.sendKeys("leitianxiao"); //密码 WebElement pwd=driver.findElement(By.id("user_password")); pwd.clear(); pwd.sendKeys("*******"); //点击提交登录信息 driver.findElement(By.name("commit")).click(); //关闭浏览器 driver.quit(); //打印是否执行完所有代码 System.out.println("passed"); } }
多浏览器
- 火狐
- IE11
元素定位进阶CSS
- 选择器
-
标签名:直接写标签名,如a、p、div、input
-
#
id :driver.findElement(By.cssSelector("#navbar-header")).click();
-
.
class:driver.findElement(By.cssSelector(".navbar-brand")).click();
-
>
表示子元素、层级关系 :driver.findElement(By.cssSelector(".navbar-nav>li>a")).click();
-
image.png^=
元素属性开始于:driver.findElement(By.cssSelector(".navbar-nav>li>a[href^='/top']")).click();
-
*=
元素属性包含:driver.findElement(By.cssSelector(".navbar-nav>li>a[href*='/bug']")).click();
-
$=
元素属性结尾:driver.findElement(By.cssSelector(".navbar-nav>li>a[href$='tions']")).click();
-
元素定位进阶XPath
-
Copy XPath:
driver.findElement(By.xpath("//*[@id=\"main-nav-menu\"]/ul/li[1]/a")).click();
-
/
子级,不能越级 -
//
子孙级,可以越级 -
*
任意元素 -
@
属性 -
contains
包含
p[contains(@class,'navbar-brand')]
:classname中包含navbar-brand的p标签 -
逻辑运算符
p[contains(@class,'navbar-brand') and contains(@style,'display:block')]
:classname中包含navbar-brand且style属性中display=block的p标签
CSS定位和XPath定位
- Xpath可以反推父元素
- Css速度快、书写短
测试框架引入-TestNG
-
pom文件添加TestNG的依赖
-
常用断言
- assertTrue 验证是或否
- assertSame 验证是否匹配、相似、模糊匹配
- assertEquals 验证是否相等
-
常用声明
- @Test
- @BeforeSuite
- @AfterSuite
- @BeforeTest
- @AfterTest
- @BeforeClass
- @AfterClass
- @BeforeMethod
- @AfterMethod
-
TestNG比JUnit的优点
- TestNG支持Groups Edit Configurations
- TestNG允许依赖测试 dependsOnMethods ="依赖的方法名"
- TestNG通过标注的方式来顺序执行 priority = "代表顺序的数字"
- TestNG支持并行测试
- 都可以做忽略测试,可以忽略某个测试方法,也可以忽略某个测试类
-
TestNG报告
- Run--->Edit Configurations--->Listeners ---> 勾选use default reports
- 运行测试脚本
- 生成
test-output
文件夹中的index.html
或old/index.html
即为测试报告
-
数据驱动
- 使用@DataProvider注解
@DataProvider public Object[][] getUsers(){ return new Object[][]{ {"leitianxiao","*******","leitianxiao"}, {"abc","123","abc"} }; } }
-
读取csv文件传参
读取文件的方法public Iterator<Object[]> readDataFormCSV(String path){ try { List<Object[]> list = new ArrayList<Object[]>(); FileReader is = new FileReader((new File(path))); BufferedReader br = new BufferedReader(is); while (br.ready()) { list.add(br.readLine().split(",")); } return list.iterator(); }catch (Exception ex){ throw new SkipException(ex.getMessage()); } }
-
读取Excel文件
添加依赖<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency>
读取Excel文件
public Object[][] getDataFormExcel(String excelPath) { Workbook workbook; try { FileInputStream excelInputStream = new FileInputStream(excelPath); workbook = new XSSFWorkbook(excelInputStream); Sheet sheet = workbook.getSheetAt(0); int rowInExcel=sheet.getPhysicalNumberOfRows(); int columnInExcel=sheet.getRow(0).getPhysicalNumberOfCells(); String[][] obj=new String[rowInExcel-1][columnInExcel]; for (int row=1;row<rowInExcel;row++){ for (int col=0;col<columnInExcel;col++){ sheet.getRow(row).getCell(col).setCellType(CellType.STRING); //sheet.getRow(row).getCell(col).setCellType(Cell.CELL_TYPE_STRING); obj[row-1][col]=sheet.getRow(row).getCell(col).getStringCellValue(); System.out.println(obj[row-1][col]); } } return obj; }catch (Exception e){ throw new SkipException(e.getMessage()); } }
Excel格式(默认从第二行开始读取,按照这个格式写)
用户名 密码 断言 leitianxiao ****** leitianxiao -
数据驱动代码改造(读取csv文件为例)
//TestNGDemo.java public class TestNGDemo { WebDriver driver; @BeforeMethod public void startUp(){ //设置系统变量(浏览器驱动名称,相对路径) System.setProperty("webdriver.chrome.driver","src/main/resources/driver/chromedriver"); driver = new ChromeDriver(); //设置隐式等待 driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @Test(dataProvider = "getUserLogin",dataProviderClass =LoginData.class) public void login(String loginName,String loginPwd,String expect){ //在浏览器中输入网址,并打开网页 driver.get("https://testerhome.com/"); //进入登录页面 driver.findElement(By.linkText("登录")).click(); //用户名 //设置隐式等待 try { WebDriverWait wait = new WebDriverWait(driver, 3); WebElement name=wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("user_login"))); name.clear(); name.sendKeys((CharSequence) loginName); }catch (Exception e){ System.out.println("找不到元素,错误信息为:"+e); } //密码 WebElement pwd=driver.findElement(By.id("user_password")); pwd.clear(); pwd.sendKeys((CharSequence) loginPwd); //点击提交登录信息 driver.findElement(By.name("commit")).click(); //点击个人头像 driver.findElement(By.cssSelector("a[href='#']>img")).click(); //获取用户名 String actual=driver.findElement(By.cssSelector("a[href='/leitianxiao']")).getText(); //断言用户名 Assert.assertEquals(actual,expect); } @AfterMethod public void quit(){ //关闭浏览器 driver.quit(); //打印是否执行完所有代码 System.out.println("passed"); } }
/** LoginData.java 为登录提供测试数据 */ public class LoginData { //读取csv文件传参 @DataProvider public Iterator<Object[]> getUserLogin() { String path = "src/main/resources/loginData.csv"; return readDataFormCSV(path); } //读取csv文件方法 public Iterator<Object[]> readDataFormCSV(String path){ try { List<Object[]> list = new ArrayList<Object[]>(); FileReader is = new FileReader((new File(path))); BufferedReader br = new BufferedReader(is); while (br.ready()) { list.add(br.readLine().split(",")); } return list.iterator(); }catch (Exception ex){ throw new SkipException(ex.getMessage()); } } }
<!-- Testng.xml运行配置 --> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> <suite name="All Test Suite"> <test verbose="2" preserve-order="true" name="/Users/leitianxiao/Documents/UIAuto"> <groups> <dependencies> <group name="group1" depends-on=""> <classes> <class name="TestNGDemo"> <methods> <include name="login"></include> </methods> </class> </classes> </group> </dependencies> </groups> </test> </suite>
PageObject设计模式
Page Object模式是使用Selenium的广大同行最为公认的一种设计模式。在设计测试时,把元素和方法按照页面抽象出来,分离成一定的对象,然后再进行组织。
Page Object模式的核心理念是,以页面(Web Page或Native App Page)为单位来封装页面上的控件以及控件的部分操作。而测试用例,更确切的是操作函数,基于页面封装对象来完成具体的界面操作,最典型的模式“XXXPage.YYYComponent.ZZZOperation”
代码改造
-
src/main/java/page
文件夹用于放各个被测系统的各个页面、各PO、各工具类 -
src/main/resources
用于放各种非.java资源 -
src/test/java
放测试用例,对PO的调用 -
首页
public class HomePage {
//页面需要操作的元素
@FindBy(linkText="登录")
WebElement loginLink;
//构造器
public HomePage(WebDriver driver){
PageFactory.initElements(driver,this);
}
public void clickLogin(){
//对元素的操作
loginLink.click();
//日志
Reporter.log("点击登录链接",true);
}
}
- 登录页
public class LoginPage {
WebDriver driver;
//页面的元素
@FindBy(id="user_login")
WebElement inputUserName;
@FindBy(id="user_password")
WebElement inputPassword;
@FindBy(name="commit")
WebElement buttonLogin;
//构造器
public LoginPage(WebDriver driver){
this.driver=driver;
PageFactory.initElements(driver,this);
}
//对元素的操作
public void inputUserName(String loginName){
//显式等待
WebDriverWait wait = new WebDriverWait(driver, 3);
wait.until(ExpectedConditions.visibilityOf(inputUserName));
inputUserName.clear();
inputUserName.sendKeys(loginName);
Reporter.log("输入用户名",true);
}
public void inputPassword(String loginPwd){
inputPassword.clear();
inputPassword.sendKeys(loginPwd);
Reporter.log("输入密码",true);
}
public void buttonLogin(){
buttonLogin.click();
Reporter.log("点击登录按钮",true);
}
}
- 业务逻辑
public class Business {
WebDriver driver;
@BeforeMethod
public void startUp(){
//设置系统变量(浏览器驱动名称,相对路径)
System.setProperty("webdriver.chrome.driver","src/main/resources/driver/chromedriver");
driver = new ChromeDriver();
//设置隐式等待
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
@Test()
public void login(){
//在浏览器中输入网址,并打开网页
driver.get("https://testerhome.com/");
//PO模式改造部分分割线 ----------
//进入首页
HomePage homePage=new HomePage(driver);
//点击登录链接
homePage.clickLogin();
//进入登录页面
LoginPage loginPage=new LoginPage(driver);
//用户名
loginPage.inputUserName("leitianxiao");
//密码
loginPage.inputPassword("******");
//点击提交登录信息
//PO模式改造部分分割线 ----------
loginPage.buttonLogin();
//点击个人头像
driver.findElement(By.cssSelector("a[href='#']>img")).click();
//获取用户名
String actual=driver.findElement(By.cssSelector("a[href='/leitianxiao']")).getText();
//断言用户名
Assert.assertEquals(actual,"leitianxiao");
}
@AfterMethod
public void quit(){
//关闭浏览器
driver.quit();
//打印是否执行完所有代码
System.out.println("passed");
}
}
Selenium进阶API
-
切换窗口/对话框/iframe
- 切换窗口
driver.switchTo().window();
//以上海链家官网为例 public class APIDemo { WebDriver driver; @BeforeMethod public void startUp() { //设置系统变量(浏览器驱动名称,相对路径) System.setProperty("webdriver.chrome.driver", "src/main/resources/driver/chromedriver"); driver = new ChromeDriver(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @Test public void switchWindow() { //在浏览器中输入网址,并打开网页 driver.get("https://sh.lianjia.com/"); //设置滚动条,找到二手房链接处 String script = "return arguments[0].scrollIntoView();"; WebElement element = driver.findElement(cssSelector("a[href='/ershoufang/']>img")); ((JavascriptExecutor) driver).executeScript(script, element); //点击二手房链接 driver.findElement(cssSelector("a[href='/ershoufang/']>img")).click(); Reporter.log("已找到二手房链接",true); //获得当前窗口的handle String curHandle=driver.getWindowHandle(); Reporter.log("打印curHandle:"+curHandle,true); //获取所有handle做循环,如果不是curHandle,就是新窗口,切换到新窗口 driver.getWindowHandles(); for(String handle:driver.getWindowHandles()){ Reporter.log("打印循环handle:"+handle,true); if(!handle.equals(curHandle)){ driver.switchTo().window(handle); break; } } Reporter.log("已找到新窗口",true); //找到搜索框 WebElement searchInput=driver.findElement(By.id("searchInput")); searchInput.clear(); searchInput.sendKeys("虹口区"); WebElement searchButton=driver.findElement(cssSelector("button[class=\"searchButton\"]")); searchButton.click(); } @AfterMethod public void quit(){ //关闭浏览器 driver.quit(); //打印是否执行完所有代码 System.out.println("passed"); } }
-
切换到对话框
driver.switchTo().alert();
-
driver.switchTo().alert().accept();
确认 -
driver.switchTo().alert().dismiss();
取消
-
-
切换到iframe
driver.switchTo().frame();
- 微博首页淘宝登录按钮是在iframe里
- 切换处iframe框
driver.switchTo.defualtcontent();
- 切换窗口
-
cookie处理
- 添加cookie
Cookie cookie=new Cookie("cookie的名字","cookie的值","cookie的path","cookie的期限"); driver.manage().addCookie(cookie);
- 删除cookie
driver.manage().deleteAllCookies();
- 获取cookie
driver.manage().getCookies();
for (Cookie cookie:driver.manage().getCookies()){ System.out.println("path:\n"+cookie.getPath()); System.out.println("getExpiry:\n"+cookie.getExpiry()); System.out.println("name:\n"+cookie.getName()); System.out.println("domain:\n"+cookie.getDomain()); System.out.println("value:\n"+cookie.getValue()); System.out.println("---------------"); }
-
执行javascript
想使用js语句修改style:document.getElementById(\"navbar-header\").style.backgroundColor='yellow'
但是Java代码中不能直接使用js。//实现将testerhome社区的logo背景色变为黄色 driver.get("https://testerhome.com"); String js="document.getElementById(\"navbar-header\").style.backgroundColor='yellow'"; //将java中的driver强制转型为JS类型 JavascriptExecutor jsDriver = (JavascriptExecutor) driver; jsDriver.executeScript(js);
-
鼠标及键盘操作Actions
public void actionsDemo(){
Actions actions=new Actions(driver);
//鼠标单击
actions.click();
//双击
actions.doubleClick();
//保持单击
actions.clickAndHold();
//鼠标松开,与clickAndHold搭配使用
actions.release();
//鼠标右击
actions.contextClick();
//按下enter键
actions.keyDown(Keys.ENTER);
//松开enter键
actions.keyUp(Keys.ENTER);
//按下、松开enter键
actions.sendKeys(Keys.ENTER);
}
-
网页截图
- 添加依赖
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency>
- 局部截图
@Test public void picDemo(){ driver.get("https://testerhome.com"); //截图 File srcFile=((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); try { FileUtils.copyFile(srcFile,new File("src/main/java/shot.png")); } catch (IOException e) { e.printStackTrace(); } }
- 添加依赖
-
上传下载
- 上传 使用AUTOIT工具,解决上传头像、上传图片等弹窗
- 下载