Selenium是一种自动化测试工具,可以模拟人来操作浏览器,执行效率有时候还不如人快,因为需要浏览器页面加载完成才能操作,对网速要求严格,可以用于重复性的操作。
- 本次将基于java / testNG-selenium-chrom-chromWebDriver+Allure架构进行展示
- 涉及功能
- 常用工具类(窗口截图,当前时间,获取指定长度随机字符串,获取指定长度随机数字)
- 登陆场景(数据驱动测试DDT,断言)
- 用户管理(增加,删除,更改,查询)
- 生成报告
- 数据驱动测试使用TestNg的DataProvider注解实现
- 定位元素使用了隐式等待,在限定时间内没有加载出来脚本会报错执行,可在此处进行异常捕获
- setUp中打开浏览器,afterTest中退出浏览器
- 每个测试方法需要加上Test注解(TestNg提供)
- 加sleep是为了能够捕获到期望的截图,否则跳转太快
Selenium环境搭建
环境声明
本机环境软件名称 |
版本号 |
电脑环境 | Mac M1 Arm64 |
Chrom版本 | 版本 108.0.5359.124 (arm64) |
ChromWebDriver 版本 | 108.0.5359.71(前三个数字和chrom版本对应即可) |
本机Selenium版本 | 4.6 |
本机Allure版本 | 2.20.1 |
JDK环境 | 1.8_u201 |
环境搭建步骤
-
下载driver;
根据chrom版本号,下载chromwebDriver驱动, 并将驱动放到/usr/local/bin目录(本机安装环境是Mac m1 所以选择的是arm64)
如果是windows或者linux环境 需要设置驱动路径
System.setProperty("webdriver.chrome.driver", "D:\\webDriver\\chromedriver.exe");// chromedriver服务地址
WebDriver driver = new ChromeDriver(); // 新建一个WebDriver 的对象,但是new 的是谷歌的驱动
2.安装selenium
1.通过jar包方式安装
1.下载Selenium相应版本号的selenium-server-版本号.jar 文件
2.打开idea,导入jar包
idea-File-Project Structure-Modules-Dependencies 点击+ 号 ,将selenium-server-版本号.Jar包导入
2. 通过Maven安装
1. 打开pom.xml 配置Selenium
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.4.0</version>
</dependency>
2.POM配置项
<dependencies> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>6.10</version> </dependency> <dependency> <groupId>io.qameta.allure</groupId> <artifactId>allure-testng</artifactId> <version>2.20.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.6</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.20</version> <configuration> <argLine> -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/1.9.6/aspectjweaver-1.9.6.jar" </argLine> </configuration> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.6</version> </dependency> </dependencies> </plugin> </plugins> </build>
3.简单Demo测试启动
新建java类,编写启动chrome浏览器代码
package com.ad4test.browser;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class Browser {
public static void main(String[] args) {
WebDriver driver = new ChromeDriver();
driver.get("http://www.baidu.com");
}
}
结合具体场景设计测试用例Demo
Login Testcases
使用DataProvider注解进行数据驱动测试,四个测试用例,根据参数数量决定用例执行次数
package com.ad4test.browser;
import com.ad4test.util.GetCurrentDate;
import com.ad4test.util.WindowUtil;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import io.qameta.allure.Feature;
public class testLogin {
@DataProvider(name="testdata")
public Object[][] TestDataFeed(){
Object [][] loginData=new Object[4][2]; // define 4 users
//1st user,incorrect username passwd
loginData[0][0]="ad4c.test04";
loginData[0][1]="*^%$%^&";
//2nd user, correct username and pwd
loginData[1][0]="ad4c.test04";
loginData[1][1]="Test@04.";
//3rd, empty username and pwd
loginData[2][0]="";
loginData[2][1]="";
//4th,correct username and incorrect pwd
loginData[3][0]="ad4c.test04";
loginData[3][1]="#$%^&*";
return loginData;
}
@Test(dataProvider = "testdata",description = " login-cases")
@Feature("LoginTestCase")
public void TestLogin(String username, String password) throws InterruptedException {
// get driver
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
// open window
driver.get("https://ad4cloud-web.lotuscars.com.cn/dev/cloud-admin#/login");
// get elements
WebElement userNameInput = driver.findElement(new By.ByXPath("/html/body/div/div/div/div[2]/form/div[3]/div/div/input"));
WebElement passwordInput = driver.findElement(new By.ByXPath("/html/body/div/div/div/div[2]/form/div[4]/div/div/input"));
WebElement loginButton = driver.findElement(new By.ByXPath("/html/body/div/div/div/div[2]/form/button/span"));
// input data
userNameInput.sendKeys(username);
passwordInput.sendKeys(password);
loginButton.click();
Thread.sleep(1500);
try{
// assert login success or not
WebElement loginSuccessUsername = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[1]/div[1]/div/div[2]/div/div/span/div[2]/span"));
String loginedUsername = loginSuccessUsername.getText();
Assert.assertEquals(loginedUsername.toLowerCase(),username.toLowerCase());
Thread.sleep(1000);
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys()+"_loginSuccess.png");
}catch (Exception ex){
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys()+"_loginFailed.png");
}finally {
driver.quit();
}
}
User Management Testcases
- 使用BeforeTest注解,进行测试的setUp操作,打开浏览器
- AfterTest注解进行TearDown操作,quit退出浏览器(close是关闭,后台会继续运行,不是退出)
- 测试依赖使用Test注解中的dependsOnMethods属性,标注依赖哪个测试方法将执行在前
- Test注解中priority属性可以调整测试方法的执行顺序,TestNg默认priority 为0
package com.ad4test.browser;
import com.ad4test.util.GetCurrentDate;
import com.ad4test.util.SysUtil;
import com.ad4test.util.WindowUtil;
import io.qameta.allure.Feature;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import java.util.concurrent.TimeUnit;
public class testUserEdit {
WebDriver driver;
String inputUserName=SysUtil.getRandomString(4)+"_Tstr";
@BeforeTest
public void setUp() {
// get driver
driver = new ChromeDriver();
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
driver.manage().window().maximize();
}
@AfterTest
public void afterTest() {
// quit driver
driver.quit();
}
@Test(description = "SystemUserLogin desc")
@Feature("Login")
public void commonLogin() throws InterruptedException {
// open window
driver.get("https://URL/dev/cloud-admin#/login");
// get elements
WebElement userNameInput = driver.findElement(new By.ByXPath("/html/body/div/div/div/div[2]/form/div[3]/div/div/input"));
WebElement passwordInput = driver.findElement(new By.ByXPath("/html/body/div/div/div/div[2]/form/div[4]/div/div/input"));
WebElement loginButton = driver.findElement(new By.ByXPath("/html/body/div/div/div/div[2]/form/button/span"));
String username="ad4c.test04";
String pwd="Test@04.";
// input data
userNameInput.sendKeys(username);
passwordInput.sendKeys(pwd);
loginButton.click();
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys() + "userEditLogin.png");
try {
WebElement loginSuccessUsername = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[1]/div[1]/div/div[2]/div/div/span/div[2]/span"));
String loginedUsername = loginSuccessUsername.getText();
Assert.assertEquals(loginedUsername.toLowerCase(), username.toLowerCase());
} catch (Exception ex) {
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys() + "_exception.png");
}
Assert.assertEquals(1,1);
}
@Test(dependsOnMethods = {"commonLogin"},description = "createUser desc")
@Feature("CreateUser")
public void createUser() throws InterruptedException {
// check if login success or not
WebElement loginedSystemButton = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[1]/div[1]/div/div[2]/div[1]/div/div/div/div[3]/div"));
loginedSystemButton.click();
Thread.sleep(1000);
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys() + "JumpToSystemPage.png");
// click add user button
WebElement addUserButton = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[2]/div[1]/div[5]/div[1]/table/thead/tr/th[9]/div/button"));
addUserButton.click();
// fill in the blank,username phone number ,name
WebElement inputUsernameE = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[3]/div/div[2]/form/div[1]/div/div/input"));
inputUsernameE.sendKeys(inputUserName);
WebElement inputPhoneNum = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[3]/div/div[2]/form/div[2]/div/div/input"));
inputPhoneNum.sendKeys("182"+SysUtil.getRandomNum(8));
WebElement inputName = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[3]/div/div[2]/form/div[3]/div/div/input"));
inputName.sendKeys(SysUtil.getRandomString(4)+"_Tsr");
// click dept option element
WebElement selectDept = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[3]/div/div[2]/form/div[5]/div/div/div[1]/input"));
selectDept.click();
WebElement selectedDept = driver.findElement(new By.ByXPath("/html/body/div[4]/div[1]/div/div[1]/ul/li/span"));
selectedDept.click();
WebElement selectDeptAd4 = driver.findElement(new By.ByXPath("/html/body/div[4]/div[1]/div[2]/div[1]/ul/li[2]"));
selectDeptAd4.click();
// click selectRole element
WebElement selectRole = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[3]/div/div[2]/form/div[7]/div/div/div[2]"));
selectRole.click();
WebElement selectedRoleUser = driver.findElement(new By.ByXPath("/html/body/div[5]/div[1]/div[1]/ul/li[2]"));
selectedRoleUser.click();
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys() + "_InputUserInfo.png");
// submit data
WebElement submitButton = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[3]/div/div[3]/span/button[2]"));
submitButton.click();
Assert.assertEquals(1,1);
}
@Test(dependsOnMethods = {"createUser"},description = "SelectUser desc")
@Feature("SelectCreatedUser")
public void selectUser() throws InterruptedException {
// select by created username
WebElement inputSelectByUserName = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[1]/div[3]/input"));
inputSelectByUserName.sendKeys(inputUserName);
WebElement searchButton = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[1]/button"));
searchButton.click();
Thread.sleep(1000);
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys() + "_SelectByUserName.png");
Assert.assertEquals(1,1);
}
@Test(dependsOnMethods = {"selectUser"},description = "ModifyCreatedUserStatus desc")
@Feature("ModifyUserStatus")
public void modifyStatus() throws InterruptedException {
// modify by created username
WebElement statusButton = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[2]/div[1]/div[3]/table/tbody/tr/td[8]/div/div/span"));
statusButton.click();
Thread.sleep(1000);
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys() + "_modifyStatus_off.png");
statusButton.click();
Thread.sleep(1000);
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys() + "_modifyStatus_on.png");
Assert.assertEquals(1,1);
}
@Test(dependsOnMethods = {"modifyStatus"},description = "ModifyUserInfo desc")
@Feature("ModifyUserInfo")
public void modifyUserInfo() throws InterruptedException {
inputUserName+="0";
// click edit button
WebElement editButton = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[2]/div[1]/div[5]/div[2]/table/tbody/tr/td[9]/div/button[1]"));
editButton.click();
// edit user info ,phone username sex
WebElement phoneNumberInput = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[4]/div/div[2]/form/div[2]/div/div/input"));
phoneNumberInput.clear();
phoneNumberInput.sendKeys("188"+SysUtil.getRandomNum(4)+"0110");
WebElement modifyNameInput = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[4]/div/div[2]/form/div[3]/div/div/input"));
modifyNameInput.clear();
modifyNameInput.sendKeys(inputUserName);
WebElement modifySexInput = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[4]/div/div[2]/form/div[6]/div/div/label[2]/span[1]/span"));
modifySexInput.click();
Thread.sleep(500);
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys() + "_modifyInfo.png");
//submit
WebElement submitButton = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[4]/div/div[3]/span/button[2]"));
submitButton.click();
System.out.println("modified username --> "+inputUserName);
driver.navigate().refresh();
Thread.sleep(1500);
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys() + "_modifiedAndRefreshed.png");
Assert.assertEquals(1,1);
}
@Test(priority = 10,description = "DeleteCreatedUser desc")
@Feature("DeleteCreatedUser")
public void deleteCreatedUser() throws InterruptedException {
// select by created username
WebElement selectUser = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[1]/div[3]/input"));
selectUser.sendKeys(inputUserName);
System.out.println("search inputUsername--- "+inputUserName);
WebElement searchButton = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[1]/button"));
searchButton.click();
Thread.sleep(2000);
//delete user
WebElement deleteButton = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[2]/div[1]/div[5]/div[2]/table/tbody/tr/td[9]/div/button[2]"));
deleteButton.click();
WebElement deleteButtonVerify = driver.findElement(new By.ByXPath("/html/body/div[3]/div/div[3]/button[2]"));
Thread.sleep(500);
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys() + "_deleteUser.png");
deleteButtonVerify.click();
driver.navigate().refresh();
// select by created username
WebElement selectDeletedUser = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[1]/div[3]/input"));
selectDeletedUser.clear();
selectDeletedUser.sendKeys(inputUserName);
WebElement searchButton1 = driver.findElement(new By.ByXPath("/html/body/div[1]/div/div/div[2]/div[2]/section/div/div[1]/button"));
searchButton1.click();
Thread.sleep(500);
WindowUtil.get_screen_shot(driver, GetCurrentDate.getCurrentDateSys() + "_searchDeletedUser.png");
Assert.assertEquals(1,1);
}
}
生成报告
点击测试之后会自动在根目录生成测试数据,在Terminal中使用如下命令,就会在根目录下生成html报告。
注意:
pom中的allure版本,需要和本机中安装的allure对应,否则可能会存在版本冲突问题(不要用2.13版本)
allure generate allure-results -o allure-html-report
Allure html报告截图