zoukankan      html  css  js  c++  java
  • 记录java+testng运行selenium(四)--- 运行代码

    涉及的文件有:

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

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

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

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

    .medicalmanualuserTestUserLogin.java : test用例类

    .medicalmanualuserTestUserLogin.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中的全部数据逐条进行返回最后来运行。

  • 相关阅读:
    【CF1023D】Array Restoration(构造,线段树)
    【CF1020E】Sergey's problem(构造)
    【CF1020D】The hat(交互,二分)
    【CF1017F】The Neutral Zone(Bitset,埃氏筛)
    【CF1016F】Road Projects(贪心)
    【ZOJ4063】Tournament(构造)
    EQueue
    领域驱动设计(DDD)部分核心概念的个人理解
    DDD CQRS架构和传统架构的优缺点比较
    限流算法-三种思路
  • 原文地址:https://www.cnblogs.com/xiaodingdong/p/11721309.html
Copyright © 2011-2022 走看看