记录java+testng运行selenium(四)--- 运行代码

时间:2022-10-12 14:33:38

涉及的文件有:

.\medical\BusinessFile.java :实例化excel及xml文件操作对象以及将list变成Map

.\medical\manual\business\LoginBusiness.java :通过放射获取元素路径及用例动作的执行(每个对应的test都应该有之相对应的business)

.\medical\manual\handles\LoginElement.java :元素对象路径定义类,后期元素对象的路径发生改变之后只需要修改相应的值即可。

及读取excel读取的数据返回到用例执行类中(excel读取可以放在LoginBusiness文件中)

.\medical\manual\user\TestUserLogin.java : test用例类

.\medical\manual\user\TestUserLogin.xml: test中定义的excel文件所在路径

一: 编写excel所在目录及sheet名

创建TestUserLogin.xml并编写以下内容

<?xml version="1.0" encoding="UTF-8"?>
<data>
<loginTest>
<load>.\drivers\测试用例.xlsx</load>
<sheetName>登录</sheetName>
</loginTest>
</data>

二:编写test执行类

创建TestUserLogin.java并编写以下代码

import java.util.Map;

import org.testng.annotations.*;

import medical.manual.business.LoginBusiness;
import medical.manual.handles.LoginElement; public class TestUserLogin { private LoginBusiness lb; @BeforeMethod
public void runDriveBrowser() {
String filename = "hospital.ini";
this.lb = new LoginBusiness(filename);
} @AfterMethod
public void closeDrive() {
lb.browser.closeBrowser(1000);
} /**
* dataProvider可以是定义的name名字也可以是函数名
* @param param 单行excel数据
*/
@Test(description = "用户的登录", dataProvider = "getLoginData", dataProviderClass = LoginElement.class)
public void loginTest(Map<?, ?> param) {
lb.medicalRecords(param);
} }

函数说明:

runDriveBrowser :每条用例执行时都重新创建浏览器对象,并把浏览器所在的ini文件当做参数传入到用例操作类中

closeDrive :用于关闭浏览器的操作,传入延迟时间主要用于延迟关闭操作

loginTest : 通过数据驱动的形式,只需要定义一个函数然后就可以执行同一个sheet下的用例(前提是用例结果相同)。

三:元素实现类

创建BusinessFile.java 并编写以下内容

package medical;

import org.testng.Assert;
import toolskit.documents.ReadExcel;
import toolskit.documents.XmlUtil; import java.util.ArrayList;
import java.util.List;
import java.util.Map; /**
* @ ClassName: medical
* @ Author: DingDong
* @ Date: 2019/10/21 16:25
* @ Version: 1.0
* @ desc:
*/
public class BusinessFile { public Object[][] dataProviderSource(String load,String sheetName){ ReadExcel re = new ReadExcel(); List<Map<String, String>> maps = re.readExcel(load, sheetName); Object[][] testData = mapsToArray(maps);
return testData;
} public List<Map<String, String>> getXmlData(String methodName,String xmlPath){
List parList; List<Map<String, String>> sonList=new ArrayList<>(); // 读取xml内容
parList = XmlUtil.getXmlComent(xmlPath); // 根据名字进行区分
for (int i=0;i< parList.size();i++) {
Map map = (Map)parList.get(i);
if (map.containsKey(methodName)) {
Map<String,String> subMap = (Map<String,String>) map.get(methodName);
sonList.add(subMap);
}
} if (sonList.size() > 0) {
return sonList;
}else{
Assert.assertTrue(sonList.size()!=0,parList+"为空,找不到属性值:"+methodName );
return null;
}
} public Object[][] mapsToArray(List<Map<String, String>> maps) {
int singleListSize = maps.size(); // 创建一个二维数组
Object[][] testData = new Object[singleListSize][]; for (int singleSize = 0; singleSize < singleListSize; singleSize++) { Map<String, String> singleMap = maps.get(singleSize);
testData[singleSize] = new Object[]{singleMap}; } // 返回数据传给脚本
return testData; }
}

函数说明:

dataProviderSource:根据用例位置及sheet名字来读取excel中的内容

getXmlData : 根据现在运行的test名及xml所在位置来读取excel所在位置及sheet名字

mapsToArray : 将 map 转换 成 Array

创建LoginElement.java 并编写以下内容:

package medical.manual.handles;

import java.lang.reflect.Method;

import java.util.HashMap;
import java.util.List;
import java.util.Map; import org.testng.annotations.DataProvider; import medical.BusinessFile; public class LoginElement extends BusinessFile { // 用于存储元素路径及元素类型
private Map<String, String> loginElement; private void setPathAndType(String elePath, String pathType) {
loginElement = new HashMap<>();
loginElement.put("elePath", elePath);
loginElement.put("pathType", pathType);
} public Map<String, String> getLoginTitle() {
setPathAndType("h3.title", "css");
return loginElement;
} public Map<String, String> getLoginUser() {
setPathAndType("username", "name");
return loginElement;
} public Map getLoginUserError() {
setPathAndType("form > div:nth-child(2) > div > div.el-form-item__error", "css");
return loginElement;
} public String getUserErrorMsg() {
// 账号输入框错误提示语
return "请填写账号";
} public Map getLoginPass() {
setPathAndType("password", "name"); return loginElement;
} public Map getLoginPassError() {
setPathAndType("div.el-form-item.el-tooltip.is-error.is-required > div > div.el-form-item__error", "css");
return loginElement;
} public String getPassErrorMsg() {
// 密码输入框错误提示语
return "请填写密码";
} public Map getLoginButton() {
setPathAndType("form > button:nth-child(4)", "css");
return loginElement;
} public Map getLoginRegister() {
setPathAndType("form > button:nth-child(5)", "css");
return loginElement;
} private Map getLoginError() {
setPathAndType("body > div.el-message.el-message--error", "css");
return loginElement;
} public Method getLoginPageElement(String methodName) {
Method getPassErrorMsg = null;
try {
// 根据方法名获得指定的方法, 参数name为方法名,参数parameterTypes为方法的参数类型 getPassErrorMsg = LoginElement.class.getDeclaredMethod(methodName);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return getPassErrorMsg;
} @DataProvider
public Object[][] getLoginData(Method method) { String xmlpth = ".\\src\\main\\java\\medical\\manual\\user\\TestUserLogin.xml";
List<Map<String, String>> xmlData = getXmlData(method.getName(),xmlpth);
String load = xmlData.get(0).get("load");
String sheetName =xmlData.get(0).get("sheetName"); Object[][] testData = dataProviderSource(load,sheetName); return testData; } }

函数说明:

get***并且返回Map类型的函数 : 定义元素路径及路径类型(有css、id、name 、xpath等)

getLoginPageElement : 放射机制获取元素路径

getLoginData : 数据驱动DataProvider中数据来源的准备

四: 用例操作类

创建LoginBusiness.java并编写如下内容

package medical.manual.business;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map; import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.Assert; import toolskit.InformationLog;
import toolskit.carrier.BrowserDriver;
import toolskit.carrier.DriverFactory;
import toolskit.exhibition.ExecuteFramework;
import toolskit.exhibition.InterfaceShow;
import toolskit.incomprehension.AbnormalCodeError;
import toolskit.incomprehension.ResourceNotFoundException;
import medical.manual.handles.LoginElement; import static toolskit.documents.ReadIni.readIni; public class LoginBusiness { public BrowserDriver browser;
private InterfaceShow execute;
private LoginElement loginElement;
private WebDriver driver; public LoginBusiness(String filename) { Map<String, Object> url_ini = readIni(filename,"");
String driverType =((Map<String, String>) url_ini.get("dz_login")).get("driver");
String webUrl = ((Map<String, String>) url_ini.get("dz_login")).get("url");
this.browser = DriverFactory.getDriverBrowser(driverType,webUrl);
this.driver = browser.getDriver(); this.loginElement = new LoginElement();
this.execute = new ExecuteFramework(driver);
} private String getElement(String elePath, String pathType) {
String errorText = execute.getAttributeTextValue(elePath, pathType, null, "text");
return errorText;
} private void inputUserInfo(String loginFunction, String userData) {
try {
Method getPassErrorMsg = loginElement.getLoginPageElement(loginFunction); Map loginMap = (Map) getPassErrorMsg.invoke(loginElement); String elePath = (String) loginMap.get("elePath");
String pathType = (String) loginMap.get("pathType"); InformationLog.inputLogInfo("the element: " + loginMap.get("elePath") + " input data " + loginMap.get("pathType")); WebElement username = execute.VisibleFocus(elePath, pathType);
execute.HandleVisibleInput("", "", username, userData); // 利用js代码在指定的元素上失去焦点
JavascriptExecutor driver_js = ((JavascriptExecutor) driver);
driver_js.executeScript("arguments[0].blur();", username); } catch (InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
} } /**
* 获取输入框中出现错误的提示语
*
* @param loginFunction 提示语所在位置的指定函数
* @param loginErrorFun 提示语内容
*/
private void getUserErrorInfo(String loginFunction, String loginErrorFun) {
Method getPassErrorMsg;
Map loginMap;
String loginError;
try {
// 找到错误提示语位置
getPassErrorMsg = loginElement.getLoginPageElement(loginFunction); loginMap = (Map) getPassErrorMsg.invoke(loginElement); String elePath = (String) loginMap.get("elePath");
String pathType = (String) loginMap.get("pathType"); // 找到错误提示语
String errorText = getElement(elePath, pathType); // 获取内置提示语进行比较
getPassErrorMsg = loginElement.getLoginPageElement(loginErrorFun); loginError = (String) getPassErrorMsg.invoke(loginElement); if (errorText != null && errorText.equals(loginError)) {
InformationLog.inputLogInfo(" element error message: " + errorText);
} else {
InformationLog.inputLogInfo(" element No error message: ");
} } catch (Exception e) {
e.printStackTrace();
} } private void clickLogin() {
// 找到错误提示语位置
Method getPassErrorMsg = loginElement.getLoginPageElement("getLoginButton"); Map loginMap = null;
try {
loginMap = (Map) getPassErrorMsg.invoke(loginElement);
} catch (Exception e) {
e.printStackTrace();
} assert loginMap != null;
String elePath = (String) loginMap.get("elePath");
String pathType = (String) loginMap.get("pathType"); WebElement userError = execute.VisibleFocus(elePath, pathType);
if (userError != null) {
userError.click();
} else {
Assert.assertThrows(NullPointerException.class,
() -> {
throw new AbnormalCodeError("excel中出现不符合要求的资源:");
}); //failed
} } public void medicalRecords(Map<?, ?> param) { // 输入内容
inputUserInfo("getLoginUser", (String) param.get("username"));
inputUserInfo("getLoginPass", (String) param.get("password")); // 点击登录按钮
clickLogin(); // 判断错误是否出现
String errorType = (String) param.get("type");
if ("info".equals(errorType)) {
getUserErrorInfo("getLoginUserError", "getUserErrorMsg");
getUserErrorInfo("getLoginPassError", "getPassErrorMsg");
} else if ("page".equals(errorType)) {
WebElement userError = new WebDriverWait(driver, 5)
.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("body > div.el-message.el-message--error"))); String errorText = userError.getText();
InformationLog.inputLogInfo("page pupop error info: " + errorText);
} else {
//failed
Assert.assertThrows(NullPointerException.class, () -> {
throw new ResourceNotFoundException();
});
}
}
}

函数说明:

实例化LoginBusiness时需要传入ini所在位置,实例化时就创建浏览器对象、元素存储对象、元素操作对象

getElement : 元素text文字获取函数,这里统一调用也可以不进行创建。

inputUserInfo : 内容输入函数,其中loginFunction为LoginElement文件中对应的get***函数名,userData为需要输入的内容该内容需要从excel中读取

getUserErrorInfo : 内容输入错误时,提示语的获取,loginFunction为LoginElement文件中对应的get***函数名,loginErrorFun为出现的提示语,提示语也是从excel中读取

clickLogin : 执行元素点击操作

medicalRecords : 将上诉的函数结合在一起,整合成整个流程。流程为:账号密码号密码输入-->提示元素校验-->执行点击操作。

说明:

整体思路是:TestUserLogin 中test运行前实例化LoginBusiness,并由此打开浏览器及进入相应的url。

在运行test时由LoginElement中name为getLoginData的dataProvider来准备数据(准备过程中主要是通过xml读取用例位置)

最后将excel中的全部数据逐条进行返回最后来运行。