From 60f7a1947ed8d4aaf9ba7737228fade16fe907d1 Mon Sep 17 00:00:00 2001 From: seagull <24163551@qq.com> Date: Mon, 16 Mar 2020 19:32:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B9=E6=8D=AEIDEA=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=E5=85=A8=E9=9D=A2=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/luckyclient/driven/DbDriven.java | 86 +- .../java/luckyclient/driven/SubString.java | 133 +- .../execution/BatchCaseExecute.java | 136 +- .../luckyclient/execution/OneCaseExecute.java | 134 +- .../execution/RunAutomationTest.java | 99 +- .../execution/WebDebugExecute.java | 74 +- .../appium/AppDriverAnalyticCase.java | 369 ++--- .../execution/appium/AppTestControl.java | 26 +- .../appium/AppiumInitialization.java | 218 +-- .../execution/appium/AppiumService.java | 96 +- .../execution/appium/CaseLocalDebug.java | 146 +- .../appium/androidex/AndroidBaseAppium.java | 101 +- .../appium/androidex/AndroidBatchExecute.java | 192 ++- .../androidex/AndroidCaseExecution.java | 642 +++++---- .../androidex/AndroidCaseLocalDebug.java | 14 +- .../AndroidEncapsulateOperation.java | 1129 ++++++++------- .../androidex/AndroidOneCaseExecute.java | 149 +- .../execution/appium/iosex/IosBaseAppium.java | 436 +++--- .../appium/iosex/IosBatchExecute.java | 190 +-- .../appium/iosex/IosCaseExecution.java | 666 +++++---- .../appium/iosex/IosCaseLocalDebug.java | 141 +- .../appium/iosex/IosEncapsulateOperation.java | 1075 ++++++++------- .../appium/iosex/IosOneCaseExecute.java | 147 +- .../execution/dispose/ActionContext.java | 126 +- .../dispose/ActionManageForSteps.java | 180 +-- .../execution/dispose/ChangString.java | 102 +- .../dispose/ParamsManageForSteps.java | 226 +-- .../dispose/actionkeyword/Action.java | 34 +- .../actionkeyword/ActionKeyWordParser.java | 38 +- .../actionkeyword/GetJsonActionParser.java | 2 +- .../dispose/actionkeyword/HeaderParser.java | 6 +- .../SubCentresStrActionParser.java | 4 +- .../actionkeyword/SubStrRegxActionParser.java | 2 +- .../actionkeyword/ThreadWaitAction.java | 6 +- .../httpinterface/ApiTestCaseDebug.java | 469 ++++--- .../httpinterface/BatchTestCaseExecution.java | 29 +- .../httpinterface/TestCaseExecution.java | 814 ++++++----- .../execution/httpinterface/TestControl.java | 14 +- .../httpinterface/ThreadForBatchCase.java | 64 +- .../httpinterface/ThreadForExecuteCase.java | 524 ++++--- .../httpinterface/WebTestCaseDebug.java | 23 +- .../analyticsteps/InterfaceAnalyticCase.java | 373 ++--- .../execution/webdriver/BaseWebDrive.java | 15 +- .../execution/webdriver/CaseLocalDebug.java | 146 +- .../webdriver/EncapsulateOperation.java | 1214 ++++++++--------- .../execution/webdriver/TestGoogle.java | 21 - .../webdriver/WebDriverInitialization.java | 266 ++-- .../execution/webdriver/WebTestControl.java | 15 +- .../webdriver/ex/WebBatchExecute.java | 162 ++- .../webdriver/ex/WebCaseExecution.java | 669 +++++---- .../webdriver/ex/WebDriverAnalyticCase.java | 387 +++--- .../webdriver/ex/WebOneCaseExecute.java | 121 +- .../execution/webdriver/ocr/Ocr.java | 22 +- .../java/luckyclient/netty/ClientHandler.java | 92 +- .../java/luckyclient/netty/HttpRequest.java | 120 +- .../java/luckyclient/netty/NettyClient.java | 109 +- .../luckyclient/remote/api/GetServerApi.java | 96 +- .../luckyclient/remote/api/PostServerApi.java | 65 +- .../remote/api/serverOperation.java | 524 +++---- .../remote/entity/monitor/IpUtils.java | 397 +++--- .../remote/entity/monitor/Server.java | 474 ++++--- .../tool/jenkins/BuildingInitialization.java | 146 +- .../tool/jenkins/JenkinsConnect.java | 136 +- .../luckyclient/tool/jenkins/JobBuildApi.java | 188 +-- .../shell/RestartServerInitialization.java | 90 +- .../tool/shell/RmtShellExecutor.java | 184 ++- .../java/luckyclient/utils/DateUtils.java | 323 +++-- .../java/luckyclient/utils/DbOperation.java | 234 ++-- .../java/luckyclient/utils/DbToolkit.java | 16 +- .../java/luckyclient/utils/JarClassFind.java | 159 +-- src/main/java/luckyclient/utils/LogUtil.java | 111 +- .../utils/config/AppiumConfig.java | 63 +- .../utils/config/DrivenConfig.java | 71 +- .../utils/httputils/HttpRequest.java | 46 +- .../utils/httputils/MyX509TrustManager.java | 70 +- src/main/java/springboot/HttpImpl.java | 116 +- 76 files changed, 8036 insertions(+), 8267 deletions(-) delete mode 100644 src/main/java/luckyclient/execution/webdriver/TestGoogle.java diff --git a/src/main/java/luckyclient/driven/DbDriven.java b/src/main/java/luckyclient/driven/DbDriven.java index 7f94a42..01e395a 100644 --- a/src/main/java/luckyclient/driven/DbDriven.java +++ b/src/main/java/luckyclient/driven/DbDriven.java @@ -1,37 +1,49 @@ -package luckyclient.driven; - -import java.util.Properties; - -import luckyclient.utils.DbOperation; -import luckyclient.utils.config.DrivenConfig; - -/** - * 提供数据库查询操作的默认测试驱动 - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull - * ================================================================= - * @author Seagull - * @date 2020年2月17日 - */ -public class DbDriven { - - public String executeSql(String sql) throws Exception{ - Properties properties = DrivenConfig.getConfiguration(); - String url = properties.getProperty("db.url"); - String username = properties.getProperty("db.username"); - String password = properties.getProperty("db.password"); - DbOperation db=new DbOperation(url,username,password); - return db.executeQuery(sql); - } - - public String executeQuery(String sql) throws Exception{ - Properties properties = DrivenConfig.getConfiguration(); - String url = properties.getProperty("db.url"); - String username = properties.getProperty("db.username"); - String password = properties.getProperty("db.password"); - DbOperation db=new DbOperation(url,username,password); - return db.executeQuery(sql); - } - -} +package luckyclient.driven; + +import java.util.Properties; + +import luckyclient.utils.DbOperation; +import luckyclient.utils.config.DrivenConfig; + +/** + * 提供数据库查询操作的默认测试驱动 + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull + * ================================================================= + * @author Seagull + * @date 2020年2月17日 + */ +public class DbDriven { + + /** + * 执行SQL语句 + * @param sql 执行SQL语句 + * @return 返回执行结果条数才及提示 + * @throws Exception 抛异常 + */ + public String executeSql(String sql) throws Exception{ + Properties properties = DrivenConfig.getConfiguration(); + String url = properties.getProperty("db.url"); + String username = properties.getProperty("db.username"); + String password = properties.getProperty("db.password"); + DbOperation db=new DbOperation(url,username,password); + return db.executeSql(sql); + } + + /** + * 查询SQL语句 + * @param sql 查询SQL + * @return 返回查询结果 + * @throws Exception 异常信息 + */ + public String executeQuery(String sql) throws Exception{ + Properties properties = DrivenConfig.getConfiguration(); + String url = properties.getProperty("db.url"); + String username = properties.getProperty("db.username"); + String password = properties.getProperty("db.password"); + DbOperation db=new DbOperation(url,username,password); + return db.executeQuery(sql); + } + +} diff --git a/src/main/java/luckyclient/driven/SubString.java b/src/main/java/luckyclient/driven/SubString.java index 307bf00..ca7e2a5 100644 --- a/src/main/java/luckyclient/driven/SubString.java +++ b/src/main/java/luckyclient/driven/SubString.java @@ -1,5 +1,6 @@ package luckyclient.driven; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; @@ -32,10 +33,10 @@ public class SubString { /** * 截取指定字符串的中间字段 * - * @param str - * @param startstr - * @param endstr - * @return + * @param str 原始字符串 + * @param startstr 开始字符 + * @param endstr 结束字符 + * @return 返回字符串截取结果 */ public static String subCentreStr(String str, String startstr, String endstr) { try{ @@ -47,8 +48,7 @@ public class SubString { if(!"".equals(endstr)){ endnum=str.indexOf(endstr, str.indexOf(startstr) + startstr.length()); } - String getstr = str.substring(startnum,endnum); - return getstr; + return str.substring(startnum,endnum); }catch(Exception e){ LogUtil.APP.error("subCentreStr截取字符串出现异常,请检查参数!",e); return "截取字符串出现异常,请检查参数!"; @@ -58,14 +58,13 @@ public class SubString { /** * 截取字符串从指定字符开始 * - * @param str - * @param startstr - * @return + * @param str 原始字符 + * @param startstr 开始字符 + * @return 返回字符串截取结果 */ public static String subStartStr(String str, String startstr) { try{ - String getstr = str.substring(str.indexOf(startstr) + startstr.length()); - return getstr; + return str.substring(str.indexOf(startstr) + startstr.length()); }catch(Exception e){ LogUtil.APP.error("subStartStr截取字符串出现异常,请检查参数!",e); return "截取字符串出现异常,请检查参数!"; @@ -75,14 +74,13 @@ public class SubString { /** * 截取字符串到指定字符结束 * - * @param str - * @param endstr - * @return + * @param str 原始字符 + * @param endstr 结束字符 + * @return 返回字符串截取结果 */ public static String subEndStr(String str, String endstr) { try{ - String getstr = str.substring(0, str.indexOf(endstr)); - return getstr; + return str.substring(0, str.indexOf(endstr)); }catch(Exception e){ LogUtil.APP.error("subEndStr截取字符串出现异常,请检查参数!",e); return "截取字符串出现异常,请检查参数!"; @@ -92,13 +90,13 @@ public class SubString { /** * 通过字符串位置截取指定字符串的中间字段 * - * @param str - * @param startnum - * @param endnum - * @return + * @param str 原始字符 + * @param startnum 开始字符位置 + * @param endnum 结果位置 + * @return 返回字符串截取结果 */ public static String subCentreNum(String str, String startnum, String endnum) { - String getstr = ""; + String getstr; if("".equals(startnum)){ startnum="0"; } @@ -107,11 +105,11 @@ public class SubString { } try{ if (isInteger(startnum) && isInteger(endnum)) { - int start = Integer.valueOf(startnum); - int end = Integer.valueOf(endnum); + int start = Integer.parseInt(startnum); + int end = Integer.parseInt(endnum); if (start > end) { getstr = "截取字符串开始位置数字不能大于结束位置数字"; - } else if (start < 0 || end < 0) { + } else if (start < 0) { getstr = "截取字符串位置的数字不能小于0"; } else if (start > str.length() || end > str.length()) { getstr = "截取字符串位置的数字不能大于字符串本身的长度【" + str.length() + "】"; @@ -132,15 +130,15 @@ public class SubString { /** * 通过字符串位置截取字符串从指定字符开始 * - * @param str - * @param startnum - * @return + * @param str 原始字符 + * @param startnum 字符开始位置 + * @return 返回字符串截取结果 */ public static String subStartNum(String str, String startnum) { - String getstr = ""; + String getstr; try{ if (isInteger(startnum)) { - int start = Integer.valueOf(startnum); + int start = Integer.parseInt(startnum); if (start < 0) { getstr = "截取字符串位置的数字不能小于0"; } else if (start > str.length()) { @@ -162,15 +160,15 @@ public class SubString { /** * 截取字符串到指定字符结束 * - * @param str - * @param endnum - * @return + * @param str 原始字符 + * @param endnum 结束位置 + * @return 返回字符串截取结果 */ public static String subEndNum(String str, String endnum) { - String getstr = ""; + String getstr; try{ if (isInteger(endnum)) { - int end = Integer.valueOf(endnum); + int end = Integer.parseInt(endnum); if (end < 0) { getstr = "截取字符串位置的数字不能小于0"; } else if (end > str.length()) { @@ -189,8 +187,15 @@ public class SubString { } } + /** + * 正则匹配字符串 + * @param str 原始字符串 + * @param rgex 正则表达式 + * @param num 字符索引 + * @return 匹配到的字符串 + */ public static String subStrRgex(String str, String rgex, String num) { - List list = new ArrayList(); + List list = new ArrayList<>(); try{ // 匹配的模式 Pattern pattern = Pattern.compile(rgex); @@ -201,9 +206,9 @@ public class SubString { // i++; } - String getstr = ""; + String getstr; if (isInteger(num)) { - int index = Integer.valueOf(num); + int index = Integer.parseInt(num); if (index < 0) { getstr = "截取字符串索引数字不能小于0"; } else if (index > str.length()) { @@ -223,8 +228,13 @@ public class SubString { } } + /** + * 判断是否是整型数字 + * @param str 整形字符 + * @return 返回布尔型结果 + */ private static boolean isInteger(String str) { - String patternStr="^[-\\+]?[\\d]*$"; + String patternStr="^[-+]?[\\d]*$"; Pattern pattern = Pattern.compile(patternStr); return pattern.matcher(str).matches(); } @@ -241,11 +251,10 @@ public class SubString { /** * 遍历JSON对象 - * - * @param json - * @param key - * @param keyindex - * @return + * @param json 原始JSON + * @param key 查询key值 + * @param keyindex key值索引 + * @return 返回json对象 */ private static JSONObject parseJsonString(String json, String key, int keyindex) { LinkedHashMap jsonMap = JSON.parseObject(json, @@ -259,14 +268,12 @@ public class SubString { /** * 遍历后JSON对象中的key以及value - * - * @param entry - * @param key - * @param keyindex - * @return + * @param entry json中所有的的key以及value + * @param key 需要提取的key + * @param keyindex 提取key的索引 */ @SuppressWarnings({ "unchecked", "rawtypes" }) - private static Map.Entry parseJsonMap(Map.Entry entry, String key, int keyindex) { + private static void parseJsonMap(Map.Entry entry, String key, int keyindex) { // 如果是单个map继续遍历 if (entry.getValue() instanceof Map) { LinkedHashMap jsonMap = JSON.parseObject(entry.getValue().toString(), @@ -304,23 +311,22 @@ public class SubString { COUNTER++; } - return entry; } /** * 获取JSON或是JSONArray对象指定序号Key中的Value * - * @param json - * @param key - * @param indexstr - * @return + * @param json 原始JSON + * @param key 指定key + * @param indexstr key的索引 + * @return 返回指定key的value字符 */ public static String getJsonValue(String json, String key, String indexstr) { json = json.trim(); - int index = 1; + int index; String result = JSONVALUE; if (isInteger(indexstr) && !"0".equals(indexstr)) { - index = Integer.valueOf(indexstr); + index = Integer.parseInt(indexstr); } else { result = JSONVALUE + "指定的key值序号不是大于0的整数(序号从1开始),请检查!"; return result; @@ -339,7 +345,7 @@ public class SubString { try { // JSONArray jsonarr = JSONArray.parseArray(json); // 直接使用fastjson的接口实现有序解析 - JSONArray jsonarr = JSONArray.parseObject(json.getBytes("UTF-8"), JSONArray.class, Feature.OrderedField); + JSONArray jsonarr = JSONArray.parseObject(json.getBytes(StandardCharsets.UTF_8), JSONArray.class, Feature.OrderedField); for (int i = 0; i < jsonarr.size(); i++) { JSONObject jsonStr = jsonarr.getJSONObject(i); parseJsonString(jsonStr.toJSONString(), key, index); @@ -367,14 +373,14 @@ public class SubString { /** * 通过jsonPath表达式获取JSON字符串指定值 - * @param expressionParams - * @param jsonString - * @return + * @param expressionParams jsonPath表达式 + * @param jsonString json原始字符串 + * @return 返回提取到手字符 * @author Seagull * @date 2019年8月28日 */ public static String jsonPathGetParams(String expressionParams, String jsonString) { - String type="String"; + String type; String expression=""; if(expressionParams.endsWith("]")&&expressionParams.contains("[")){ try{ @@ -394,7 +400,7 @@ public class SubString { List list = JsonPath.parse(jsonString).read(expression); jsonString=""; for(Object result:list){ - result = (String)jsonString+result+","; + result = jsonString +result+","; jsonString = (String)result; } }else{ @@ -403,7 +409,7 @@ public class SubString { }catch(PathNotFoundException pnfe){ LogUtil.APP.error("通过jsonPath获取JSON字符串指定值出现异常,没有找到对应参数路径,请确认JSON字符串【{}】表达式是否正确【{}】!",jsonString,expression); }catch(Exception e){ - LogUtil.APP.error("通过jsonPath获取JSON字符串指定值出现异,请检查您的动作参数格式(String/List[表达式])或是被提取的json字符串是否正常!",expressionParams); + LogUtil.APP.error("通过jsonPath获取JSON字符串指定值出现异常,请检查您的动作参数格式(String/List[表达式])或是被提取的json字符串是否正常!"); } }else{ LogUtil.APP.warn("获取JSON字符串指定jsonPath表达式【{}】异常,请检查您的动作参数格式(String/List[表达式])是否正常!",expressionParams); @@ -411,5 +417,4 @@ public class SubString { LogUtil.APP.info("获取JSON字符串指定jsonPath表达式【{}】的值是:{}",expression,jsonString); return jsonString; } - } diff --git a/src/main/java/luckyclient/execution/BatchCaseExecute.java b/src/main/java/luckyclient/execution/BatchCaseExecute.java index 111ec64..6b03323 100644 --- a/src/main/java/luckyclient/execution/BatchCaseExecute.java +++ b/src/main/java/luckyclient/execution/BatchCaseExecute.java @@ -1,68 +1,68 @@ -package luckyclient.execution; - -import java.io.File; -import java.util.Properties; - -import org.apache.log4j.PropertyConfigurator; - -import luckyclient.execution.appium.androidex.AndroidBatchExecute; -import luckyclient.execution.appium.iosex.IosBatchExecute; -import luckyclient.execution.httpinterface.BatchTestCaseExecution; -import luckyclient.execution.httpinterface.TestControl; -import luckyclient.execution.webdriver.ex.WebBatchExecute; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.entity.TaskExecute; -import luckyclient.remote.entity.TaskScheduling; -import luckyclient.utils.LogUtil; -import luckyclient.utils.config.AppiumConfig; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * - * @date 2017年12月1日 上午9:29:40 - * - */ -public class BatchCaseExecute extends TestControl { - - public static void main(String[] args) { - // TODO Auto-generated method stub - try { - PropertyConfigurator.configure(System.getProperty("user.dir") + File.separator + "log4j.conf"); - String taskid = args[0]; - String batchcase = args[1]; - TaskExecute task = GetServerApi.cgetTaskbyid(Integer.valueOf(taskid)); - TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(Integer.valueOf(taskid)); - if (taskScheduling.getTaskType() == 0) { - BatchTestCaseExecution.batchCaseExecuteForTast(taskScheduling.getProject().getProjectName(), - String.valueOf(task.getTaskId()), batchcase); - } else if (taskScheduling.getTaskType() == 1) { - // UI测试 - WebBatchExecute.batchCaseExecuteForTast(taskScheduling.getProject().getProjectName(), - String.valueOf(task.getTaskId()), batchcase); - - } else if (taskScheduling.getTaskType() == 2) { - Properties properties = AppiumConfig.getConfiguration(); - - if ("Android".equals(properties.getProperty("platformName"))) { - AndroidBatchExecute.batchCaseExecuteForTast(taskScheduling.getProject().getProjectName(), - String.valueOf(task.getTaskId()), batchcase); - } else if ("IOS".equals(properties.getProperty("platformName"))) { - IosBatchExecute.batchCaseExecuteForTast(taskScheduling.getProject().getProjectName(), - String.valueOf(task.getTaskId()), batchcase); - } - - } - } catch (Exception e) { - // TODO Auto-generated catch block - LogUtil.APP.error("启动批量运行用例主函数出现异常,请检查!",e); - } finally{ - System.exit(0); - } - } - -} +package luckyclient.execution; + +import java.io.File; +import java.util.Properties; + +import org.apache.log4j.PropertyConfigurator; + +import luckyclient.execution.appium.androidex.AndroidBatchExecute; +import luckyclient.execution.appium.iosex.IosBatchExecute; +import luckyclient.execution.httpinterface.BatchTestCaseExecution; +import luckyclient.execution.httpinterface.TestControl; +import luckyclient.execution.webdriver.ex.WebBatchExecute; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.entity.TaskExecute; +import luckyclient.remote.entity.TaskScheduling; +import luckyclient.utils.LogUtil; +import luckyclient.utils.config.AppiumConfig; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * + * @date 2017年12月1日 上午9:29:40 + * + */ +public class BatchCaseExecute extends TestControl { + + public static void main(String[] args) { + // TODO Auto-generated method stub + try { + PropertyConfigurator.configure(System.getProperty("user.dir") + File.separator + "log4j.conf"); + String taskid = args[0]; + String batchcase = args[1]; + TaskExecute task = GetServerApi.cgetTaskbyid(Integer.parseInt(taskid)); + TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(Integer.parseInt(taskid)); + if (taskScheduling.getTaskType() == 0) { + BatchTestCaseExecution.batchCaseExecuteForTast( + String.valueOf(task.getTaskId()), batchcase); + } else if (taskScheduling.getTaskType() == 1) { + // UI测试 + WebBatchExecute.batchCaseExecuteForTast( + String.valueOf(task.getTaskId()), batchcase); + + } else if (taskScheduling.getTaskType() == 2) { + Properties properties = AppiumConfig.getConfiguration(); + + if ("Android".equals(properties.getProperty("platformName"))) { + AndroidBatchExecute.batchCaseExecuteForTast( + String.valueOf(task.getTaskId()), batchcase); + } else if ("IOS".equals(properties.getProperty("platformName"))) { + IosBatchExecute.batchCaseExecuteForTast( + String.valueOf(task.getTaskId()), batchcase); + } + + } + } catch (Exception e) { + // TODO Auto-generated catch block + LogUtil.APP.error("启动批量运行用例主函数出现异常,请检查!",e); + } finally{ + System.exit(0); + } + } + +} diff --git a/src/main/java/luckyclient/execution/OneCaseExecute.java b/src/main/java/luckyclient/execution/OneCaseExecute.java index 63dfb10..bf4f3af 100644 --- a/src/main/java/luckyclient/execution/OneCaseExecute.java +++ b/src/main/java/luckyclient/execution/OneCaseExecute.java @@ -1,68 +1,66 @@ -package luckyclient.execution; - -import java.io.File; -import java.util.Properties; - -import org.apache.log4j.PropertyConfigurator; - -import luckyclient.execution.appium.androidex.AndroidOneCaseExecute; -import luckyclient.execution.appium.iosex.IosOneCaseExecute; -import luckyclient.execution.httpinterface.TestCaseExecution; -import luckyclient.execution.httpinterface.TestControl; -import luckyclient.execution.webdriver.ex.WebOneCaseExecute; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.entity.TaskExecute; -import luckyclient.remote.entity.TaskScheduling; -import luckyclient.utils.LogUtil; -import luckyclient.utils.config.AppiumConfig; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * - * @date 2017年12月1日 上午9:29:40 - * - */ -public class OneCaseExecute extends TestControl { - - public static void main(String[] args) throws Exception { - // TODO Auto-generated method stub - try{ - PropertyConfigurator.configure(System.getProperty("user.dir")+ File.separator +"log4j.conf"); - String taskId = args[0]; - String caseId = args[1]; - int version = Integer.parseInt(args[2]); - TaskExecute task = GetServerApi.cgetTaskbyid(Integer.valueOf(taskId)); - TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(Integer.valueOf(taskId)); - if (taskScheduling.getTaskType() == 0) { - // 接口测试 - TestCaseExecution testCaseExecution=new TestCaseExecution(); - testCaseExecution.oneCaseExecuteForTask(taskScheduling.getProject().getProjectName(), Integer.valueOf(caseId), String.valueOf(task.getTaskId())); - - } else if (taskScheduling.getTaskType() == 1) { - WebOneCaseExecute.oneCaseExecuteForTast(taskScheduling.getProject().getProjectName(), Integer.valueOf(caseId), version, - String.valueOf(task.getTaskId())); - - } else if (taskScheduling.getTaskType() == 2) { - Properties properties = AppiumConfig.getConfiguration(); - - if ("Android".equals(properties.getProperty("platformName"))) { - AndroidOneCaseExecute.oneCaseExecuteForTast(taskScheduling.getProject().getProjectName(), Integer.valueOf(caseId), - version, String.valueOf(task.getTaskId())); - } else if ("IOS".equals(properties.getProperty("platformName"))) { - IosOneCaseExecute.oneCaseExecuteForTast(taskScheduling.getProject().getProjectName(), Integer.valueOf(caseId), version, - String.valueOf(task.getTaskId())); - } - - } - }catch(Exception e){ - LogUtil.APP.error("启动单个用例运行主函数出现异常,请检查!",e); - } finally{ - System.exit(0); - } - } -} +package luckyclient.execution; + +import java.io.File; +import java.util.Properties; + +import org.apache.log4j.PropertyConfigurator; + +import luckyclient.execution.appium.androidex.AndroidOneCaseExecute; +import luckyclient.execution.appium.iosex.IosOneCaseExecute; +import luckyclient.execution.httpinterface.TestCaseExecution; +import luckyclient.execution.httpinterface.TestControl; +import luckyclient.execution.webdriver.ex.WebOneCaseExecute; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.entity.TaskExecute; +import luckyclient.remote.entity.TaskScheduling; +import luckyclient.utils.LogUtil; +import luckyclient.utils.config.AppiumConfig; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * + * @date 2017年12月1日 上午9:29:40 + * + */ +public class OneCaseExecute extends TestControl { + + public static void main(String[] args) { + try{ + PropertyConfigurator.configure(System.getProperty("user.dir")+ File.separator +"log4j.conf"); + String taskId = args[0]; + String caseId = args[1]; + TaskExecute task = GetServerApi.cgetTaskbyid(Integer.parseInt(taskId)); + TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(Integer.parseInt(taskId)); + if (taskScheduling.getTaskType() == 0) { + // 接口测试 + TestCaseExecution testCaseExecution=new TestCaseExecution(); + testCaseExecution.oneCaseExecuteForTask(Integer.valueOf(caseId), String.valueOf(task.getTaskId())); + + } else if (taskScheduling.getTaskType() == 1) { + WebOneCaseExecute.oneCaseExecuteForTast(Integer.valueOf(caseId), + String.valueOf(task.getTaskId())); + + } else if (taskScheduling.getTaskType() == 2) { + Properties properties = AppiumConfig.getConfiguration(); + + if ("Android".equals(properties.getProperty("platformName"))) { + AndroidOneCaseExecute.oneCaseExecuteForTast(Integer.valueOf(caseId), + String.valueOf(task.getTaskId())); + } else if ("IOS".equals(properties.getProperty("platformName"))) { + IosOneCaseExecute.oneCaseExecuteForTast(Integer.valueOf(caseId), + String.valueOf(task.getTaskId())); + } + + } + }catch(Exception e){ + LogUtil.APP.error("启动单个用例运行主函数出现异常,请检查!",e); + } finally{ + System.exit(0); + } + } +} diff --git a/src/main/java/luckyclient/execution/RunAutomationTest.java b/src/main/java/luckyclient/execution/RunAutomationTest.java index 47b36b4..80b33cf 100644 --- a/src/main/java/luckyclient/execution/RunAutomationTest.java +++ b/src/main/java/luckyclient/execution/RunAutomationTest.java @@ -1,50 +1,49 @@ -package luckyclient.execution; - -import java.io.File; - -import org.apache.log4j.PropertyConfigurator; - -import luckyclient.execution.appium.AppTestControl; -import luckyclient.execution.httpinterface.TestControl; -import luckyclient.execution.webdriver.WebTestControl; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.entity.TaskExecute; -import luckyclient.remote.entity.TaskScheduling; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * - * @date 2017年12月1日 上午9:29:40 - * - */ -public class RunAutomationTest extends TestControl { - public static void main(String[] args) { - // TODO Auto-generated method stub - try { - PropertyConfigurator.configure(System.getProperty("user.dir") + File.separator + "log4j.conf"); - String taskid = args[0]; - TaskExecute task = GetServerApi.cgetTaskbyid(Integer.valueOf(taskid)); - TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(Integer.valueOf(taskid)); - if (taskScheduling.getTaskType() == 0) { - // 接口测试 - TestControl.taskExecutionPlan(task); - } else if (taskScheduling.getTaskType() == 1) { - // UI测试 - WebTestControl.taskExecutionPlan(task); - } else if (taskScheduling.getTaskType() == 2) { - AppTestControl.taskExecutionPlan(task); - } - } catch (Exception e) { - // TODO Auto-generated catch block - LogUtil.APP.error("启动测试任务运行主函数出现异常,请检查!",e); - } finally{ - System.exit(0); - } - } -} +package luckyclient.execution; + +import java.io.File; + +import org.apache.log4j.PropertyConfigurator; + +import luckyclient.execution.appium.AppTestControl; +import luckyclient.execution.httpinterface.TestControl; +import luckyclient.execution.webdriver.WebTestControl; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.entity.TaskExecute; +import luckyclient.remote.entity.TaskScheduling; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * + * @date 2017年12月1日 上午9:29:40 + * + */ +public class RunAutomationTest extends TestControl { + public static void main(String[] args) { + try { + PropertyConfigurator.configure(System.getProperty("user.dir") + File.separator + "log4j.conf"); + String taskid = args[0]; + TaskExecute task = GetServerApi.cgetTaskbyid(Integer.parseInt(taskid)); + TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(Integer.parseInt(taskid)); + if (taskScheduling.getTaskType() == 0) { + // 接口测试 + TestControl.taskExecutionPlan(task); + } else if (taskScheduling.getTaskType() == 1) { + // UI测试 + WebTestControl.taskExecutionPlan(task); + } else if (taskScheduling.getTaskType() == 2) { + AppTestControl.taskExecutionPlan(task); + } + } catch (Exception e) { + // TODO Auto-generated catch block + LogUtil.APP.error("启动测试任务运行主函数出现异常,请检查!",e); + } finally{ + System.exit(0); + } + } +} diff --git a/src/main/java/luckyclient/execution/WebDebugExecute.java b/src/main/java/luckyclient/execution/WebDebugExecute.java index 2bc0b8d..2290e13 100644 --- a/src/main/java/luckyclient/execution/WebDebugExecute.java +++ b/src/main/java/luckyclient/execution/WebDebugExecute.java @@ -1,38 +1,36 @@ -package luckyclient.execution; - -import java.io.File; - -import org.apache.log4j.PropertyConfigurator; - -import luckyclient.execution.httpinterface.TestControl; -import luckyclient.execution.httpinterface.WebTestCaseDebug; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * @date 2017年12月1日 上午9:29:40 - * - */ -public class WebDebugExecute extends TestControl{ - - public static void main(String[] args) throws Exception { - // TODO Auto-generated method stub - try { - PropertyConfigurator.configure(System.getProperty("user.dir") + File.separator + "log4j.conf"); - String caseIdStr = args[0]; - String userIdStr = args[1]; - WebTestCaseDebug.oneCaseDebug(caseIdStr, userIdStr); - } catch (Exception e) { - // TODO: handle exception - LogUtil.APP.error("启动用例调试主函数出现异常,请检查!",e); - } finally{ - System.exit(0); - } - } -} +package luckyclient.execution; + +import java.io.File; + +import org.apache.log4j.PropertyConfigurator; + +import luckyclient.execution.httpinterface.TestControl; +import luckyclient.execution.httpinterface.WebTestCaseDebug; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * @date 2017年12月1日 上午9:29:40 + * + */ +public class WebDebugExecute extends TestControl{ + + public static void main(String[] args) { + try { + PropertyConfigurator.configure(System.getProperty("user.dir") + File.separator + "log4j.conf"); + String caseIdStr = args[0]; + String userIdStr = args[1]; + WebTestCaseDebug.oneCaseDebug(caseIdStr, userIdStr); + } catch (Exception e) { + LogUtil.APP.error("启动用例调试主函数出现异常,请检查!",e); + } finally{ + System.exit(0); + } + } +} diff --git a/src/main/java/luckyclient/execution/appium/AppDriverAnalyticCase.java b/src/main/java/luckyclient/execution/appium/AppDriverAnalyticCase.java index 99ff4d5..ea9cca4 100644 --- a/src/main/java/luckyclient/execution/appium/AppDriverAnalyticCase.java +++ b/src/main/java/luckyclient/execution/appium/AppDriverAnalyticCase.java @@ -1,184 +1,185 @@ -package luckyclient.execution.appium; - -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.lang3.StringUtils; - -import luckyclient.execution.dispose.ChangString; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.LogUtil; -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * @ClassName: AnalyticCase - * @Description: 解析单个用例中描述部分的脚本 - * @author: seagull - * @date 2016年9月18日 - * - */ -public class AppDriverAnalyticCase { - //private static String splitFlag = "\\|"; - - /** - * 移动端的用例步骤解析 - * @param projectcase - * @param step - * @param taskid - * @param caselog - * @return - * @author Seagull - * @date 2019年1月17日 - */ - public static Map analyticCaseStep(ProjectCase projectcase,ProjectCaseSteps step,String taskid,serverOperation caselog, Map variable){ - Map params = new HashMap(0); - - String resultstr = null; - try { - // 处理值传递 - String path = ChangString.changparams(step.getStepPath(), variable, "包路径|定位路径"); - if(null != path && path.contains("=")){ - String property = path.substring(0, path.indexOf("=")).trim(); - String propertyValue = path.substring(path.indexOf("=")+1, path.length()).trim(); - //set属性 - params.put("property", property.toLowerCase()); - //set属性值 - params.put("property_value", propertyValue); - LogUtil.APP.info("对象属性解析结果:property:{}; property_value:{}",property,propertyValue); - } - // set操作方法,处理值传递 - String operation = ChangString.changparams(step.getStepOperation().toLowerCase(), variable, "操作"); - params.put("operation", operation); - // set属性值,处理值传递 - String operationValue = ChangString.changparams(step.getStepParameters(), variable, "操作参数"); - if(StringUtils.isNotEmpty(operationValue)){ - //set属性值 - params.put("operation_value", operationValue); - } - LogUtil.APP.info("对象操作解析结果:operation:{}; operation_value:{}",operation,operationValue); - //获取预期结果字符串 - resultstr = step.getExpectedResult(); - - //set预期结果 - if(null==resultstr||"".equals(resultstr)){ - params.put("ExpectedResults", ""); - }else if(null!=resultstr){ - String expectedResults = subComment(resultstr); - - //处理check字段 - if(expectedResults.startsWith("check(")){ - params.put("checkproperty", expectedResults.substring(expectedResults.indexOf("check(")+6, expectedResults.indexOf("="))); - params.put("checkproperty_value", expectedResults.substring(expectedResults.indexOf("=")+1, expectedResults.lastIndexOf(")"))); - } - - //处理值传递 - expectedResults = ChangString.changparams(expectedResults, variable, "预期结果"); - params.put("ExpectedResults", expectedResults); - LogUtil.APP.info("预期结果解析:ExpectedResults:{}",expectedResults); - } - - LogUtil.APP.info("用例编号:{} 步骤编号:{} 解析自动化用例步骤脚本完成!",projectcase.getCaseSign(),step.getStepSerialNumber()); - if(null!=caselog){ - caselog.insertTaskCaseLog(taskid, projectcase.getCaseId(),"步骤编号:"+step.getStepSerialNumber()+" 解析自动化用例步骤脚本完成!","info",String.valueOf(step.getStepSerialNumber()),""); - } - }catch(Exception e) { - if(null!=caselog){ - caselog.insertTaskCaseLog(taskid, projectcase.getCaseId(),"步骤编号:"+step.getStepSerialNumber()+" 解析自动化用例步骤脚本出错!","error",String.valueOf(step.getStepSerialNumber()),""); - } - LogUtil.APP.error("用例编号:{} 步骤编号:{} 解析自动化用例步骤脚本出错!",projectcase.getCaseSign(),step.getStepSerialNumber(),e); - params.put("exception","用例编号:"+projectcase.getCaseSign()+"|解析异常,用例步骤为空或是用例脚本错误!"); - return params; - } - return params; - } - - private static String subComment(String htmlStr) throws InterruptedException{ - // 定义script的正则表达式 - String regExScript = "]*?>[\\s\\S]*?<\\/script>"; - // 定义style的正则表达式 - String regExStyle = "]*?>[\\s\\S]*?<\\/style>"; - // 定义HTML标签的正则表达式 - String regExHtml = "<[^>]+>"; - //定义空格回车换行符 - String regExSpace = "\t|\r|\n"; - - String scriptstr = null; - if (htmlStr!=null) { - Pattern pScript = Pattern.compile(regExScript, Pattern.CASE_INSENSITIVE); - Matcher mScript = pScript.matcher(htmlStr); - // 过滤script标签 - htmlStr = mScript.replaceAll(""); - - Pattern pStyle = Pattern.compile(regExStyle, Pattern.CASE_INSENSITIVE); - Matcher mStyle = pStyle.matcher(htmlStr); - // 过滤style标签 - htmlStr = mStyle.replaceAll(""); - - Pattern pHtml = Pattern.compile(regExHtml, Pattern.CASE_INSENSITIVE); - Matcher mHtml = pHtml.matcher(htmlStr); - // 过滤html标签 - htmlStr = mHtml.replaceAll(""); - - Pattern pSpace = Pattern.compile(regExSpace, Pattern.CASE_INSENSITIVE); - Matcher mSpace = pSpace.matcher(htmlStr); - // 过滤空格回车标签 - htmlStr = mSpace.replaceAll(""); - - } - if(htmlStr.indexOf("/*")>-1&&htmlStr.indexOf("*/")>-1){ - String commentstr = htmlStr.substring(htmlStr.trim().indexOf("/*"),htmlStr.indexOf("*/")+2); - //去注释 - scriptstr = htmlStr.replace(commentstr, ""); - }else{ - scriptstr = htmlStr; - } - //去掉字符串前后的空格 - scriptstr = trimInnerSpaceStr(scriptstr); - //替换空格转义 - scriptstr = scriptstr.replaceAll(" ", " "); - //转义双引号 - scriptstr = scriptstr.replaceAll(""", "\""); - //转义单引号 - scriptstr = scriptstr.replaceAll("'", "\'"); - //转义链接符 - scriptstr = scriptstr.replaceAll("&", "&"); - scriptstr = scriptstr.replaceAll("<", "<"); - scriptstr = scriptstr.replaceAll(">", ">"); - - return scriptstr; - } - - /*** - * 去掉字符串前后的空格,中间的空格保留 - * @param str - * @return - */ - public static String trimInnerSpaceStr(String str) { - str = str.trim(); - while (str.startsWith(" ")) { - str = str.substring(1, str.length()).trim(); - } - while (str.startsWith(" ")) { - str = str.substring(6, str.length()).trim(); - } - while (str.endsWith(" ")) { - str = str.substring(0, str.length() - 1).trim(); - } - while (str.endsWith(" ")) { - str = str.substring(0, str.length() - 6).trim(); - } - return str; - } - - public static void main(String[] args){ - // TODO Auto-generated method stub - } - -} +package luckyclient.execution.appium; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; + +import luckyclient.execution.dispose.ChangString; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.LogUtil; +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * @ClassName: AnalyticCase + * @Description: 解析单个用例中描述部分的脚本 + * @author: seagull + * @date 2016年9月18日 + * + */ +public class AppDriverAnalyticCase { + //private static String splitFlag = "\\|"; + + /** + * 移动端的用例步骤解析 + * @param projectcase 用例对象 + * @param step 步骤对象 + * @param taskid 任务ID + * @param caselog 日志操作 + * @return 返回步骤分析对象MAP + * @author Seagull + * @date 2019年1月17日 + */ + public static Map analyticCaseStep(ProjectCase projectcase,ProjectCaseSteps step,String taskid,serverOperation caselog, Map variable){ + Map params = new HashMap<>(0); + + String resultstr; + try { + // 处理值传递 + String path = ChangString.changparams(step.getStepPath(), variable, "包路径|定位路径"); + if(null != path && path.contains("=")){ + String property = path.substring(0, path.indexOf("=")).trim(); + String propertyValue = path.substring(path.indexOf("=")+1).trim(); + //set属性 + params.put("property", property.toLowerCase()); + //set属性值 + params.put("property_value", propertyValue); + LogUtil.APP.info("对象属性解析结果:property:{}; property_value:{}",property,propertyValue); + } + // set操作方法,处理值传递 + String operation = ChangString.changparams(step.getStepOperation().toLowerCase(), variable, "操作"); + params.put("operation", operation); + // set属性值,处理值传递 + String operationValue = ChangString.changparams(step.getStepParameters(), variable, "操作参数"); + if(StringUtils.isNotEmpty(operationValue)){ + //set属性值 + params.put("operation_value", operationValue); + } + LogUtil.APP.info("对象操作解析结果:operation:{}; operation_value:{}",operation,operationValue); + //获取预期结果字符串 + resultstr = step.getExpectedResult(); + + //set预期结果 + if(null==resultstr||"".equals(resultstr)){ + params.put("ExpectedResults", ""); + }else { + String expectedResults = subComment(resultstr); + + //处理check字段 + if(expectedResults.startsWith("check(")){ + params.put("checkproperty", expectedResults.substring(expectedResults.indexOf("check(")+6, expectedResults.indexOf("="))); + params.put("checkproperty_value", expectedResults.substring(expectedResults.indexOf("=")+1, expectedResults.lastIndexOf(")"))); + } + + //处理值传递 + expectedResults = ChangString.changparams(expectedResults, variable, "预期结果"); + params.put("ExpectedResults", expectedResults); + LogUtil.APP.info("预期结果解析:ExpectedResults:{}",expectedResults); + } + + LogUtil.APP.info("用例编号:{} 步骤编号:{} 解析自动化用例步骤脚本完成!",projectcase.getCaseSign(),step.getStepSerialNumber()); + if(null!=caselog){ + caselog.insertTaskCaseLog(taskid, projectcase.getCaseId(),"步骤编号:"+step.getStepSerialNumber()+" 解析自动化用例步骤脚本完成!","info",String.valueOf(step.getStepSerialNumber()),""); + } + }catch(Exception e) { + if(null!=caselog){ + caselog.insertTaskCaseLog(taskid, projectcase.getCaseId(),"步骤编号:"+step.getStepSerialNumber()+" 解析自动化用例步骤脚本出错!","error",String.valueOf(step.getStepSerialNumber()),""); + } + LogUtil.APP.error("用例编号:{} 步骤编号:{} 解析自动化用例步骤脚本出错!",projectcase.getCaseSign(),step.getStepSerialNumber(),e); + params.put("exception","用例编号:"+projectcase.getCaseSign()+"|解析异常,用例步骤为空或是用例脚本错误!"); + return params; + } + return params; + } + + private static String subComment(String htmlStr) { + // 定义script的正则表达式 + String regExScript = "]*?>[\\s\\S]*?"; + // 定义style的正则表达式 + String regExStyle = "]*?>[\\s\\S]*?"; + // 定义HTML标签的正则表达式 + String regExHtml = "<[^>]+>"; + //定义空格回车换行符 + String regExSpace = "[\t\r\n]"; + + String scriptstr; + if (htmlStr!=null) { + Pattern pScript = Pattern.compile(regExScript, Pattern.CASE_INSENSITIVE); + Matcher mScript = pScript.matcher(htmlStr); + // 过滤script标签 + htmlStr = mScript.replaceAll(""); + + Pattern pStyle = Pattern.compile(regExStyle, Pattern.CASE_INSENSITIVE); + Matcher mStyle = pStyle.matcher(htmlStr); + // 过滤style标签 + htmlStr = mStyle.replaceAll(""); + + Pattern pHtml = Pattern.compile(regExHtml, Pattern.CASE_INSENSITIVE); + Matcher mHtml = pHtml.matcher(htmlStr); + // 过滤html标签 + htmlStr = mHtml.replaceAll(""); + + Pattern pSpace = Pattern.compile(regExSpace, Pattern.CASE_INSENSITIVE); + Matcher mSpace = pSpace.matcher(htmlStr); + // 过滤空格回车标签 + htmlStr = mSpace.replaceAll(""); + + } + assert htmlStr != null; + if(htmlStr.contains("/*") && htmlStr.contains("*/")){ + String commentstr = htmlStr.substring(htmlStr.trim().indexOf("/*"),htmlStr.indexOf("*/")+2); + //去注释 + scriptstr = htmlStr.replace(commentstr, ""); + }else{ + scriptstr = htmlStr; + } + //去掉字符串前后的空格 + scriptstr = trimInnerSpaceStr(scriptstr); + //替换空格转义 + scriptstr = scriptstr.replaceAll(" ", " "); + //转义双引号 + scriptstr = scriptstr.replaceAll(""", "\""); + //转义单引号 + scriptstr = scriptstr.replaceAll("'", "'"); + //转义链接符 + scriptstr = scriptstr.replaceAll("&", "&"); + scriptstr = scriptstr.replaceAll("<", "<"); + scriptstr = scriptstr.replaceAll(">", ">"); + + return scriptstr; + } + + /** + * 去掉字符串前后的空格,中间的空格保留 + * @param str 原始字符串 + * @return 返回去掉空格后的字符串 + */ + public static String trimInnerSpaceStr(String str) { + str = str.trim(); + while (str.startsWith(" ")) { + str = str.substring(1).trim(); + } + while (str.startsWith(" ")) { + str = str.substring(6).trim(); + } + while (str.endsWith(" ")) { + str = str.substring(0, str.length() - 1).trim(); + } + while (str.endsWith(" ")) { + str = str.substring(0, str.length() - 6).trim(); + } + return str; + } + + public static void main(String[] args){ + // TODO Auto-generated method stub + } + +} diff --git a/src/main/java/luckyclient/execution/appium/AppTestControl.java b/src/main/java/luckyclient/execution/appium/AppTestControl.java index fbcce40..d9d099f 100644 --- a/src/main/java/luckyclient/execution/appium/AppTestControl.java +++ b/src/main/java/luckyclient/execution/appium/AppTestControl.java @@ -43,7 +43,7 @@ public class AppTestControl { /** * 控制台模式调度计划执行用例 - * @param planname + * @param planname 测试计划名称 */ public static void manualExecutionPlan(String planname) { // 不记日志到数据库 @@ -65,7 +65,7 @@ public class AppTestControl { } serverOperation caselog = new serverOperation(); List testCases = GetServerApi.getCasesbyplanname(planname); - List pcplist = new ArrayList(); + List pcplist = new ArrayList<>(); if (testCases.size() != 0) { pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testCases.get(0).getProjectId())); } @@ -84,21 +84,18 @@ public class AppTestControl { } else if ("IOS".equals(properties.getProperty("platformName"))) { IosCaseExecution.caseExcution(testcase, steps, taskid, iosdriver, caselog, pcplist); } - } catch (InterruptedException e) { - // TODO Auto-generated catch block - LogUtil.APP.error("用户执行过程中抛出InterruptedException异常!", e); - - } catch (IOException e) { - // TODO Auto-generated catch block - LogUtil.APP.error("用户执行过程中抛出IOException异常!", e); + } catch (Exception e) { + LogUtil.APP.error("用户执行过程中抛出Exception异常!", e); } LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); } LogUtil.APP.info("当前项目测试计划中的用例已经全部执行完成..."); // 关闭APP以及appium会话 if ("Android".equals(properties.getProperty("platformName"))) { + assert androiddriver != null; androiddriver.closeApp(); } else if ("IOS".equals(properties.getProperty("platformName"))) { + assert iosdriver != null; iosdriver.closeApp(); } } @@ -113,7 +110,7 @@ public class AppTestControl { Properties properties = AppiumConfig.getConfiguration(); AppiumService as=null; //根据配置自动启动Appiume服务 - if(Boolean.valueOf(properties.getProperty("autoRunAppiumService"))){ + if(Boolean.parseBoolean(properties.getProperty("autoRunAppiumService"))){ as =new AppiumService(); as.start(); Thread.sleep(10000); @@ -127,7 +124,7 @@ public class AppTestControl { String jobname = GetServerApi.cGetTaskSchedulingByTaskId(task.getTaskId()).getSchedulingName(); int[] tastcount = null; // 判断是否要自动重启TOMCAT - if (restartstatus.indexOf("Status:true") > -1) { + if (restartstatus.contains("Status:true")) { // 判断是否构建是否成功 if (BuildResult.SUCCESS.equals(buildResult)) { try { @@ -161,22 +158,23 @@ public class AppTestControl { } else if ("IOS".equals(properties.getProperty("platformName"))) { IosCaseExecution.caseExcution(testcase, steps, taskId, iosdriver, caselog, pcplist); } - } catch (InterruptedException | IOException e) { - // TODO Auto-generated catch block + } catch (Exception e) { LogUtil.APP.error("用户执行过程中抛出异常!", e); } LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); } tastcount = serverOperation.updateTaskExecuteData(taskId, cases.size(),2); String testtime = serverOperation.getTestTime(taskId); - LogUtil.APP.info("当前项目【{]】测试计划中的用例已经全部执行完成...",projectname); + LogUtil.APP.info("当前项目【{}】测试计划中的用例已经全部执行完成...",projectname); MailSendInitialization.sendMailInitialization(HtmlMail.htmlSubjectFormat(jobname), HtmlMail.htmlContentFormat(tastcount, taskId, buildResult.toString(), restartstatus, testtime, jobname), taskId, taskScheduling, tastcount); // 关闭APP以及appium会话 if ("Android".equals(properties.getProperty("platformName"))) { + assert androiddriver != null; androiddriver.closeApp(); } else if ("IOS".equals(properties.getProperty("platformName"))) { + assert iosdriver != null; iosdriver.closeApp(); } } else { diff --git a/src/main/java/luckyclient/execution/appium/AppiumInitialization.java b/src/main/java/luckyclient/execution/appium/AppiumInitialization.java index 1647cc9..91afa8d 100644 --- a/src/main/java/luckyclient/execution/appium/AppiumInitialization.java +++ b/src/main/java/luckyclient/execution/appium/AppiumInitialization.java @@ -1,108 +1,110 @@ -package luckyclient.execution.appium; - -import java.io.File; -import java.io.IOException; -import java.net.URL; -import java.util.Properties; -import java.util.concurrent.TimeUnit; - -import org.openqa.selenium.remote.DesiredCapabilities; - -import io.appium.java_client.android.AndroidDriver; -import io.appium.java_client.android.AndroidElement; -import io.appium.java_client.ios.IOSDriver; -import io.appium.java_client.ios.IOSElement; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * - * @date 2017年12月1日 上午9:29:40 - * - */ -public class AppiumInitialization { - /** - * 初始化AndroidAppium - * - * @throws IOException - */ - public static AndroidDriver setAndroidAppium(Properties properties) throws IOException { - AndroidDriver appium = null; - DesiredCapabilities capabilities = new DesiredCapabilities(); - File directory = new File(""); - File app = new File(directory.getCanonicalPath() + File.separator + properties.getProperty("appname")); - capabilities.setCapability("app", app.getAbsolutePath()); - // 自动化测试服务 - capabilities.setCapability("automationName", properties.getProperty("automationName")); - // 设备名称 - capabilities.setCapability("deviceName", properties.getProperty("deviceName")); - // 平台类型 - capabilities.setCapability("platformName", properties.getProperty("platformName")); - // 系统版本 - capabilities.setCapability("platformVersion", properties.getProperty("platformVersion")); - // 模拟器上的ip地址 - capabilities.setCapability("udid", properties.getProperty("udid")); - // Android应用的包名 - capabilities.setCapability("appPackage", properties.getProperty("appPackage")); - // 启动的Android Activity - capabilities.setCapability("appActivity", properties.getProperty("appActivity")); - // 支持中文输入,会自动安装Unicode输入 - capabilities.setCapability("unicodeKeyboard", Boolean.valueOf(properties.getProperty("unicodeKeyboard"))); - // 重置输入法到原有状态 - capabilities.setCapability("resetKeyboard", Boolean.valueOf(properties.getProperty("resetKeyboard"))); - // 不重新签名apk - capabilities.setCapability("noSign", Boolean.valueOf(properties.getProperty("noSign"))); - // 是否避免重新安装APP - capabilities.setCapability("noReset", Boolean.valueOf(properties.getProperty("noReset"))); - // 等待超时没接收到命令关闭appium - capabilities.setCapability("newCommandTimeout", properties.getProperty("newCommandTimeout")); - String url="http://" + properties.getProperty("appiumsever") + "/wd/hub"; - appium = new AndroidDriver(new URL(url), capabilities); - int waittime = Integer.valueOf(properties.getProperty("implicitlyWait")); - appium.manage().timeouts().implicitlyWait(waittime, TimeUnit.SECONDS); - return appium; - } - - /** - * 初始化IOSAppium - * - * @throws IOException - */ - public static IOSDriver setIosAppium(Properties properties) throws IOException { - IOSDriver appium = null; - DesiredCapabilities capabilities = new DesiredCapabilities(); - File directory = new File(""); - File app = new File(directory.getCanonicalPath() + File.separator + properties.getProperty("appname")); - capabilities.setCapability("app", app.getAbsolutePath()); - // 自动化测试服务 - capabilities.setCapability("automationName", properties.getProperty("automationName")); - // 设备名称 - capabilities.setCapability("deviceName", properties.getProperty("deviceName")); - // 平台类型 - capabilities.setCapability("platformName", properties.getProperty("platformName")); - // 系统版本 - capabilities.setCapability("platformVersion", properties.getProperty("platformVersion")); - // 模拟器上的ip地址 - capabilities.setCapability("udid", properties.getProperty("udid")); - // 支持中文输入,会自动安装Unicode输入 - capabilities.setCapability("unicodeKeyboard", Boolean.valueOf(properties.getProperty("unicodeKeyboard"))); - // 重置输入法到原有状态 - capabilities.setCapability("resetKeyboard", Boolean.valueOf(properties.getProperty("resetKeyboard"))); - // 不重新签名apk - capabilities.setCapability("noSign", Boolean.valueOf(properties.getProperty("noSign"))); - // 是否避免重新安装APP - capabilities.setCapability("noReset", Boolean.valueOf(properties.getProperty("noReset"))); - // 等待超时没接收到命令关闭appium - capabilities.setCapability("newCommandTimeout", properties.getProperty("newCommandTimeout")); - String url="http://" + properties.getProperty("appiumsever") + "/wd/hub"; - appium = new IOSDriver(new URL(url),capabilities); - int waittime = Integer.valueOf(properties.getProperty("implicitlyWait")); - appium.manage().timeouts().implicitlyWait(waittime, TimeUnit.SECONDS); - return appium; - } - -} +package luckyclient.execution.appium; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Properties; +import java.util.concurrent.TimeUnit; + +import org.openqa.selenium.remote.DesiredCapabilities; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.IOSElement; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * + * @date 2017年12月1日 上午9:29:40 + * + */ +public class AppiumInitialization { + /** + * 初始化AndroidAppium + * @param properties 配置文件对象 + * @return 返回安卓appium对象 + * @throws IOException 抛异常 + */ + public static AndroidDriver setAndroidAppium(Properties properties) throws IOException { + AndroidDriver appium; + DesiredCapabilities capabilities = new DesiredCapabilities(); + File directory = new File(""); + File app = new File(directory.getCanonicalPath() + File.separator + properties.getProperty("appname")); + capabilities.setCapability("app", app.getAbsolutePath()); + // 自动化测试服务 + capabilities.setCapability("automationName", properties.getProperty("automationName")); + // 设备名称 + capabilities.setCapability("deviceName", properties.getProperty("deviceName")); + // 平台类型 + capabilities.setCapability("platformName", properties.getProperty("platformName")); + // 系统版本 + capabilities.setCapability("platformVersion", properties.getProperty("platformVersion")); + // 模拟器上的ip地址 + capabilities.setCapability("udid", properties.getProperty("udid")); + // Android应用的包名 + capabilities.setCapability("appPackage", properties.getProperty("appPackage")); + // 启动的Android Activity + capabilities.setCapability("appActivity", properties.getProperty("appActivity")); + // 支持中文输入,会自动安装Unicode输入 + capabilities.setCapability("unicodeKeyboard", Boolean.valueOf(properties.getProperty("unicodeKeyboard"))); + // 重置输入法到原有状态 + capabilities.setCapability("resetKeyboard", Boolean.valueOf(properties.getProperty("resetKeyboard"))); + // 不重新签名apk + capabilities.setCapability("noSign", Boolean.valueOf(properties.getProperty("noSign"))); + // 是否避免重新安装APP + capabilities.setCapability("noReset", Boolean.valueOf(properties.getProperty("noReset"))); + // 等待超时没接收到命令关闭appium + capabilities.setCapability("newCommandTimeout", properties.getProperty("newCommandTimeout")); + String url="http://" + properties.getProperty("appiumsever") + "/wd/hub"; + appium = new AndroidDriver<>(new URL(url), capabilities); + int waittime = Integer.parseInt(properties.getProperty("implicitlyWait")); + appium.manage().timeouts().implicitlyWait(waittime, TimeUnit.SECONDS); + return appium; + } + + /** + * 初始化IOSAppium + * @param properties 配置文件对象 + * @return 返回IOS appium对象 + * @throws IOException 抛出IO异常 + */ + public static IOSDriver setIosAppium(Properties properties) throws IOException { + IOSDriver appium; + DesiredCapabilities capabilities = new DesiredCapabilities(); + File directory = new File(""); + File app = new File(directory.getCanonicalPath() + File.separator + properties.getProperty("appname")); + capabilities.setCapability("app", app.getAbsolutePath()); + // 自动化测试服务 + capabilities.setCapability("automationName", properties.getProperty("automationName")); + // 设备名称 + capabilities.setCapability("deviceName", properties.getProperty("deviceName")); + // 平台类型 + capabilities.setCapability("platformName", properties.getProperty("platformName")); + // 系统版本 + capabilities.setCapability("platformVersion", properties.getProperty("platformVersion")); + // 模拟器上的ip地址 + capabilities.setCapability("udid", properties.getProperty("udid")); + // 支持中文输入,会自动安装Unicode输入 + capabilities.setCapability("unicodeKeyboard", Boolean.valueOf(properties.getProperty("unicodeKeyboard"))); + // 重置输入法到原有状态 + capabilities.setCapability("resetKeyboard", Boolean.valueOf(properties.getProperty("resetKeyboard"))); + // 不重新签名apk + capabilities.setCapability("noSign", Boolean.valueOf(properties.getProperty("noSign"))); + // 是否避免重新安装APP + capabilities.setCapability("noReset", Boolean.valueOf(properties.getProperty("noReset"))); + // 等待超时没接收到命令关闭appium + capabilities.setCapability("newCommandTimeout", properties.getProperty("newCommandTimeout")); + String url="http://" + properties.getProperty("appiumsever") + "/wd/hub"; + appium = new IOSDriver<>(new URL(url), capabilities); + int waittime = Integer.parseInt(properties.getProperty("implicitlyWait")); + appium.manage().timeouts().implicitlyWait(waittime, TimeUnit.SECONDS); + return appium; + } + +} diff --git a/src/main/java/luckyclient/execution/appium/AppiumService.java b/src/main/java/luckyclient/execution/appium/AppiumService.java index 7ee2d76..86ed927 100644 --- a/src/main/java/luckyclient/execution/appium/AppiumService.java +++ b/src/main/java/luckyclient/execution/appium/AppiumService.java @@ -1,48 +1,48 @@ -package luckyclient.execution.appium; - -import java.io.File; -import java.util.Properties; - -import io.appium.java_client.service.local.AppiumDriverLocalService; -import io.appium.java_client.service.local.AppiumServiceBuilder; -import io.appium.java_client.service.local.flags.GeneralServerFlag; -import luckyclient.utils.LogUtil; -import luckyclient.utils.config.AppiumConfig; - -/** - * - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull - * ================================================================= - * @author Seagull - * @date 2019年8月8日 - */ -public class AppiumService extends Thread{ - - @Override - public void run(){ - try{ - Properties properties = AppiumConfig.getConfiguration(); - File mainjsFile = new File(properties.getProperty("mainjsPath")); - String ip=properties.getProperty("appiumsever"); - AppiumServiceBuilder builder = - new AppiumServiceBuilder().withArgument(GeneralServerFlag.SESSION_OVERRIDE) - .withIPAddress(ip.split(":")[0].trim()) - .withAppiumJS(mainjsFile) - .usingPort(Integer.valueOf(ip.split(":")[1].trim())); - - AppiumDriverLocalService service = AppiumDriverLocalService.buildService(builder); - service.start(); - - if (service == null || !service.isRunning()){ - LogUtil.APP.warn("自动启动Appium服务失败,请检查!"); - }else{ - LogUtil.APP.info("自动启动Appium服务成功,监听IP:{} 监听端口:{}",ip.split(":")[0].trim(),ip.split(":")[1].trim()); - } - }catch(Exception e){ - LogUtil.APP.error("自动启动Appium服务抛出异常,请检查!",e); - } - } - -} +package luckyclient.execution.appium; + +import java.io.File; +import java.util.Properties; + +import io.appium.java_client.service.local.AppiumDriverLocalService; +import io.appium.java_client.service.local.AppiumServiceBuilder; +import io.appium.java_client.service.local.flags.GeneralServerFlag; +import luckyclient.utils.LogUtil; +import luckyclient.utils.config.AppiumConfig; + +/** + * + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull + * ================================================================= + * @author Seagull + * @date 2019年8月8日 + */ +public class AppiumService extends Thread{ + + @Override + public void run(){ + try{ + Properties properties = AppiumConfig.getConfiguration(); + File mainjsFile = new File(properties.getProperty("mainjsPath")); + String ip=properties.getProperty("appiumsever"); + AppiumServiceBuilder builder = + new AppiumServiceBuilder().withArgument(GeneralServerFlag.SESSION_OVERRIDE) + .withIPAddress(ip.split(":")[0].trim()) + .withAppiumJS(mainjsFile) + .usingPort(Integer.parseInt(ip.split(":")[1].trim())); + + AppiumDriverLocalService service = AppiumDriverLocalService.buildService(builder); + service.start(); + + if (!service.isRunning()){ + LogUtil.APP.warn("自动启动Appium服务失败,请检查!"); + }else{ + LogUtil.APP.info("自动启动Appium服务成功,监听IP:{} 监听端口:{}",ip.split(":")[0].trim(),ip.split(":")[1].trim()); + } + }catch(Exception e){ + LogUtil.APP.error("自动启动Appium服务抛出异常,请检查!",e); + } + } + +} diff --git a/src/main/java/luckyclient/execution/appium/CaseLocalDebug.java b/src/main/java/luckyclient/execution/appium/CaseLocalDebug.java index 8391af1..af5495b 100644 --- a/src/main/java/luckyclient/execution/appium/CaseLocalDebug.java +++ b/src/main/java/luckyclient/execution/appium/CaseLocalDebug.java @@ -1,73 +1,73 @@ -package luckyclient.execution.appium; - -import java.util.List; - -import io.appium.java_client.android.AndroidDriver; -import io.appium.java_client.android.AndroidElement; -import luckyclient.execution.appium.androidex.AndroidCaseExecution; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * @date 2017年12月1日 上午9:29:40 - * - */ -public class CaseLocalDebug{ - - /** - * 单个移动端用例调试 - * @param appium - * @param testCaseExternalId - * @author Seagull - * @date 2020年1月20日 - */ - public static void oneCasedebug(AndroidDriver appium,String testCaseExternalId){ - //不记录日志到数据库 - serverOperation.exetype = 1; - serverOperation caselog = new serverOperation(); - try { - ProjectCase testcase = GetServerApi.cgetCaseBysign(testCaseExternalId); - List pcplist=GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); - LogUtil.APP.info("开始执行用例:【{}】......",testCaseExternalId); - List steps=GetServerApi.getStepsbycaseid(testcase.getCaseId()); - AndroidCaseExecution.caseExcution(testcase, steps, "888888", appium, caselog, pcplist); - LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); - } catch (Exception e) { - LogUtil.APP.error("用户执行过程中抛出异常!", e); - } - //退出 - appium.quit(); - } - - /** - * 多个移动端用例调试 - * @param appium - * @param projectname - * @param addtestcase - * @author Seagull - * @date 2020年1月20日 - */ - public static void moreCaseDebug(AndroidDriver appium,String projectname,List addtestcase){ - System.out.println("当前调试用例总共:"+addtestcase.size()); - for(String testCaseExternalId:addtestcase) { - try{ - LogUtil.APP.info("开始调用方法,项目名:{},用例编号:{}",projectname,testCaseExternalId); - oneCasedebug(appium,testCaseExternalId); - }catch(Exception e){ - continue; - } - } - } - -} +package luckyclient.execution.appium; + +import java.util.List; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import luckyclient.execution.appium.androidex.AndroidCaseExecution; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * @date 2017年12月1日 上午9:29:40 + * + */ +public class CaseLocalDebug{ + + /** + * 单个移动端用例调试 + * @param appium appium初始化对象 + * @param testCaseExternalId 用例编号 + * @author Seagull + * @date 2020年1月20日 + */ + public static void oneCasedebug(AndroidDriver appium,String testCaseExternalId){ + //不记录日志到数据库 + serverOperation.exetype = 1; + serverOperation caselog = new serverOperation(); + try { + ProjectCase testcase = GetServerApi.cgetCaseBysign(testCaseExternalId); + List pcplist=GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); + LogUtil.APP.info("开始执行用例:【{}】......",testCaseExternalId); + List steps=GetServerApi.getStepsbycaseid(testcase.getCaseId()); + AndroidCaseExecution.caseExcution(testcase, steps, "888888", appium, caselog, pcplist); + LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); + } catch (Exception e) { + LogUtil.APP.error("用户执行过程中抛出异常!", e); + } + //退出 + appium.quit(); + } + + /** + * 多个移动端用例调试 + * @param appium appium对象 + * @param projectname 项目名 + * @param addtestcase 用例对象集 + * @author Seagull + * @date 2020年1月20日 + */ + public static void moreCaseDebug(AndroidDriver appium,String projectname,List addtestcase){ + System.out.println("当前调试用例总共:"+addtestcase.size()); + for(String testCaseExternalId:addtestcase) { + try{ + LogUtil.APP.info("开始调用方法,项目名:{},用例编号:{}",projectname,testCaseExternalId); + oneCasedebug(appium,testCaseExternalId); + }catch(Exception e){ + LogUtil.APP.info("运行用例 出现异常,用例编号:{}",testCaseExternalId); + } + } + } + +} diff --git a/src/main/java/luckyclient/execution/appium/androidex/AndroidBaseAppium.java b/src/main/java/luckyclient/execution/appium/androidex/AndroidBaseAppium.java index 1f7dd67..cbb466c 100644 --- a/src/main/java/luckyclient/execution/appium/androidex/AndroidBaseAppium.java +++ b/src/main/java/luckyclient/execution/appium/androidex/AndroidBaseAppium.java @@ -23,20 +23,15 @@ import luckyclient.utils.LogUtil; * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 * ================================================================= - * * @author: seagull - * * @date 2017年12月1日 上午9:29:40 - * */ public class AndroidBaseAppium { /** * 安卓手机报错截图 - * - * @param appium - * @param imagname - * @throws IOException + * @param appium appium初始化对象 + * @param imagname 截图名称 */ public static void screenShot(AndroidDriver appium, String imagname) { imagname = imagname + ".png"; @@ -64,33 +59,31 @@ public class AndroidBaseAppium { /** * appium不支持中文输入 参考了robotium的以js方式为元素直接设置value的做法 * 利用Selenium中Webdriver执行js方法实现中文输入 - * @param appium - * @param preferences - * @param value + * @param appium appium初始化对象 + * @param preferences 对象名称 + * @param value 传入值 */ public static void sendChinese(AndroidDriver appium, String preferences, String value) { - org.openqa.selenium.JavascriptExecutor jse = (org.openqa.selenium.JavascriptExecutor) appium; - jse.executeScript("document.getElementByName('" + preferences + "').value='" + value + "'"); + ((JavascriptExecutor) appium).executeScript("document.getElementByName('" + preferences + "').value='" + value + "'"); } /** - * js webview 支持4.1~4.4 - * @param appium - * @param sX - * @param sY - * @param eX - * @param eY - * @param duration - * @throws Exception + * js webview 支持4.1~4.4 页面滑动 + * @param appium appium初始化对象 + * @param sX 开始X坐标 + * @param sY 开始Y坐标 + * @param eX 结束X坐标 + * @param eY 结束Y坐标 + * @param duration 持续时间 */ public static void webViewSwipe(AndroidDriver appium, Double sX, Double sY, Double eX, Double eY, - Double duration) throws Exception { + Double duration) { JavascriptExecutor js; HashMap swipeObject; try { // 滑动 - js = (JavascriptExecutor) appium; - swipeObject = new HashMap(5); + js = appium; + swipeObject = new HashMap<>(5); swipeObject.put("startX", sX); swipeObject.put("startY", sY); swipeObject.put("endX", eX); @@ -100,23 +93,18 @@ public class AndroidBaseAppium { } catch (Exception e) { // TODO Auto-generated catch block LogUtil.APP.error("安卓手机滑动出现异常",e); - } finally { - // 释放变量 } - } /** * 调用 ADB直接滑动 支持4.1~4.4 - * @param appium - * @param sX - * @param sY - * @param eX - * @param eY - * @throws Exception + * @param appium appium初始化对象 + * @param sX 开始X坐标 + * @param sY 开始Y坐标 + * @param eX 结束X坐标 + * @param eY 结束Y坐标 */ - public static void adbSwipe(AndroidDriver appium, Double sX, Double sY, Double eX, Double eY) - throws Exception { + public static void adbSwipe(AndroidDriver appium, Double sX, Double sY, Double eX, Double eY) { int xLine; int yLine; int sX2; @@ -138,36 +126,30 @@ public class AndroidBaseAppium { } catch (Exception e) { // TODO Auto-generated catch block LogUtil.APP.error("安卓手机调用 ADB直接滑动出现异常",e); - } finally { - // 释放变量 } } /** * 屏幕点击事件 - * @param drivers - * @param x - * @param y - * @param duration + * @param drivers appium初始化对象 + * @param x 点击X坐标 + * @param y 点击Y坐标 + * @param duration 持续时间 */ public static void clickScreenForJs(AndroidDriver drivers, int x, int y, int duration) { - JavascriptExecutor js = (JavascriptExecutor) drivers; - HashMap tapObject = new HashMap(3); + HashMap tapObject = new HashMap<>(3); tapObject.put("x", x); tapObject.put("y", y); tapObject.put("duration", duration); - js.executeScript("mobile: tap", tapObject); + ((JavascriptExecutor) drivers).executeScript("mobile: tap", tapObject); } /** * 拖住页面按屏幕比例向上滑动(手指向下,页面向上) - * - * @param driver - * @param second - * 持续时间 - * @param num - * 滚动次数 + * @param driver appium初始化对象 + * @param second 持续时间 + * @param num 滚动次数 */ public static void swipePageUp(AndroidDriver driver, Double second, int num) { int nanos = (int) (second * 1000); @@ -184,10 +166,9 @@ public class AndroidBaseAppium { /** * 拖住页面按屏幕比例向下滑动(手指向上,页面向下) - * - * @param driver - * @param second - * @param num + * @param driver appium初始化对象 + * @param second 持续时间 + * @param num 滑动次数 */ public static void swipePageDown(AndroidDriver driver, Double second, int num) { int nanos = (int) (second * 1000); @@ -203,10 +184,9 @@ public class AndroidBaseAppium { /** * 拖住页面按屏幕比例向左滑动(手指向左,页面向左滚动) - * - * @param driver - * @param second - * @param num + * @param driver appium初始化对象 + * @param second 持续时间 + * @param num 滑动次数 */ public static void swipePageLeft(AndroidDriver driver, Double second, int num) { int nanos = (int) (second * 1000); @@ -222,10 +202,9 @@ public class AndroidBaseAppium { /** * 拖住页面按屏幕比例向右滑动(手指向右,页面向右) - * - * @param driver - * @param second - * @param num + * @param driver appium初始化对象 + * @param second 持续时间 + * @param num 滑动次数 */ public static void swipePageRight(AndroidDriver driver, Double second, int num) { int nanos = (int) (second * 1000); diff --git a/src/main/java/luckyclient/execution/appium/androidex/AndroidBatchExecute.java b/src/main/java/luckyclient/execution/appium/androidex/AndroidBatchExecute.java index 59c0dcb..57e0aee 100644 --- a/src/main/java/luckyclient/execution/appium/androidex/AndroidBatchExecute.java +++ b/src/main/java/luckyclient/execution/appium/androidex/AndroidBatchExecute.java @@ -1,97 +1,95 @@ -package luckyclient.execution.appium.androidex; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.List; -import java.util.Properties; - -import io.appium.java_client.android.AndroidDriver; -import io.appium.java_client.android.AndroidElement; -import luckyclient.execution.appium.AppiumInitialization; -import luckyclient.execution.appium.AppiumService; -import luckyclient.execution.httpinterface.TestControl; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.remote.entity.TaskExecute; -import luckyclient.utils.LogUtil; -import luckyclient.utils.config.AppiumConfig; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * - * @date 2018年1月26日 上午15:29:40 - * - */ -public class AndroidBatchExecute { - - public static void batchCaseExecuteForTast(String projectname, String taskid, String batchcase) throws IOException, InterruptedException { - // 记录日志到数据库 - serverOperation.exetype = 0; - TestControl.TASKID = taskid; - AndroidDriver ad = null; - AppiumService as=null; - try { - Properties properties = AppiumConfig.getConfiguration(); - //根据配置自动启动Appiume服务 - if(Boolean.valueOf(properties.getProperty("autoRunAppiumService"))){ - as =new AppiumService(); - as.start(); - Thread.sleep(10000); - } - - ad = AppiumInitialization.setAndroidAppium(properties); - } catch (MalformedURLException e) { - // TODO Auto-generated catch block - LogUtil.APP.error("安卓手机根据配置自动启动Appiume服务出现异常",e); - } - serverOperation caselog = new serverOperation(); - TaskExecute task = GetServerApi.cgetTaskbyid(Integer.valueOf(taskid)); - List pcplist = GetServerApi - .cgetParamsByProjectid(task.getProjectId().toString()); - // 执行全部非成功状态用例 - if (batchcase.indexOf("ALLFAIL") > -1) { - List caseIdList = caselog.getCaseListForUnSucByTaskId(taskid); - for (int i = 0; i < caseIdList.size(); i++) { - ProjectCase testcase = GetServerApi.cGetCaseByCaseId(caseIdList.get(i)); - List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); - // 删除旧的日志 - serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); - try { - AndroidCaseExecution.caseExcution(testcase, steps, taskid, ad, caselog, pcplist); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - LogUtil.APP.error("用户执行过程中抛出异常!", e); - } - } - } else { // 批量执行用例 - String[] temp = batchcase.split("\\#"); - for (int i = 0; i < temp.length; i++) { - ProjectCase testcase = GetServerApi.cGetCaseByCaseId(Integer.valueOf(temp[i])); - List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); - // 删除旧的日志 - serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); - try { - AndroidCaseExecution.caseExcution(testcase, steps, taskid, ad, caselog, pcplist); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - LogUtil.APP.error("用户执行过程中抛出异常!", e); - } - } - } - serverOperation.updateTaskExecuteData(taskid, 0,2); - ad.closeApp(); - //关闭Appium服务的线程 - if(as!=null){ - as.interrupt(); - } - } - -} +package luckyclient.execution.appium.androidex; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.List; +import java.util.Properties; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import luckyclient.execution.appium.AppiumInitialization; +import luckyclient.execution.appium.AppiumService; +import luckyclient.execution.httpinterface.TestControl; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.remote.entity.TaskExecute; +import luckyclient.utils.LogUtil; +import luckyclient.utils.config.AppiumConfig; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * + * @date 2018年1月26日 上午15:29:40 + * + */ +public class AndroidBatchExecute { + + public static void batchCaseExecuteForTast(String taskid, String batchcase) throws IOException, InterruptedException { + // 记录日志到数据库 + serverOperation.exetype = 0; + TestControl.TASKID = taskid; + AndroidDriver ad = null; + AppiumService as=null; + try { + Properties properties = AppiumConfig.getConfiguration(); + //根据配置自动启动Appiume服务 + if(Boolean.parseBoolean(properties.getProperty("autoRunAppiumService"))){ + as =new AppiumService(); + as.start(); + Thread.sleep(10000); + } + + ad = AppiumInitialization.setAndroidAppium(properties); + } catch (MalformedURLException e) { + LogUtil.APP.error("安卓手机根据配置自动启动Appiume服务出现异常",e); + } + serverOperation caselog = new serverOperation(); + TaskExecute task = GetServerApi.cgetTaskbyid(Integer.parseInt(taskid)); + List pcplist = GetServerApi + .cgetParamsByProjectid(task.getProjectId().toString()); + // 执行全部非成功状态用例 + if (batchcase.contains("ALLFAIL")) { + List caseIdList = caselog.getCaseListForUnSucByTaskId(taskid); + for (Integer integer : caseIdList) { + ProjectCase testcase = GetServerApi.cGetCaseByCaseId(integer); + List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); + // 删除旧的日志 + serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); + try { + AndroidCaseExecution.caseExcution(testcase, steps, taskid, ad, caselog, pcplist); + } catch (Exception e) { + LogUtil.APP.error("用户执行过程中抛出异常!", e); + } + } + } else { // 批量执行用例 + String[] temp = batchcase.split("#"); + for (String s : temp) { + ProjectCase testcase = GetServerApi.cGetCaseByCaseId(Integer.valueOf(s)); + List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); + // 删除旧的日志 + serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); + try { + AndroidCaseExecution.caseExcution(testcase, steps, taskid, ad, caselog, pcplist); + } catch (Exception e) { + LogUtil.APP.error("用户执行过程中抛出异常!", e); + } + } + } + serverOperation.updateTaskExecuteData(taskid, 0,2); + assert ad != null; + ad.closeApp(); + //关闭Appium服务的线程 + if(as!=null){ + as.interrupt(); + } + } + +} diff --git a/src/main/java/luckyclient/execution/appium/androidex/AndroidCaseExecution.java b/src/main/java/luckyclient/execution/appium/androidex/AndroidCaseExecution.java index b3f2a7b..a38df77 100644 --- a/src/main/java/luckyclient/execution/appium/androidex/AndroidCaseExecution.java +++ b/src/main/java/luckyclient/execution/appium/androidex/AndroidCaseExecution.java @@ -1,323 +1,319 @@ -package luckyclient.execution.appium.androidex; - -import java.io.IOException; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import io.appium.java_client.android.AndroidDriver; -import io.appium.java_client.android.AndroidElement; -import luckyclient.execution.appium.AppDriverAnalyticCase; -import luckyclient.execution.dispose.ActionManageForSteps; -import luckyclient.execution.dispose.ChangString; -import luckyclient.execution.dispose.ParamsManageForSteps; -import luckyclient.execution.httpinterface.TestCaseExecution; -import luckyclient.execution.httpinterface.analyticsteps.InterfaceAnalyticCase; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.Constants; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author seagull - * @date 2018年1月21日 上午15:12:48 - */ -public class AndroidCaseExecution{ - static Map variable = new HashMap(); - private static String casenote = "备注初始化"; - private static String imagname = ""; - - public static void caseExcution(ProjectCase testcase, List steps,String taskid, AndroidDriver appium,serverOperation caselog,List pcplist) - throws InterruptedException, IOException { - caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), 3); - // 把公共参数加入到MAP中 - for (ProjectCaseParams pcp : pcplist) { - variable.put(pcp.getParamsName(), pcp.getParamsValue()); - } - // 加入全局变量 - variable.putAll(ParamsManageForSteps.GLOBAL_VARIABLE); - // 0通过 1失败 2锁定 3执行中 4未执行 - int setcaseresult = 0; - for (ProjectCaseSteps step : steps) { - Map params; - String result; - - // 根据步骤类型来分析步骤参数 - if (3 == step.getStepType()){ - params = AppDriverAnalyticCase.analyticCaseStep(testcase, step, taskid,caselog,variable); - }else{ - params = InterfaceAnalyticCase.analyticCaseStep(testcase, step, taskid, caselog,variable); - } - - if(null != params.get("exception") && params.get("exception").contains("解析异常")){ - setcaseresult = 2; - break; - } - - // 根据步骤类型来执行步骤 - if (3 == step.getStepType()){ - result = androidRunStep(params, appium, taskid, testcase.getCaseId(), step.getStepSerialNumber(), caselog); - }else{ - TestCaseExecution testCaseExecution=new TestCaseExecution(); - result = testCaseExecution.runStep(params, taskid, testcase.getCaseSign(), step, caselog); - } - - String expectedResults = params.get("ExpectedResults").toString(); - expectedResults=ChangString.changparams(expectedResults, variable,"预期结果"); - - // 判断结果 - int stepresult = judgeResult(testcase, step, params, appium, taskid, expectedResults, result, caselog); - // 失败,并且不在继续,直接终止 - if (0 != stepresult) { - setcaseresult = stepresult; - if (testcase.getFailcontinue() == 0) { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),step.getStepSerialNumber()); - break; - } else { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),step.getStepSerialNumber()); - } - } - } - - variable.clear(); - caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), setcaseresult); - if(setcaseresult==0){ - LogUtil.APP.info("用例【{}】全部步骤执行结果成功...",testcase.getCaseSign()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例全部步骤执行结果成功","info", "ending",""); - }else{ - LogUtil.APP.warn("用例【{}】步骤执行过程中失败或是锁定...请查看具体原因!【{}】",testcase.getCaseSign(),casenote); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例执行过程中失败或是锁定"+casenote,"error", "ending",""); - } - //LogOperation.UpdateTastdetail(taskid, 0); - } - - public static String androidRunStep(Map params, AndroidDriver appium,String taskid,Integer caseId,int stepno,serverOperation caselog) { - String result = ""; - String property; - String propertyValue; - String operation; - String operationValue; - - try { - property = params.get("property"); - propertyValue = params.get("property_value"); - operation = params.get("operation"); - operationValue = params.get("operation_value"); - - LogUtil.APP.info("二次解析用例过程完成,等待进行对象操作......"); - caselog.insertTaskCaseLog(taskid, caseId, "对象操作:"+operation+"; 操作值:"+operationValue,"info", String.valueOf(stepno),""); - } catch (Exception e) { - LogUtil.APP.error("二次解析用例过程抛出异常!",e); - return "步骤执行失败:解析用例失败!"; - } - - try { - //调用接口用例 - if(null != operation&&null != operationValue&&"runcase".equals(operation)){ - String[] temp=operationValue.split(",",-1); - TestCaseExecution testCaseExecution=new TestCaseExecution(); - String ex = testCaseExecution.oneCaseExecuteForUICase(temp[0], taskid, caselog, appium); - if(!ex.contains("CallCase调用出错!") && !ex.contains("解析出错啦!") && !ex.contains("失败")){ - return ex; - }else{ - return "步骤执行失败:调用接口用例过程失败"; - } - } - - AndroidElement ae = null; - // 页面元素层 - if (null != property && null != propertyValue) { - ae = isElementExist(appium, property, propertyValue); - // 判断此元素是否存在 - if (null==ae) { - LogUtil.APP.warn("定位对象失败,isElementExist为null!"); - return "步骤执行失败:isElementExist定位元素过程失败!"; - } - - if (operation.indexOf("select") > -1) { - result = AndroidEncapsulateOperation.selectOperation(ae, operation, operationValue); - } else if (operation.indexOf("get") > -1){ - result = AndroidEncapsulateOperation.getOperation(ae, operation,operationValue); - } else { - result = AndroidEncapsulateOperation.objectOperation(appium, ae, operation, operationValue, property, propertyValue); - } - // Driver层操作 - } else if (null==property && null != operation) { - // 处理弹出框事件 - if (operation.indexOf("alert") > -1){ - result = AndroidEncapsulateOperation.alertOperation(appium, operation); - }else{ - result = AndroidEncapsulateOperation.driverOperation(appium, operation, operationValue); - } - }else{ - LogUtil.APP.warn("元素操作过程失败!"); - result = "步骤执行失败:元素操作过程失败!"; - } - } catch (Exception e) { - LogUtil.APP.error("元素定位过程或是操作过程失败或异常!",e); - return "步骤执行失败:元素定位过程或是操作过程失败或异常!" + e.getMessage(); - } - caselog.insertTaskCaseLog(taskid, caseId, result,"info", String.valueOf(stepno),""); - - if(result.indexOf("获取到的值是【")>-1&&result.indexOf("】")>-1){ - result = result.substring(result.indexOf("获取到的值是【")+7, result.length()-1); - } - return result; - - } - - public static AndroidElement isElementExist(AndroidDriver appium, String property, String propertyValue) { - try { - AndroidElement ae = null; - property=property.toLowerCase(); - // 处理WebElement对象定位 - switch (property) { - case "id": - ae = appium.findElementById(propertyValue); - break; - case "name": - ae = appium.findElementByAndroidUIAutomator("text(\""+propertyValue+"\")"); - break; - case "androiduiautomator": - ae = appium.findElementByAndroidUIAutomator(propertyValue); - break; - case "xpath": - ae = appium.findElementByXPath(propertyValue); - break; - case "linktext": - ae = appium.findElementByLinkText(propertyValue); - break; - case "tagname": - ae = appium.findElementByTagName(propertyValue); - break; - case "cssselector": - ae = appium.findElementByCssSelector(propertyValue); - break; - case "classname": - ae = appium.findElementByClassName(propertyValue); - break; - case "partiallinktext": - ae = appium.findElementByPartialLinkText(propertyValue); - break; - default: - break; - } - - return ae; - - } catch (Exception e) { - LogUtil.APP.error("当前对象定位失败,出现异常!",e); - return null; - } - - } - - public static int judgeResult(ProjectCase testcase, ProjectCaseSteps step, Map params, AndroidDriver appium, String taskid, String expect, String result, serverOperation caselog) throws InterruptedException { - int setresult = 0; - java.text.DateFormat timeformat = new java.text.SimpleDateFormat("MMdd-hhmmss"); - imagname = timeformat.format(new Date()); - - result = ActionManageForSteps.actionManage(step.getAction(), result); - if (null != result && !result.contains("步骤执行失败:")) { - // 有预期结果 - if (null != expect && !expect.isEmpty()) { - LogUtil.APP.info("期望结果为【{}】",expect); - - // 赋值传参模式 - if (expect.length() > Constants.ASSIGNMENT_SIGN.length() && expect.startsWith(Constants.ASSIGNMENT_SIGN)) { - variable.put(expect.substring(Constants.ASSIGNMENT_SIGN.length()), result); - LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),result,expect.substring(Constants.ASSIGNMENT_SIGN.length())); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + result + "】赋值给变量【" + expect.substring(Constants.ASSIGNMENT_SIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); - } - // 赋值全局变量 - else if (expect.length() > Constants.ASSIGNMENT_GLOBALSIGN.length() && expect.startsWith(Constants.ASSIGNMENT_GLOBALSIGN)) { - variable.put(expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), result); - ParamsManageForSteps.GLOBAL_VARIABLE.put(expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), result); - LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给全局变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),result,expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length())); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + result + "】赋值给全局变量【" + expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); - } - // 移动端 UI检查模式 - else if (3 == step.getStepType() && params.get("checkproperty") != null && params.get("checkproperty_value") != null) { - String checkproperty = params.get("checkproperty"); - String checkPropertyValue = params.get("checkproperty_value"); - - AndroidElement ae = isElementExist(appium, checkproperty, checkPropertyValue); - if (null != ae) { - LogUtil.APP.info("用例:{} 第{}步,在当前页面中找到预期结果中对象。当前步骤执行成功!",testcase.getCaseSign(),step.getStepSerialNumber()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在当前页面中找到预期结果中对象。当前步骤执行成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - casenote = "第" + step.getStepSerialNumber() + "步,没有在当前页面中找到预期结果中对象。执行失败!"; - setresult = 1; - AndroidBaseAppium.screenShot(appium, imagname); - LogUtil.APP.warn("用例:{} 第{}步,没有在当前页面中找到预期结果中对象。当前步骤执行失败!",testcase.getCaseSign(),step.getStepSerialNumber()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在当前页面中没有找到预期结果中对象。当前步骤执行失败!" + "checkproperty【" + checkproperty + "】 checkproperty_value【" + checkPropertyValue + "】", "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - } - // 其它匹配模式 - else { - // 模糊匹配预期结果模式 - if (expect.length() > Constants.FUZZY_MATCHING_SIGN.length() && expect.startsWith(Constants.FUZZY_MATCHING_SIGN)) { - if (result.contains(expect.substring(Constants.FUZZY_MATCHING_SIGN.length()))) { - LogUtil.APP.info("用例:{} 第{}步,模糊匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果成功!执行结果:" + result, "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - casenote = "第" + step.getStepSerialNumber() + "步,模糊匹配预期结果失败!"; - setresult = 1; - AndroidBaseAppium.screenShot(appium, imagname); - LogUtil.APP.warn("用例:{} 第{}步,模糊匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expect.substring(Constants.FUZZY_MATCHING_SIGN.length()),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果失败!预期结果:" + expect.substring(Constants.FUZZY_MATCHING_SIGN.length()) + ",测试结果:" + result, "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - } - // 正则匹配预期结果模式 - else if (expect.length() > Constants.REGULAR_MATCHING_SIGN.length() && expect.startsWith(Constants.REGULAR_MATCHING_SIGN)) { - Pattern pattern = Pattern.compile(expect.substring(Constants.REGULAR_MATCHING_SIGN.length())); - Matcher matcher = pattern.matcher(result); - if (matcher.find()) { - LogUtil.APP.info("用例:{} 第{}步,正则匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - casenote = "第" + step.getStepSerialNumber() + "步,正则匹配预期结果失败!"; - setresult = 1; - AndroidBaseAppium.screenShot(appium, imagname); - LogUtil.APP.warn("用例:{} 第{}步,正则匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expect.substring(Constants.REGULAR_MATCHING_SIGN.length()),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果失败!预期结果:" + expect.substring(Constants.REGULAR_MATCHING_SIGN.length()) + ",测试结果:" + result, "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - } - // 精确匹配预期结果模式 - else { - if (expect.equals(result)) { - LogUtil.APP.info("用例:{} 第{}步,精确匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "精确匹配预期结果成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - casenote = "第" + step.getStepSerialNumber() + "步,精确匹配预期结果失败!"; - setresult = 1; - AndroidBaseAppium.screenShot(appium, imagname); - LogUtil.APP.warn("用例:{} 第{}步,精确匹配预期结果失败!预期结果是:【{}】 执行结果:【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),expect,result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "精确匹配预期结果失败!预期结果是:【"+expect+"】 执行结果:【"+ result+"】", "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - } - } - } - } else { - casenote = (null != result) ? result : ""; - setresult = 2; - AndroidBaseAppium.screenShot(appium, imagname); - LogUtil.APP.warn("用例:{} 第{}步,执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),casenote); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "当前步骤在执行过程中解析|定位元素|操作对象失败!" + casenote, "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - - return setresult; - } - -} +package luckyclient.execution.appium.androidex; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import luckyclient.execution.appium.AppDriverAnalyticCase; +import luckyclient.execution.dispose.ActionManageForSteps; +import luckyclient.execution.dispose.ChangString; +import luckyclient.execution.dispose.ParamsManageForSteps; +import luckyclient.execution.httpinterface.TestCaseExecution; +import luckyclient.execution.httpinterface.analyticsteps.InterfaceAnalyticCase; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.Constants; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * @author seagull + * @date 2018年1月21日 上午15:12:48 + */ +public class AndroidCaseExecution{ + static Map variable = new HashMap<>(); + private static String casenote = "备注初始化"; + + public static void caseExcution(ProjectCase testcase, List steps,String taskid, AndroidDriver appium,serverOperation caselog,List pcplist) { + caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), 3); + // 把公共参数加入到MAP中 + for (ProjectCaseParams pcp : pcplist) { + variable.put(pcp.getParamsName(), pcp.getParamsValue()); + } + // 加入全局变量 + variable.putAll(ParamsManageForSteps.GLOBAL_VARIABLE); + // 0通过 1失败 2锁定 3执行中 4未执行 + int setcaseresult = 0; + for (ProjectCaseSteps step : steps) { + Map params; + String result; + + // 根据步骤类型来分析步骤参数 + if (3 == step.getStepType()){ + params = AppDriverAnalyticCase.analyticCaseStep(testcase, step, taskid,caselog,variable); + }else{ + params = InterfaceAnalyticCase.analyticCaseStep(testcase, step, taskid, caselog,variable); + } + + if(null != params.get("exception") && params.get("exception").contains("解析异常")){ + setcaseresult = 2; + break; + } + + // 根据步骤类型来执行步骤 + if (3 == step.getStepType()){ + result = androidRunStep(params, appium, taskid, testcase.getCaseId(), step.getStepSerialNumber(), caselog); + }else{ + TestCaseExecution testCaseExecution=new TestCaseExecution(); + result = testCaseExecution.runStep(params, taskid, testcase.getCaseSign(), step, caselog); + } + + String expectedResults = params.get("ExpectedResults"); + expectedResults=ChangString.changparams(expectedResults, variable,"预期结果"); + + // 判断结果 + int stepresult = judgeResult(testcase, step, params, appium, taskid, expectedResults, result, caselog); + // 失败,并且不在继续,直接终止 + if (0 != stepresult) { + setcaseresult = stepresult; + if (testcase.getFailcontinue() == 0) { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),step.getStepSerialNumber()); + break; + } else { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),step.getStepSerialNumber()); + } + } + } + + variable.clear(); + caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), setcaseresult); + if(setcaseresult==0){ + LogUtil.APP.info("用例【{}】全部步骤执行结果成功...",testcase.getCaseSign()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例全部步骤执行结果成功","info", "ending",""); + }else{ + LogUtil.APP.warn("用例【{}】步骤执行过程中失败或是锁定...请查看具体原因!【{}】",testcase.getCaseSign(),casenote); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例执行过程中失败或是锁定"+casenote,"error", "ending",""); + } + //LogOperation.UpdateTastdetail(taskid, 0); + } + + public static String androidRunStep(Map params, AndroidDriver appium,String taskid,Integer caseId,int stepno,serverOperation caselog) { + String result; + String property; + String propertyValue; + String operation; + String operationValue; + + try { + property = params.get("property"); + propertyValue = params.get("property_value"); + operation = params.get("operation"); + operationValue = params.get("operation_value"); + + LogUtil.APP.info("二次解析用例过程完成,等待进行对象操作......"); + caselog.insertTaskCaseLog(taskid, caseId, "对象操作:"+operation+"; 操作值:"+operationValue,"info", String.valueOf(stepno),""); + } catch (Exception e) { + LogUtil.APP.error("二次解析用例过程抛出异常!",e); + return "步骤执行失败:解析用例失败!"; + } + + try { + //调用接口用例 + if(null != operationValue && "runcase".equals(operation)){ + String[] temp=operationValue.split(",",-1); + TestCaseExecution testCaseExecution=new TestCaseExecution(); + String ex = testCaseExecution.oneCaseExecuteForUICase(temp[0], taskid, caselog, appium); + if(!ex.contains("CallCase调用出错!") && !ex.contains("解析出错啦!") && !ex.contains("失败")){ + return ex; + }else{ + return "步骤执行失败:调用接口用例过程失败"; + } + } + + AndroidElement ae; + // 页面元素层 + if (null != property && null != propertyValue) { + ae = isElementExist(appium, property, propertyValue); + // 判断此元素是否存在 + if (null==ae) { + LogUtil.APP.warn("定位对象失败,isElementExist为null!"); + return "步骤执行失败:isElementExist定位元素过程失败!"; + } + + if (operation.contains("select")) { + result = AndroidEncapsulateOperation.selectOperation(ae, operation, operationValue); + } else if (operation.contains("get")){ + result = AndroidEncapsulateOperation.getOperation(ae, operation,operationValue); + } else { + result = AndroidEncapsulateOperation.objectOperation(appium, ae, operation, operationValue, property, propertyValue); + } + // Driver层操作 + } else if (null==property && null != operation) { + // 处理弹出框事件 + if (operation.contains("alert")){ + result = AndroidEncapsulateOperation.alertOperation(appium, operation); + }else{ + result = AndroidEncapsulateOperation.driverOperation(appium, operation, operationValue); + } + }else{ + LogUtil.APP.warn("元素操作过程失败!"); + result = "步骤执行失败:元素操作过程失败!"; + } + } catch (Exception e) { + LogUtil.APP.error("元素定位过程或是操作过程失败或异常!",e); + return "步骤执行失败:元素定位过程或是操作过程失败或异常!" + e.getMessage(); + } + caselog.insertTaskCaseLog(taskid, caseId, result,"info", String.valueOf(stepno),""); + + if(result.contains("获取到的值是【") && result.contains("】")){ + result = result.substring(result.indexOf("获取到的值是【")+7, result.length()-1); + } + return result; + + } + + public static AndroidElement isElementExist(AndroidDriver appium, String property, String propertyValue) { + try { + AndroidElement ae = null; + property=property.toLowerCase(); + // 处理WebElement对象定位 + switch (property) { + case "id": + ae = appium.findElementById(propertyValue); + break; + case "name": + ae = appium.findElementByAndroidUIAutomator("text(\""+propertyValue+"\")"); + break; + case "androiduiautomator": + ae = appium.findElementByAndroidUIAutomator(propertyValue); + break; + case "xpath": + ae = appium.findElementByXPath(propertyValue); + break; + case "linktext": + ae = appium.findElementByLinkText(propertyValue); + break; + case "tagname": + ae = appium.findElementByTagName(propertyValue); + break; + case "cssselector": + ae = appium.findElementByCssSelector(propertyValue); + break; + case "classname": + ae = appium.findElementByClassName(propertyValue); + break; + case "partiallinktext": + ae = appium.findElementByPartialLinkText(propertyValue); + break; + default: + break; + } + + return ae; + + } catch (Exception e) { + LogUtil.APP.error("当前对象定位失败,出现异常!",e); + return null; + } + + } + + public static int judgeResult(ProjectCase testcase, ProjectCaseSteps step, Map params, AndroidDriver appium, String taskid, String expect, String result, serverOperation caselog) { + int setresult = 0; + java.text.DateFormat timeformat = new java.text.SimpleDateFormat("MMdd-hhmmss"); + String imagname = timeformat.format(new Date()); + + result = ActionManageForSteps.actionManage(step.getAction(), result); + if (null != result && !result.contains("步骤执行失败:")) { + // 有预期结果 + if (null != expect && !expect.isEmpty()) { + LogUtil.APP.info("期望结果为【{}】",expect); + + // 赋值传参模式 + if (expect.length() > Constants.ASSIGNMENT_SIGN.length() && expect.startsWith(Constants.ASSIGNMENT_SIGN)) { + variable.put(expect.substring(Constants.ASSIGNMENT_SIGN.length()), result); + LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),result,expect.substring(Constants.ASSIGNMENT_SIGN.length())); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + result + "】赋值给变量【" + expect.substring(Constants.ASSIGNMENT_SIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); + } + // 赋值全局变量 + else if (expect.length() > Constants.ASSIGNMENT_GLOBALSIGN.length() && expect.startsWith(Constants.ASSIGNMENT_GLOBALSIGN)) { + variable.put(expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), result); + ParamsManageForSteps.GLOBAL_VARIABLE.put(expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), result); + LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给全局变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),result,expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length())); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + result + "】赋值给全局变量【" + expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); + } + // 移动端 UI检查模式 + else if (3 == step.getStepType() && params.get("checkproperty") != null && params.get("checkproperty_value") != null) { + String checkproperty = params.get("checkproperty"); + String checkPropertyValue = params.get("checkproperty_value"); + + AndroidElement ae = isElementExist(appium, checkproperty, checkPropertyValue); + if (null != ae) { + LogUtil.APP.info("用例:{} 第{}步,在当前页面中找到预期结果中对象。当前步骤执行成功!",testcase.getCaseSign(),step.getStepSerialNumber()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在当前页面中找到预期结果中对象。当前步骤执行成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + casenote = "第" + step.getStepSerialNumber() + "步,没有在当前页面中找到预期结果中对象。执行失败!"; + setresult = 1; + AndroidBaseAppium.screenShot(appium, imagname); + LogUtil.APP.warn("用例:{} 第{}步,没有在当前页面中找到预期结果中对象。当前步骤执行失败!",testcase.getCaseSign(),step.getStepSerialNumber()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在当前页面中没有找到预期结果中对象。当前步骤执行失败!" + "checkproperty【" + checkproperty + "】 checkproperty_value【" + checkPropertyValue + "】", "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + } + // 其它匹配模式 + else { + // 模糊匹配预期结果模式 + if (expect.length() > Constants.FUZZY_MATCHING_SIGN.length() && expect.startsWith(Constants.FUZZY_MATCHING_SIGN)) { + if (result.contains(expect.substring(Constants.FUZZY_MATCHING_SIGN.length()))) { + LogUtil.APP.info("用例:{} 第{}步,模糊匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果成功!执行结果:" + result, "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + casenote = "第" + step.getStepSerialNumber() + "步,模糊匹配预期结果失败!"; + setresult = 1; + AndroidBaseAppium.screenShot(appium, imagname); + LogUtil.APP.warn("用例:{} 第{}步,模糊匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expect.substring(Constants.FUZZY_MATCHING_SIGN.length()),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果失败!预期结果:" + expect.substring(Constants.FUZZY_MATCHING_SIGN.length()) + ",测试结果:" + result, "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + } + // 正则匹配预期结果模式 + else if (expect.length() > Constants.REGULAR_MATCHING_SIGN.length() && expect.startsWith(Constants.REGULAR_MATCHING_SIGN)) { + Pattern pattern = Pattern.compile(expect.substring(Constants.REGULAR_MATCHING_SIGN.length())); + Matcher matcher = pattern.matcher(result); + if (matcher.find()) { + LogUtil.APP.info("用例:{} 第{}步,正则匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + casenote = "第" + step.getStepSerialNumber() + "步,正则匹配预期结果失败!"; + setresult = 1; + AndroidBaseAppium.screenShot(appium, imagname); + LogUtil.APP.warn("用例:{} 第{}步,正则匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expect.substring(Constants.REGULAR_MATCHING_SIGN.length()),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果失败!预期结果:" + expect.substring(Constants.REGULAR_MATCHING_SIGN.length()) + ",测试结果:" + result, "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + } + // 精确匹配预期结果模式 + else { + if (expect.equals(result)) { + LogUtil.APP.info("用例:{} 第{}步,精确匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "精确匹配预期结果成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + casenote = "第" + step.getStepSerialNumber() + "步,精确匹配预期结果失败!"; + setresult = 1; + AndroidBaseAppium.screenShot(appium, imagname); + LogUtil.APP.warn("用例:{} 第{}步,精确匹配预期结果失败!预期结果是:【{}】 执行结果:【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),expect,result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "精确匹配预期结果失败!预期结果是:【"+expect+"】 执行结果:【"+ result+"】", "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + } + } + } + } else { + casenote = (null != result) ? result : ""; + setresult = 2; + AndroidBaseAppium.screenShot(appium, imagname); + LogUtil.APP.warn("用例:{} 第{}步,执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),casenote); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "当前步骤在执行过程中解析|定位元素|操作对象失败!" + casenote, "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + + return setresult; + } + +} diff --git a/src/main/java/luckyclient/execution/appium/androidex/AndroidCaseLocalDebug.java b/src/main/java/luckyclient/execution/appium/androidex/AndroidCaseLocalDebug.java index aa06f5c..39d0ce8 100644 --- a/src/main/java/luckyclient/execution/appium/androidex/AndroidCaseLocalDebug.java +++ b/src/main/java/luckyclient/execution/appium/androidex/AndroidCaseLocalDebug.java @@ -1,8 +1,6 @@ package luckyclient.execution.appium.androidex; -import java.io.IOException; import java.util.List; - import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidElement; import luckyclient.remote.api.GetServerApi; @@ -24,6 +22,11 @@ import luckyclient.utils.LogUtil; */ public class AndroidCaseLocalDebug { + /** + * IDEA工具方式调试测试用例 + * @param androiddriver 初始化appium对象 + * @param testCaseExternalId 用例编号 + */ public static void oneCasedebug(AndroidDriver androiddriver, String testCaseExternalId) { // 不记录日志到数据库 serverOperation.exetype = 1; @@ -45,9 +48,9 @@ public class AndroidCaseLocalDebug { /** * 用于做多条用例串行调试 - * @param androiddriver - * @param projectname - * @param addtestcase + * @param androiddriver 初始化appium对象 + * @param projectname 项目名称 + * @param addtestcase 用例集 * @author Seagull * @date 2019年4月18日 */ @@ -61,7 +64,6 @@ public class AndroidCaseLocalDebug { oneCasedebug(androiddriver, testCaseExternalId); } catch (Exception e) { LogUtil.APP.error("多用例调试过程中抛出异常!", e); - continue; } } // 关闭APP以及appium会话 diff --git a/src/main/java/luckyclient/execution/appium/androidex/AndroidEncapsulateOperation.java b/src/main/java/luckyclient/execution/appium/androidex/AndroidEncapsulateOperation.java index 5ad71e5..656f1bf 100644 --- a/src/main/java/luckyclient/execution/appium/androidex/AndroidEncapsulateOperation.java +++ b/src/main/java/luckyclient/execution/appium/androidex/AndroidEncapsulateOperation.java @@ -1,565 +1,564 @@ -package luckyclient.execution.appium.androidex; - -import java.time.Duration; -import java.util.Date; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import org.openqa.selenium.Alert; -import org.openqa.selenium.JavascriptExecutor; -import org.openqa.selenium.support.ui.Select; - -import cn.hutool.core.util.StrUtil; -import io.appium.java_client.android.AndroidDriver; -import io.appium.java_client.android.AndroidElement; -import io.appium.java_client.android.AndroidTouchAction; -import io.appium.java_client.android.nativekey.AndroidKey; -import io.appium.java_client.android.nativekey.KeyEvent; -import io.appium.java_client.touch.LongPressOptions; -import io.appium.java_client.touch.WaitOptions; -import io.appium.java_client.touch.offset.ElementOption; -import io.appium.java_client.touch.offset.PointOption; -import luckyclient.execution.dispose.ChangString; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author Seagull - * @date 2017年1月29日 上午9:31:42 - * - */ -public class AndroidEncapsulateOperation { - public static String selectOperation(AndroidElement ae, String operation, String operationValue) throws Exception { - String result = ""; - // 下拉框对象处理 - Select select = new Select(ae); - - // 处理下拉框事件 - switch (operation) { - case "selectbyvisibletext": - select.selectByVisibleText(operationValue); - LogUtil.APP - .info("下拉框对象通过VisibleText属性选择...【VisibleText属性值:{}】",operationValue); - break; - case "selectbyvalue": - select.selectByValue(operationValue); - LogUtil.APP.info("下拉框对象通过Value属性选择...【Value属性值:{}】",operationValue); - break; - case "selectbyindex": - select.selectByIndex(Integer.valueOf(operationValue)); - LogUtil.APP.info("下拉框对象通过Index属性选择...【Index属性值:{}】",operationValue); - break; - case "isselect": - result = "获取到的值是【" + ae.isSelected() + "】"; - LogUtil.APP.info("判断对象是否已经被选择...【结果值:{}】",ae.isSelected()); - break; - default: - break; - } - return result; - } - - public static String getOperation(AndroidElement ae, String operation, String value) throws Exception { - String result = ""; - // 获取对象处理 - switch (operation) { - case "gettext": - result = "获取到的值是【" + ae.getText() + "】"; - LogUtil.APP.info("getText获取对象text属性...【text属性值:{}】",result); - break; // 获取输入框内容 - case "gettagname": - result = "获取到的值是【" + ae.getTagName() + "】"; - LogUtil.APP.info("getTagName获取对象tagname属性...【tagname属性值:{}】",result); - break; - case "getattribute": - result = "获取到的值是【" + ae.getAttribute(value) + "】"; - LogUtil.APP - .info("getAttribute获取对象【{}】属性...【{}属性值:{}】",value,value,result); - break; - case "getcssvalue": - result = "获取到的值是【" + ae.getCssValue(value) + "】"; - LogUtil.APP - .info("getCssValue获取对象【{}】属性...【{}属性值:{}】",value,value,result); - break; - default: - break; - } - return result; - } - - public static String objectOperation(AndroidDriver appium, AndroidElement ae, String operation, - String operationValue, String property, String propertyValue) throws Exception { - String result = ""; - AndroidTouchAction action = new AndroidTouchAction(appium); - - // 处理WebElement对象操作 - switch (operation) { - case "click": - ae.click(); - result = "click点击对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; - LogUtil.APP - .info("click点击对象...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); - break; - case "sendkeys": - ae.sendKeys(operationValue); - result = "sendKeys对象输入...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "; 操作值:" + operationValue - + "】"; - LogUtil.APP.info("sendkeys对象输入...【对象定位属性:{}; 定位属性值:{}; 操作值:{}】",property,propertyValue,operationValue); - break; - case "clear": - ae.clear(); - result = "clear清空输入框...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; - LogUtil.APP - .info("clear清空输入框...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); - break; // 清空输入框 - case "isenabled": - result = "获取到的值是【" + ae.isEnabled() + "】"; - LogUtil.APP.info("当前对象判断是否可用布尔值为【{}】",ae.isEnabled()); - break; - case "isdisplayed": - result = "获取到的值是【" + ae.isDisplayed() + "】"; - LogUtil.APP.info("当前对象判断是否可见布尔值为【{}】",ae.isDisplayed()); - break; - case "exjsob": - JavascriptExecutor jse = (JavascriptExecutor) appium; - jse.executeScript(operationValue, ae); - result = "执行JS...【" + operationValue + "】"; - LogUtil.APP.info("执行JS...【{}】",operationValue); - break; - case "longpresselement": - LongPressOptions lpoptions = new LongPressOptions(); - lpoptions.withElement(ElementOption.element(ae)); - if (null != operationValue && ChangString.isNumeric(operationValue)) { - int nanos = Integer.valueOf(operationValue) * 1000; - Duration duration = Duration.ofNanos(nanos); - lpoptions.withDuration(duration); - } - action.longPress(lpoptions).release().perform(); - result = "longpresselement在屏幕指定元素上按住" + operationValue + "秒...【对象定位属性:" + property + "; 定位属性值:" - + propertyValue + "】"; - LogUtil.APP.info("longpresselement在屏幕指定元素上按住{}秒...【对象定位属性:{}; 定位属性值:{}】",operationValue,property,propertyValue); - break; - default: - break; - } - return result; - } - - public static String alertOperation(AndroidDriver appium, String operation) throws Exception { - String result = ""; - Alert alert = appium.switchTo().alert(); - switch (operation) { - case "alertaccept": - alert.accept(); - LogUtil.APP.info("弹出框对象点击同意..."); - break; - case "alertdismiss": - alert.dismiss(); - LogUtil.APP.info("弹出框对象点击取消..."); - break; - case "alertgettext": - result = "获取到的值是【" + alert.getText() + "】"; - LogUtil.APP.info("弹出框对象通过getText获取对象text属性...【Text属性值:{}】",alert.getText()); - break; - default: - break; - } - return result; - } - - public static String driverOperation(AndroidDriver appium, String operation, String operationValue) - throws Exception { - String result = ""; - AndroidTouchAction action = new AndroidTouchAction(appium); - // 处理页面对象操作 - switch (operation) { - case "getcontexthandles": - Set handles = appium.getContextHandles(); - int handlenum = 1; - for (String handle : handles) { - if (String.valueOf(handlenum).equals(operationValue)) { - if (appium.getContext().equals(handle)) { - result = "请注意,你指定的ContextHandle就是当前页面哦,获取到的值是【" + handle + "】"; - } else { - result = "指定ContextHandler的顺序值是" + operationValue + ",获取到的值是【" + handle + "】"; - } - break; - } - handlenum++; - } - LogUtil.APP.info("getContext获取窗口句柄...{}",result); - break; - case "exjs": - JavascriptExecutor jse = (JavascriptExecutor) appium; - jse.executeScript(operationValue); - result = "执行JS...【" + operationValue + "】"; - LogUtil.APP.info("执行JS...【{}】",operationValue); - break; - case "exAdbShell": - Runtime.getRuntime().exec(operationValue); - result = "执行安卓adb命令...【" + operationValue + "】"; - LogUtil.APP.info("执行安卓adb命令...【{}】",operationValue); - break; - case "androidkeycode": - // 模拟手机键盘 - try { - if (StrUtil.isNotBlank(operationValue)) { - KeyEvent keyEvent = new KeyEvent(); - appium.pressKey(keyEvent.withKey(AndroidKey.valueOf(operationValue))); - result = "模拟手机键盘发送指令...keycode【" + operationValue + "】"; - LogUtil.APP.info("模拟手机键盘发送指令...keycode【{}】", operationValue); - } else { - result = "模拟手机键盘失败,键盘参数为空,请检查你的参数!"; - LogUtil.APP.info("模拟手机键盘失败,键盘参数为空,请检查你的参数!"); - } - } catch (IllegalArgumentException ae) { - result = "模拟手机按键失败,没有找到对应的按键参数,请检查你的参数!"; - LogUtil.APP.info("模拟手机按键失败,没有找到对应的按键参数,请检查你的参数!"); - } - break; - // 隐藏手机键盘 - case "hidekeyboard": - appium.hideKeyboard(); - result = "隐藏手机键盘...【hideKeyboard】"; - LogUtil.APP.info("隐藏手机键盘...【hideKeyboard】"); - break; - case "gotocontext": - Set ctNames = appium.getContextHandles(); - int flag = 0; - for (String contextName : ctNames) { - if (contextName.contains(operationValue)) { - flag = 1; - appium.context(contextName); - break; - } - } - if (flag == 1) { - result = "切换context至【" + operationValue + "】"; - LogUtil.APP.info("切换context至【{}】",operationValue); - } else { - result = "切换context失败,未找到contextName值为【" + operationValue + "】的对象"; - LogUtil.APP.info("切换context失败,未找到contextName值为【{}】的对象",operationValue); - } - break; - case "getcontext": - result = "获取到的值是【" + appium.getContext() + "】"; - LogUtil.APP.info("获取页面Context...【{}】",appium.getContext()); - break; - case "gettitle": - result = "获取到的值是【" + appium.getTitle() + "】"; - LogUtil.APP.info("获取页面gettitle...【{}】",appium.getTitle()); - break; - case "swipeup": - String[] tempup = operationValue.split("\\|", -1); - if (null != tempup[0] && ChangString.isNumeric(tempup[0])) { - Double second = Double.valueOf(tempup[0]); - if (null != tempup[1] && ChangString.isNumeric(tempup[1])) { - int num = Integer.valueOf(tempup[1]); - AndroidBaseAppium.swipePageDown(appium, second, num); - result = "swipeup手指向上滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipeup手指向上滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipeup手指向上滑动参数判断次数出现异常【" + tempup[1] + "】"; - LogUtil.APP.info("swipeup手指向上滑动参数判断次数出现异常【{}】",tempup[1]); - } - } else { - result = "swipeup手指向上滑动参数判断时间出现异常【" + tempup[0] + "】"; - LogUtil.APP.info("swipeup手指向上滑动参数判断时间出现异常【{}】",tempup[0]); - } - break; - case "swipedown": - String[] tempdown = operationValue.split("\\|", -1); - if (null != tempdown[0] && ChangString.isNumeric(tempdown[0])) { - Double second = Double.valueOf(tempdown[0]); - if (null != tempdown[1] && ChangString.isNumeric(tempdown[1])) { - int num = Integer.valueOf(tempdown[1]); - AndroidBaseAppium.swipePageUp(appium, second, num); - result = "swipedown手指向下滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipedown手指向下滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipedown手指向下滑动参数判断次数出现异常【" + tempdown[1] + "】"; - LogUtil.APP.info("swipedown手指向下滑动参数判断次数出现异常【{}】",tempdown[1]); - } - } else { - result = "swipedown手指向下滑动参数判断时间出现异常【" + tempdown[0] + "】"; - LogUtil.APP.info("swipedown手指向下滑动参数判断时间出现异常【{}】",tempdown[0]); - } - break; - case "swipeleft": - String[] templeft = operationValue.split("\\|", -1); - if (null != templeft[0] && ChangString.isNumeric(templeft[0])) { - Double second = Double.valueOf(templeft[0]); - if (null != templeft[1] && ChangString.isNumeric(templeft[1])) { - int num = Integer.valueOf(templeft[1]); - AndroidBaseAppium.swipePageRight(appium, second, num); - result = "swipleft手指向左滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipleft手指向左滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipleft手指向左滑动参数判断次数出现异常【" + templeft[1] + "】"; - LogUtil.APP.info("swipleft手指向左滑动参数判断次数出现异常【{}】",templeft[1]); - } - } else { - result = "swipleft手指向左滑动参数判断时间出现异常【" + templeft[0] + "】"; - LogUtil.APP.info("swipleft手指向左滑动参数判断时间出现异常【{}】",templeft[0]); - } - break; - case "swiperight": - String[] tempright = operationValue.split("\\|", -1); - if (null != tempright[0] && ChangString.isNumeric(tempright[0])) { - Double second = Double.valueOf(tempright[0]); - if (null != tempright[1] && ChangString.isNumeric(tempright[1])) { - int num = Integer.valueOf(tempright[1]); - AndroidBaseAppium.swipePageLeft(appium, second, num); - result = "swipright手指向右滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipright手指向右滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipright手指向右滑动参数判断次数出现异常【" + tempright[1] + "】"; - LogUtil.APP.info("swipright手指向右滑动参数判断次数出现异常【{}】",tempright[1]); - } - } else { - result = "swipright手指向右滑动参数判断时间出现异常【" + tempright[0] + "】"; - LogUtil.APP.info("swipright手指向右滑动参数判断时间出现异常【{}】",tempright[0]); - } - break; - case "swipepageup": - String[] tempPageUp = operationValue.split("\\|", -1); - if (null != tempPageUp[0] && ChangString.isNumeric(tempPageUp[0])) { - Double second = Double.valueOf(tempPageUp[0]); - if (null != tempPageUp[1] && ChangString.isNumeric(tempPageUp[1])) { - int num = Integer.valueOf(tempPageUp[1]); - AndroidBaseAppium.swipePageUp(appium, second, num); - result = "swipeup页面向上滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipeup页面向上滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipeup页面向上滑动参数判断次数出现异常【" + tempPageUp[1] + "】"; - LogUtil.APP.info("swipeup页面向上滑动参数判断次数出现异常【{}】",tempPageUp[1]); - } - } else { - result = "swipeup页面向上滑动参数判断时间出现异常【" + tempPageUp[0] + "】"; - LogUtil.APP.info("swipeup页面向上滑动参数判断时间出现异常【{}】",tempPageUp[0]); - } - break; - case "swipepagedown": - String[] tempPageDown = operationValue.split("\\|", -1); - if (null != tempPageDown[0] && ChangString.isNumeric(tempPageDown[0])) { - Double second = Double.valueOf(tempPageDown[0]); - if (null != tempPageDown[1] && ChangString.isNumeric(tempPageDown[1])) { - int num = Integer.valueOf(tempPageDown[1]); - AndroidBaseAppium.swipePageDown(appium, second, num); - result = "swipedown页面向下滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipedown页面向下滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipedown页面向下滑动参数判断次数出现异常【" + tempPageDown[1] + "】"; - LogUtil.APP.info("swipedown页面向下滑动参数判断次数出现异常【{}】",tempPageDown[1]); - } - } else { - result = "swipedown页面向下滑动参数判断时间出现异常【" + tempPageDown[0] + "】"; - LogUtil.APP.info("swipedown页面向下滑动参数判断时间出现异常【{}】",tempPageDown[0]); - } - break; - case "swipepageleft": - String[] tempPageLeft = operationValue.split("\\|", -1); - if (null != tempPageLeft[0] && ChangString.isNumeric(tempPageLeft[0])) { - Double second = Double.valueOf(tempPageLeft[0]); - if (null != tempPageLeft[1] && ChangString.isNumeric(tempPageLeft[1])) { - int num = Integer.valueOf(tempPageLeft[1]); - AndroidBaseAppium.swipePageLeft(appium, second, num); - result = "swipleft页面向左滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipleft页面向左滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipleft页面向左滑动参数判断次数出现异常【" + tempPageLeft[1] + "】"; - LogUtil.APP.info("swipleft页面向左滑动参数判断次数出现异常【{}】",tempPageLeft[1]); - } - } else { - result = "swipleft页面向左滑动参数判断时间出现异常【" + tempPageLeft[0] + "】"; - LogUtil.APP.info("swipleft页面向左滑动参数判断时间出现异常【{}】",tempPageLeft[0]); - } - break; - case "swipepageright": - String[] tempPageRight = operationValue.split("\\|", -1); - if (null != tempPageRight[0] && ChangString.isNumeric(tempPageRight[0])) { - Double second = Double.valueOf(tempPageRight[0]); - if (null != tempPageRight[1] && ChangString.isNumeric(tempPageRight[1])) { - int num = Integer.valueOf(tempPageRight[1]); - AndroidBaseAppium.swipePageRight(appium, second, num); - result = "swipright页面向右滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipright页面向右滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipright页面向右滑动参数判断次数出现异常【" + tempPageRight[1] + "】"; - LogUtil.APP.info("swipright页面向右滑动参数判断次数出现异常【{}】",tempPageRight[1]); - } - } else { - result = "swipright页面向右滑动参数判断时间出现异常【" + tempPageRight[0] + "】"; - LogUtil.APP.info("swipright页面向右滑动参数判断时间出现异常【{}】",tempPageRight[0]); - } - break; - case "longpressxy": - String[] longpressxy = operationValue.split("\\|", -1); - if (null != longpressxy[0] && ChangString.isNumeric(longpressxy[0])) { - int longpressx = Integer.valueOf(longpressxy[0]); - if (null != longpressxy[1] && ChangString.isNumeric(longpressxy[1])) { - int longpressy = Integer.valueOf(longpressxy[1]); - if (null != longpressxy[2] && ChangString.isNumeric(longpressxy[2])) { - LongPressOptions lpoptions = new LongPressOptions(); - lpoptions.withPosition(PointOption.point(longpressx, longpressy)); - int nanos = Integer.valueOf(longpressxy[2]) * 1000; - Duration duration = Duration.ofNanos(nanos); - lpoptions.withDuration(duration); - action.longPress(lpoptions).release().perform(); - result = "longpressxy在屏幕指定XY坐标上按住" + longpressxy[2] + "秒...X|Y【" + longpressx + "|" + longpressy - + "】"; - LogUtil.APP.info("longpressxy在屏幕指定XY坐标上按住{}秒...X|Y【{}|{}】",longpressxy[2],longpressx,longpressy); - } else { - action.longPress(PointOption.point(longpressx, longpressy)).release().perform(); - result = "longpressxy在屏幕指定XY坐标上长按...X|Y【" + longpressx + "|" + longpressy + "】"; - LogUtil.APP.info("longpressxy在屏幕指定XY坐标上长按...X|Y【{}|{}】",longpressx,longpressy); - } - } else { - result = "longpressxy参数指定的Y坐标处理出现异常【" + longpressxy[1] + "】"; - LogUtil.APP.info("longpressxy参数指定的Y坐标处理出现异常【{}】",longpressxy[1]); - } - } else { - result = "longpressxy参数指定的X坐标处理出现异常【" + longpressxy[0] + "】"; - LogUtil.APP.info("longpressxy参数指定的X坐标处理出现异常【{}】",longpressxy[0]); - } - break; - case "pressxy": - String[] pressxy = operationValue.split("\\|", -1); - if (null != pressxy[0] && ChangString.isNumeric(pressxy[0])) { - int pressx = Integer.valueOf(pressxy[0]); - if (null != pressxy[1] && ChangString.isNumeric(pressxy[1])) { - int pressy = Integer.valueOf(pressxy[1]); - action.press(PointOption.point(pressx, pressy)).release().perform(); - result = "pressxy在屏幕指定XY坐标上点击...X|Y【" + pressx + "|" + pressy + "】"; - LogUtil.APP.info("pressxy在屏幕指定XY坐标上点击...X|Y【{}|{}】",pressx,pressy); - } else { - result = "pressxy参数指定的Y坐标处理出现异常【" + pressxy[1] + "】"; - LogUtil.APP.info("pressxy参数指定的Y坐标处理出现异常【{}】",pressxy[1]); - } - } else { - result = "pressxy参数指定的X坐标处理出现异常【" + pressxy[0] + "】"; - LogUtil.APP.info("pressxy参数指定的X坐标处理出现异常【{}】",pressxy[0]); - } - break; - case "tapxy": - String[] tapxy = operationValue.split("\\|", -1); - if (null != tapxy[0] && ChangString.isNumeric(tapxy[0])) { - int tapx = Integer.valueOf(tapxy[0]); - if (null != tapxy[1] && ChangString.isNumeric(tapxy[1])) { - int tapy = Integer.valueOf(tapxy[1]); - action.tap(PointOption.point(tapx, tapy)).release().perform(); - result = "tapxy在屏幕指定XY坐标上轻击...X|Y【" + tapx + "|" + tapy + "】"; - LogUtil.APP.info("tapxy在屏幕指定XY坐标上轻击...X|Y【{}|{}】",tapx,tapy); - } else { - result = "tapxy参数指定的Y坐标处理出现异常【" + tapxy[1] + "】"; - LogUtil.APP.info("tapxy参数指定的Y坐标处理出现异常【{}】",tapxy[1]); - } - } else { - result = "tapxy参数指定的X坐标处理出现异常【" + tapxy[0] + "】"; - LogUtil.APP.info("tapxy参数指定的X坐标处理出现异常【{}】",tapxy[0]); - } - break; - case "jspressxy": - String[] jspressxy = operationValue.split("\\|", -1); - if (null != jspressxy[0] && ChangString.isNumeric(jspressxy[0])) { - int jspressx = Integer.valueOf(jspressxy[0]); - if (null != jspressxy[1] && ChangString.isNumeric(jspressxy[1])) { - int jspressy = Integer.valueOf(jspressxy[1]); - if (null != jspressxy[2] && ChangString.isNumeric(jspressxy[2])) { - AndroidBaseAppium.clickScreenForJs(appium, jspressx, jspressy, Integer.valueOf(jspressxy[2])); - result = "jspressxy在屏幕指定XY坐标上按" + jspressxy[2] + "秒...X|Y【" + jspressx + "|" + jspressy + "】"; - LogUtil.APP.info("jspressxy在屏幕指定XY坐标上按{}秒...X|Y【{}|{}】",jspressxy[2],jspressx,jspressy); - } else { - AndroidBaseAppium.clickScreenForJs(appium, jspressx, jspressy, 2); - result = "jspressxy在屏幕指定XY坐标上按2秒(持续时间判断异常,使用默认2秒时间)...X|Y【" + jspressx + "|" + jspressy + "】"; - LogUtil.APP.info("jspressxy在屏幕指定XY坐标上按2秒(持续时间判断异常,使用默认2秒时间)...X|Y【{}|{}】",jspressx,jspressy); - } - } else { - result = "jspressxy参数指定的Y坐标处理出现异常【" + jspressxy[1] + "】"; - LogUtil.APP.info("jspressxy参数指定的Y坐标处理出现异常【{}】",jspressxy[1]); - } - } else { - result = "jspressxy参数指定的X坐标处理出现异常【" + jspressxy[0] + "】"; - LogUtil.APP.info("jspressxy参数指定的X坐标处理出现异常【{}】",jspressxy[0]); - } - break; - case "moveto": - String[] movexy = operationValue.split("\\|", -1); - if (null != movexy[0] && !"".equals(movexy[0])) { - String[] startxy = movexy[0].split(",", -1); - int startx = Integer.valueOf(startxy[0]); - int starty = Integer.valueOf(startxy[1]); - for (int movexyi = 1; movexyi < movexy.length; movexyi++) { - if (null != movexy[movexyi] && !"".equals(movexy[movexyi])) { - String[] endxy = movexy[movexyi].split(",", -1); - int endx = Integer.valueOf(endxy[0]); - int endy = Integer.valueOf(endxy[1]); - // 不确定是否是API的bug,只有一次MOVE时,是XY坐标,当大于一次MOVE时,坐标是偏移坐标 - if (movexy.length < 3) { - action.press(PointOption.point(startx, starty)) - .waitAction(WaitOptions.waitOptions(Duration.ofNanos(1500))) - .moveTo(PointOption.point(endx, endy)); - LogUtil.APP.info("从开始坐标【{},{}】拖动至坐标【{},{}】",startxy[0],startxy[1],endxy[0],endxy[1]); - } else { - if (movexyi == 1) { - action.press(PointOption.point(startx, starty)) - .waitAction(WaitOptions.waitOptions(Duration.ofNanos(1500))) - .moveTo(PointOption.point(endx - startx, endy - starty)); - LogUtil.APP.info("从开始坐标【{},{}】拖动至坐标【{},{}】",startxy[0],startxy[1],endxy[0],endxy[1]); - } else { - action.waitAction(WaitOptions.waitOptions(Duration.ofNanos(1500))) - .moveTo(PointOption.point(endx - startx, endy - starty)); - LogUtil.APP - .info("第{}次拖动至坐标【{},{}】",movexyi,endxy[0],endxy[1]); - } - startx = endx; - starty = endy; - } - } else { - LogUtil.APP.warn("判断结束坐标位置出现异常,结束坐标参数【{}】",movexy[movexyi]); - } - } - action.release().perform(); - result = "moveto全部拖动释放并完成发送...开始位置【" + startxy[0] + "," + startxy[1] + "】"; - LogUtil.APP.info("moveto全部拖动释放并完成发送...开始位置【{},{}】",startxy[0],startxy[1]); - } else { - result = "moveto参数指定的起始坐标处理出现异常【" + movexy[0] + "】,请检查!"; - LogUtil.APP.info("moveto参数指定的起始坐标处理出现异常【{}】,请检查!",movexy[0]); - } - break; - case "timeout": - if (null != operationValue && ChangString.isNumeric(operationValue)) { - // 设置页面加载最大时长30秒 - appium.manage().timeouts().pageLoadTimeout(Integer.valueOf(operationValue), TimeUnit.SECONDS); - // 设置元素出现最大时长30秒 - appium.manage().timeouts().implicitlyWait(Integer.valueOf(operationValue), TimeUnit.SECONDS); - result = "设置全局页面加载&元素出现最大等待时间【" + operationValue + "】秒..."; - LogUtil.APP.info("设置全局页面加载&元素出现最大等待时间【{}】秒...",operationValue); - } else { - result = "【等待时间转换出错,请检查参数】"; - LogUtil.APP.info(result + "原因是因为判断你的等待时间不是数字..."); - } - break; - case "screenshot": - java.text.DateFormat timeformat = new java.text.SimpleDateFormat("MMdd-HHmmss"); - String imagname = "FunctionScreenShot_" + timeformat.format(new Date()); - AndroidBaseAppium.screenShot(appium, imagname); - result = "截图名称【" + imagname + "】..."; - LogUtil.APP.info("使用方法主动截取当前屏幕...{}",result); - break; - default: - break; - } - return result; - } - - public static void main(String[] args) { - // TODO Auto-generated method stub - - } - -} +package luckyclient.execution.appium.androidex; + +import java.time.Duration; +import java.util.Date; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.openqa.selenium.Alert; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.support.ui.Select; + +import cn.hutool.core.util.StrUtil; +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import io.appium.java_client.android.AndroidTouchAction; +import io.appium.java_client.android.nativekey.AndroidKey; +import io.appium.java_client.android.nativekey.KeyEvent; +import io.appium.java_client.touch.LongPressOptions; +import io.appium.java_client.touch.WaitOptions; +import io.appium.java_client.touch.offset.ElementOption; +import io.appium.java_client.touch.offset.PointOption; +import luckyclient.execution.dispose.ChangString; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author Seagull + * @date 2017年1月29日 上午9:31:42 + */ +public class AndroidEncapsulateOperation { + /** + * select控件关键字处理 + * @param ae UI对象 + * @param operation 操作关键字 + * @param operationValue 操作值 + * @return 返回操作结果 + */ + public static String selectOperation(AndroidElement ae, String operation, String operationValue) { + String result = ""; + // 下拉框对象处理 + Select select = new Select(ae); + + // 处理下拉框事件 + switch (operation) { + case "selectbyvisibletext": + select.selectByVisibleText(operationValue); + LogUtil.APP + .info("下拉框对象通过VisibleText属性选择...【VisibleText属性值:{}】",operationValue); + break; + case "selectbyvalue": + select.selectByValue(operationValue); + LogUtil.APP.info("下拉框对象通过Value属性选择...【Value属性值:{}】",operationValue); + break; + case "selectbyindex": + select.selectByIndex(Integer.parseInt(operationValue)); + LogUtil.APP.info("下拉框对象通过Index属性选择...【Index属性值:{}】",operationValue); + break; + case "isselect": + result = "获取到的值是【" + ae.isSelected() + "】"; + LogUtil.APP.info("判断对象是否已经被选择...【结果值:{}】",ae.isSelected()); + break; + default: + break; + } + return result; + } + + public static String getOperation(AndroidElement ae, String operation, String value) { + String result = ""; + // 获取对象处理 + switch (operation) { + case "gettext": + result = "获取到的值是【" + ae.getText() + "】"; + LogUtil.APP.info("getText获取对象text属性...【text属性值:{}】",result); + break; // 获取输入框内容 + case "gettagname": + result = "获取到的值是【" + ae.getTagName() + "】"; + LogUtil.APP.info("getTagName获取对象tagname属性...【tagname属性值:{}】",result); + break; + case "getattribute": + result = "获取到的值是【" + ae.getAttribute(value) + "】"; + LogUtil.APP + .info("getAttribute获取对象【{}】属性...【{}属性值:{}】",value,value,result); + break; + case "getcssvalue": + result = "获取到的值是【" + ae.getCssValue(value) + "】"; + LogUtil.APP + .info("getCssValue获取对象【{}】属性...【{}属性值:{}】",value,value,result); + break; + default: + break; + } + return result; + } + + public static String objectOperation(AndroidDriver appium, AndroidElement ae, String operation, + String operationValue, String property, String propertyValue) { + String result = ""; + AndroidTouchAction action = new AndroidTouchAction(appium); + + // 处理WebElement对象操作 + switch (operation) { + case "click": + ae.click(); + result = "click点击对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; + LogUtil.APP + .info("click点击对象...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); + break; + case "sendkeys": + ae.sendKeys(operationValue); + result = "sendKeys对象输入...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "; 操作值:" + operationValue + + "】"; + LogUtil.APP.info("sendkeys对象输入...【对象定位属性:{}; 定位属性值:{}; 操作值:{}】",property,propertyValue,operationValue); + break; + case "clear": + ae.clear(); + result = "clear清空输入框...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; + LogUtil.APP + .info("clear清空输入框...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); + break; // 清空输入框 + case "isenabled": + result = "获取到的值是【" + ae.isEnabled() + "】"; + LogUtil.APP.info("当前对象判断是否可用布尔值为【{}】",ae.isEnabled()); + break; + case "isdisplayed": + result = "获取到的值是【" + ae.isDisplayed() + "】"; + LogUtil.APP.info("当前对象判断是否可见布尔值为【{}】",ae.isDisplayed()); + break; + case "exjsob": + ((JavascriptExecutor) appium).executeScript(operationValue, ae); + result = "执行JS...【" + operationValue + "】"; + LogUtil.APP.info("执行JS...【{}】",operationValue); + break; + case "longpresselement": + LongPressOptions lpoptions = new LongPressOptions(); + lpoptions.withElement(ElementOption.element(ae)); + if (null != operationValue && ChangString.isNumeric(operationValue)) { + int nanos = Integer.parseInt(operationValue) * 1000; + Duration duration = Duration.ofNanos(nanos); + lpoptions.withDuration(duration); + } + action.longPress(lpoptions).release().perform(); + result = "longpresselement在屏幕指定元素上按住" + operationValue + "秒...【对象定位属性:" + property + "; 定位属性值:" + + propertyValue + "】"; + LogUtil.APP.info("longpresselement在屏幕指定元素上按住{}秒...【对象定位属性:{}; 定位属性值:{}】",operationValue,property,propertyValue); + break; + default: + break; + } + return result; + } + + public static String alertOperation(AndroidDriver appium, String operation) { + String result = ""; + Alert alert = appium.switchTo().alert(); + switch (operation) { + case "alertaccept": + alert.accept(); + LogUtil.APP.info("弹出框对象点击同意..."); + break; + case "alertdismiss": + alert.dismiss(); + LogUtil.APP.info("弹出框对象点击取消..."); + break; + case "alertgettext": + result = "获取到的值是【" + alert.getText() + "】"; + LogUtil.APP.info("弹出框对象通过getText获取对象text属性...【Text属性值:{}】",alert.getText()); + break; + default: + break; + } + return result; + } + + public static String driverOperation(AndroidDriver appium, String operation, String operationValue) + throws Exception { + String result = ""; + AndroidTouchAction action = new AndroidTouchAction(appium); + // 处理页面对象操作 + switch (operation) { + case "getcontexthandles": + Set handles = appium.getContextHandles(); + int handlenum = 1; + for (String handle : handles) { + if (String.valueOf(handlenum).equals(operationValue)) { + if (appium.getContext().equals(handle)) { + result = "请注意,你指定的ContextHandle就是当前页面哦,获取到的值是【" + handle + "】"; + } else { + result = "指定ContextHandler的顺序值是" + operationValue + ",获取到的值是【" + handle + "】"; + } + break; + } + handlenum++; + } + LogUtil.APP.info("getContext获取窗口句柄...{}",result); + break; + case "exjs": + ((JavascriptExecutor) appium).executeScript(operationValue); + result = "执行JS...【" + operationValue + "】"; + LogUtil.APP.info("执行JS...【{}】",operationValue); + break; + case "exAdbShell": + Runtime.getRuntime().exec(operationValue); + result = "执行安卓adb命令...【" + operationValue + "】"; + LogUtil.APP.info("执行安卓adb命令...【{}】",operationValue); + break; + case "androidkeycode": + // 模拟手机键盘 + try { + if (StrUtil.isNotBlank(operationValue)) { + KeyEvent keyEvent = new KeyEvent(); + appium.pressKey(keyEvent.withKey(AndroidKey.valueOf(operationValue))); + result = "模拟手机键盘发送指令...keycode【" + operationValue + "】"; + LogUtil.APP.info("模拟手机键盘发送指令...keycode【{}】", operationValue); + } else { + result = "模拟手机键盘失败,键盘参数为空,请检查你的参数!"; + LogUtil.APP.info("模拟手机键盘失败,键盘参数为空,请检查你的参数!"); + } + } catch (IllegalArgumentException ae) { + result = "模拟手机按键失败,没有找到对应的按键参数,请检查你的参数!"; + LogUtil.APP.info("模拟手机按键失败,没有找到对应的按键参数,请检查你的参数!"); + } + break; + // 隐藏手机键盘 + case "hidekeyboard": + appium.hideKeyboard(); + result = "隐藏手机键盘...【hideKeyboard】"; + LogUtil.APP.info("隐藏手机键盘...【hideKeyboard】"); + break; + case "gotocontext": + Set ctNames = appium.getContextHandles(); + int flag = 0; + for (String contextName : ctNames) { + if (contextName.contains(operationValue)) { + flag = 1; + appium.context(contextName); + break; + } + } + if (flag == 1) { + result = "切换context至【" + operationValue + "】"; + LogUtil.APP.info("切换context至【{}】",operationValue); + } else { + result = "切换context失败,未找到contextName值为【" + operationValue + "】的对象"; + LogUtil.APP.info("切换context失败,未找到contextName值为【{}】的对象",operationValue); + } + break; + case "getcontext": + result = "获取到的值是【" + appium.getContext() + "】"; + LogUtil.APP.info("获取页面Context...【{}】",appium.getContext()); + break; + case "gettitle": + result = "获取到的值是【" + appium.getTitle() + "】"; + LogUtil.APP.info("获取页面gettitle...【{}】",appium.getTitle()); + break; + case "swipeup": + String[] tempup = operationValue.split("\\|", -1); + if (null != tempup[0] && ChangString.isNumeric(tempup[0])) { + Double second = Double.valueOf(tempup[0]); + if (null != tempup[1] && ChangString.isNumeric(tempup[1])) { + int num = Integer.parseInt(tempup[1]); + AndroidBaseAppium.swipePageDown(appium, second, num); + result = "swipeup手指向上滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipeup手指向上滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipeup手指向上滑动参数判断次数出现异常【" + tempup[1] + "】"; + LogUtil.APP.info("swipeup手指向上滑动参数判断次数出现异常【{}】",tempup[1]); + } + } else { + result = "swipeup手指向上滑动参数判断时间出现异常【" + tempup[0] + "】"; + LogUtil.APP.info("swipeup手指向上滑动参数判断时间出现异常【{}】",tempup[0]); + } + break; + case "swipedown": + String[] tempdown = operationValue.split("\\|", -1); + if (null != tempdown[0] && ChangString.isNumeric(tempdown[0])) { + Double second = Double.valueOf(tempdown[0]); + if (null != tempdown[1] && ChangString.isNumeric(tempdown[1])) { + int num = Integer.parseInt(tempdown[1]); + AndroidBaseAppium.swipePageUp(appium, second, num); + result = "swipedown手指向下滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipedown手指向下滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipedown手指向下滑动参数判断次数出现异常【" + tempdown[1] + "】"; + LogUtil.APP.info("swipedown手指向下滑动参数判断次数出现异常【{}】",tempdown[1]); + } + } else { + result = "swipedown手指向下滑动参数判断时间出现异常【" + tempdown[0] + "】"; + LogUtil.APP.info("swipedown手指向下滑动参数判断时间出现异常【{}】",tempdown[0]); + } + break; + case "swipeleft": + String[] templeft = operationValue.split("\\|", -1); + if (null != templeft[0] && ChangString.isNumeric(templeft[0])) { + Double second = Double.valueOf(templeft[0]); + if (null != templeft[1] && ChangString.isNumeric(templeft[1])) { + int num = Integer.parseInt(templeft[1]); + AndroidBaseAppium.swipePageRight(appium, second, num); + result = "swipleft手指向左滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipleft手指向左滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipleft手指向左滑动参数判断次数出现异常【" + templeft[1] + "】"; + LogUtil.APP.info("swipleft手指向左滑动参数判断次数出现异常【{}】",templeft[1]); + } + } else { + result = "swipleft手指向左滑动参数判断时间出现异常【" + templeft[0] + "】"; + LogUtil.APP.info("swipleft手指向左滑动参数判断时间出现异常【{}】",templeft[0]); + } + break; + case "swiperight": + String[] tempright = operationValue.split("\\|", -1); + if (null != tempright[0] && ChangString.isNumeric(tempright[0])) { + Double second = Double.valueOf(tempright[0]); + if (null != tempright[1] && ChangString.isNumeric(tempright[1])) { + int num = Integer.parseInt(tempright[1]); + AndroidBaseAppium.swipePageLeft(appium, second, num); + result = "swipright手指向右滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipright手指向右滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipright手指向右滑动参数判断次数出现异常【" + tempright[1] + "】"; + LogUtil.APP.info("swipright手指向右滑动参数判断次数出现异常【{}】",tempright[1]); + } + } else { + result = "swipright手指向右滑动参数判断时间出现异常【" + tempright[0] + "】"; + LogUtil.APP.info("swipright手指向右滑动参数判断时间出现异常【{}】",tempright[0]); + } + break; + case "swipepageup": + String[] tempPageUp = operationValue.split("\\|", -1); + if (null != tempPageUp[0] && ChangString.isNumeric(tempPageUp[0])) { + Double second = Double.valueOf(tempPageUp[0]); + if (null != tempPageUp[1] && ChangString.isNumeric(tempPageUp[1])) { + int num = Integer.parseInt(tempPageUp[1]); + AndroidBaseAppium.swipePageUp(appium, second, num); + result = "swipeup页面向上滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipeup页面向上滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipeup页面向上滑动参数判断次数出现异常【" + tempPageUp[1] + "】"; + LogUtil.APP.info("swipeup页面向上滑动参数判断次数出现异常【{}】",tempPageUp[1]); + } + } else { + result = "swipeup页面向上滑动参数判断时间出现异常【" + tempPageUp[0] + "】"; + LogUtil.APP.info("swipeup页面向上滑动参数判断时间出现异常【{}】",tempPageUp[0]); + } + break; + case "swipepagedown": + String[] tempPageDown = operationValue.split("\\|", -1); + if (null != tempPageDown[0] && ChangString.isNumeric(tempPageDown[0])) { + Double second = Double.valueOf(tempPageDown[0]); + if (null != tempPageDown[1] && ChangString.isNumeric(tempPageDown[1])) { + int num = Integer.parseInt(tempPageDown[1]); + AndroidBaseAppium.swipePageDown(appium, second, num); + result = "swipedown页面向下滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipedown页面向下滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipedown页面向下滑动参数判断次数出现异常【" + tempPageDown[1] + "】"; + LogUtil.APP.info("swipedown页面向下滑动参数判断次数出现异常【{}】",tempPageDown[1]); + } + } else { + result = "swipedown页面向下滑动参数判断时间出现异常【" + tempPageDown[0] + "】"; + LogUtil.APP.info("swipedown页面向下滑动参数判断时间出现异常【{}】",tempPageDown[0]); + } + break; + case "swipepageleft": + String[] tempPageLeft = operationValue.split("\\|", -1); + if (null != tempPageLeft[0] && ChangString.isNumeric(tempPageLeft[0])) { + Double second = Double.valueOf(tempPageLeft[0]); + if (null != tempPageLeft[1] && ChangString.isNumeric(tempPageLeft[1])) { + int num = Integer.parseInt(tempPageLeft[1]); + AndroidBaseAppium.swipePageLeft(appium, second, num); + result = "swipleft页面向左滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipleft页面向左滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipleft页面向左滑动参数判断次数出现异常【" + tempPageLeft[1] + "】"; + LogUtil.APP.info("swipleft页面向左滑动参数判断次数出现异常【{}】",tempPageLeft[1]); + } + } else { + result = "swipleft页面向左滑动参数判断时间出现异常【" + tempPageLeft[0] + "】"; + LogUtil.APP.info("swipleft页面向左滑动参数判断时间出现异常【{}】",tempPageLeft[0]); + } + break; + case "swipepageright": + String[] tempPageRight = operationValue.split("\\|", -1); + if (null != tempPageRight[0] && ChangString.isNumeric(tempPageRight[0])) { + Double second = Double.valueOf(tempPageRight[0]); + if (null != tempPageRight[1] && ChangString.isNumeric(tempPageRight[1])) { + int num = Integer.parseInt(tempPageRight[1]); + AndroidBaseAppium.swipePageRight(appium, second, num); + result = "swipright页面向右滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipright页面向右滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipright页面向右滑动参数判断次数出现异常【" + tempPageRight[1] + "】"; + LogUtil.APP.info("swipright页面向右滑动参数判断次数出现异常【{}】",tempPageRight[1]); + } + } else { + result = "swipright页面向右滑动参数判断时间出现异常【" + tempPageRight[0] + "】"; + LogUtil.APP.info("swipright页面向右滑动参数判断时间出现异常【{}】",tempPageRight[0]); + } + break; + case "longpressxy": + String[] longpressxy = operationValue.split("\\|", -1); + if (null != longpressxy[0] && ChangString.isNumeric(longpressxy[0])) { + int longpressx = Integer.parseInt(longpressxy[0]); + if (null != longpressxy[1] && ChangString.isNumeric(longpressxy[1])) { + int longpressy = Integer.parseInt(longpressxy[1]); + if (null != longpressxy[2] && ChangString.isNumeric(longpressxy[2])) { + LongPressOptions lpoptions = new LongPressOptions(); + lpoptions.withPosition(PointOption.point(longpressx, longpressy)); + int nanos = Integer.parseInt(longpressxy[2]) * 1000; + Duration duration = Duration.ofNanos(nanos); + lpoptions.withDuration(duration); + action.longPress(lpoptions).release().perform(); + result = "longpressxy在屏幕指定XY坐标上按住" + longpressxy[2] + "秒...X|Y【" + longpressx + "|" + longpressy + + "】"; + LogUtil.APP.info("longpressxy在屏幕指定XY坐标上按住{}秒...X|Y【{}|{}】",longpressxy[2],longpressx,longpressy); + } else { + action.longPress(PointOption.point(longpressx, longpressy)).release().perform(); + result = "longpressxy在屏幕指定XY坐标上长按...X|Y【" + longpressx + "|" + longpressy + "】"; + LogUtil.APP.info("longpressxy在屏幕指定XY坐标上长按...X|Y【{}|{}】",longpressx,longpressy); + } + } else { + result = "longpressxy参数指定的Y坐标处理出现异常【" + longpressxy[1] + "】"; + LogUtil.APP.info("longpressxy参数指定的Y坐标处理出现异常【{}】",longpressxy[1]); + } + } else { + result = "longpressxy参数指定的X坐标处理出现异常【" + longpressxy[0] + "】"; + LogUtil.APP.info("longpressxy参数指定的X坐标处理出现异常【{}】",longpressxy[0]); + } + break; + case "pressxy": + String[] pressxy = operationValue.split("\\|", -1); + if (null != pressxy[0] && ChangString.isNumeric(pressxy[0])) { + int pressx = Integer.parseInt(pressxy[0]); + if (null != pressxy[1] && ChangString.isNumeric(pressxy[1])) { + int pressy = Integer.parseInt(pressxy[1]); + action.press(PointOption.point(pressx, pressy)).release().perform(); + result = "pressxy在屏幕指定XY坐标上点击...X|Y【" + pressx + "|" + pressy + "】"; + LogUtil.APP.info("pressxy在屏幕指定XY坐标上点击...X|Y【{}|{}】",pressx,pressy); + } else { + result = "pressxy参数指定的Y坐标处理出现异常【" + pressxy[1] + "】"; + LogUtil.APP.info("pressxy参数指定的Y坐标处理出现异常【{}】",pressxy[1]); + } + } else { + result = "pressxy参数指定的X坐标处理出现异常【" + pressxy[0] + "】"; + LogUtil.APP.info("pressxy参数指定的X坐标处理出现异常【{}】",pressxy[0]); + } + break; + case "tapxy": + String[] tapxy = operationValue.split("\\|", -1); + if (null != tapxy[0] && ChangString.isNumeric(tapxy[0])) { + int tapx = Integer.parseInt(tapxy[0]); + if (null != tapxy[1] && ChangString.isNumeric(tapxy[1])) { + int tapy = Integer.parseInt(tapxy[1]); + action.tap(PointOption.point(tapx, tapy)).release().perform(); + result = "tapxy在屏幕指定XY坐标上轻击...X|Y【" + tapx + "|" + tapy + "】"; + LogUtil.APP.info("tapxy在屏幕指定XY坐标上轻击...X|Y【{}|{}】",tapx,tapy); + } else { + result = "tapxy参数指定的Y坐标处理出现异常【" + tapxy[1] + "】"; + LogUtil.APP.info("tapxy参数指定的Y坐标处理出现异常【{}】",tapxy[1]); + } + } else { + result = "tapxy参数指定的X坐标处理出现异常【" + tapxy[0] + "】"; + LogUtil.APP.info("tapxy参数指定的X坐标处理出现异常【{}】",tapxy[0]); + } + break; + case "jspressxy": + String[] jspressxy = operationValue.split("\\|", -1); + if (null != jspressxy[0] && ChangString.isNumeric(jspressxy[0])) { + int jspressx = Integer.parseInt(jspressxy[0]); + if (null != jspressxy[1] && ChangString.isNumeric(jspressxy[1])) { + int jspressy = Integer.parseInt(jspressxy[1]); + if (null != jspressxy[2] && ChangString.isNumeric(jspressxy[2])) { + AndroidBaseAppium.clickScreenForJs(appium, jspressx, jspressy, Integer.parseInt(jspressxy[2])); + result = "jspressxy在屏幕指定XY坐标上按" + jspressxy[2] + "秒...X|Y【" + jspressx + "|" + jspressy + "】"; + LogUtil.APP.info("jspressxy在屏幕指定XY坐标上按{}秒...X|Y【{}|{}】",jspressxy[2],jspressx,jspressy); + } else { + AndroidBaseAppium.clickScreenForJs(appium, jspressx, jspressy, 2); + result = "jspressxy在屏幕指定XY坐标上按2秒(持续时间判断异常,使用默认2秒时间)...X|Y【" + jspressx + "|" + jspressy + "】"; + LogUtil.APP.info("jspressxy在屏幕指定XY坐标上按2秒(持续时间判断异常,使用默认2秒时间)...X|Y【{}|{}】",jspressx,jspressy); + } + } else { + result = "jspressxy参数指定的Y坐标处理出现异常【" + jspressxy[1] + "】"; + LogUtil.APP.info("jspressxy参数指定的Y坐标处理出现异常【{}】",jspressxy[1]); + } + } else { + result = "jspressxy参数指定的X坐标处理出现异常【" + jspressxy[0] + "】"; + LogUtil.APP.info("jspressxy参数指定的X坐标处理出现异常【{}】",jspressxy[0]); + } + break; + case "moveto": + String[] movexy = operationValue.split("\\|", -1); + if (null != movexy[0] && !"".equals(movexy[0])) { + String[] startxy = movexy[0].split(",", -1); + int startx = Integer.parseInt(startxy[0]); + int starty = Integer.parseInt(startxy[1]); + for (int movexyi = 1; movexyi < movexy.length; movexyi++) { + if (null != movexy[movexyi] && !"".equals(movexy[movexyi])) { + String[] endxy = movexy[movexyi].split(",", -1); + int endx = Integer.parseInt(endxy[0]); + int endy = Integer.parseInt(endxy[1]); + // 不确定是否是API的bug,只有一次MOVE时,是XY坐标,当大于一次MOVE时,坐标是偏移坐标 + if (movexy.length < 3) { + action.press(PointOption.point(startx, starty)) + .waitAction(WaitOptions.waitOptions(Duration.ofNanos(1500))) + .moveTo(PointOption.point(endx, endy)); + LogUtil.APP.info("从开始坐标【{},{}】拖动至坐标【{},{}】",startxy[0],startxy[1],endxy[0],endxy[1]); + } else { + if (movexyi == 1) { + action.press(PointOption.point(startx, starty)) + .waitAction(WaitOptions.waitOptions(Duration.ofNanos(1500))) + .moveTo(PointOption.point(endx - startx, endy - starty)); + LogUtil.APP.info("从开始坐标【{},{}】拖动至坐标【{},{}】",startxy[0],startxy[1],endxy[0],endxy[1]); + } else { + action.waitAction(WaitOptions.waitOptions(Duration.ofNanos(1500))) + .moveTo(PointOption.point(endx - startx, endy - starty)); + LogUtil.APP + .info("第{}次拖动至坐标【{},{}】",movexyi,endxy[0],endxy[1]); + } + startx = endx; + starty = endy; + } + } else { + LogUtil.APP.warn("判断结束坐标位置出现异常,结束坐标参数【{}】",movexy[movexyi]); + } + } + action.release().perform(); + result = "moveto全部拖动释放并完成发送...开始位置【" + startxy[0] + "," + startxy[1] + "】"; + LogUtil.APP.info("moveto全部拖动释放并完成发送...开始位置【{},{}】",startxy[0],startxy[1]); + } else { + result = "moveto参数指定的起始坐标处理出现异常【" + movexy[0] + "】,请检查!"; + LogUtil.APP.info("moveto参数指定的起始坐标处理出现异常【{}】,请检查!",movexy[0]); + } + break; + case "timeout": + if (null != operationValue && ChangString.isNumeric(operationValue)) { + // 设置页面加载最大时长30秒 + appium.manage().timeouts().pageLoadTimeout(Integer.parseInt(operationValue), TimeUnit.SECONDS); + // 设置元素出现最大时长30秒 + appium.manage().timeouts().implicitlyWait(Integer.parseInt(operationValue), TimeUnit.SECONDS); + result = "设置全局页面加载&元素出现最大等待时间【" + operationValue + "】秒..."; + LogUtil.APP.info("设置全局页面加载&元素出现最大等待时间【{}】秒...",operationValue); + } else { + result = "【等待时间转换出错,请检查参数】"; + LogUtil.APP.info(result + "原因是因为判断你的等待时间不是数字..."); + } + break; + case "screenshot": + java.text.DateFormat timeformat = new java.text.SimpleDateFormat("MMdd-HHmmss"); + String imagname = "FunctionScreenShot_" + timeformat.format(new Date()); + AndroidBaseAppium.screenShot(appium, imagname); + result = "截图名称【" + imagname + "】..."; + LogUtil.APP.info("使用方法主动截取当前屏幕...{}",result); + break; + default: + break; + } + return result; + } + +} diff --git a/src/main/java/luckyclient/execution/appium/androidex/AndroidOneCaseExecute.java b/src/main/java/luckyclient/execution/appium/androidex/AndroidOneCaseExecute.java index c610140..5fa8358 100644 --- a/src/main/java/luckyclient/execution/appium/androidex/AndroidOneCaseExecute.java +++ b/src/main/java/luckyclient/execution/appium/androidex/AndroidOneCaseExecute.java @@ -1,74 +1,75 @@ -package luckyclient.execution.appium.androidex; - -import java.io.IOException; -import java.util.List; -import java.util.Properties; - -import io.appium.java_client.android.AndroidDriver; -import io.appium.java_client.android.AndroidElement; -import luckyclient.execution.appium.AppiumInitialization; -import luckyclient.execution.appium.AppiumService; -import luckyclient.execution.httpinterface.TestControl; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.LogUtil; -import luckyclient.utils.config.AppiumConfig; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * - * @date 2018年1月26日 上午9:29:40 - * - */ -public class AndroidOneCaseExecute { - - public static void oneCaseExecuteForTast(String projectname, Integer caseId, int version, String taskid) - throws IOException, InterruptedException { - // 记录日志到数据库 - serverOperation.exetype = 0; - TestControl.TASKID = taskid; - AndroidDriver ad = null; - AppiumService as=null; - try { - Properties properties = AppiumConfig.getConfiguration(); - //根据配置自动启动Appiume服务 - if(Boolean.valueOf(properties.getProperty("autoRunAppiumService"))){ - as =new AppiumService(); - as.start(); - Thread.sleep(10000); - } - - ad = AppiumInitialization.setAndroidAppium(properties); - } catch (IOException e1) { - LogUtil.APP.error("初始化AndroidDriver出错!", e1); - } - serverOperation caselog = new serverOperation(); - // 删除旧的日志 - ProjectCase testcase = GetServerApi.cGetCaseByCaseId(caseId); - serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); - List pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); - LogUtil.APP.info("开始执行用例:【{}】......",testcase.getCaseSign()); - try { - List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); - AndroidCaseExecution.caseExcution(testcase, steps, taskid, ad, caselog, pcplist); - LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); - } catch (InterruptedException e) { - LogUtil.APP.error("用户执行过程中抛出异常!", e); - } - serverOperation.updateTaskExecuteData(taskid, 0,2); - ad.closeApp(); - //关闭Appium服务的线程 - if(as!=null){ - as.interrupt(); - } - } - -} +package luckyclient.execution.appium.androidex; + +import java.io.IOException; +import java.util.List; +import java.util.Properties; + +import io.appium.java_client.android.AndroidDriver; +import io.appium.java_client.android.AndroidElement; +import luckyclient.execution.appium.AppiumInitialization; +import luckyclient.execution.appium.AppiumService; +import luckyclient.execution.httpinterface.TestControl; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.LogUtil; +import luckyclient.utils.config.AppiumConfig; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * + * @date 2018年1月26日 上午9:29:40 + * + */ +public class AndroidOneCaseExecute { + + public static void oneCaseExecuteForTast(Integer caseId, String taskid) + throws InterruptedException { + // 记录日志到数据库 + serverOperation.exetype = 0; + TestControl.TASKID = taskid; + AndroidDriver ad = null; + AppiumService as=null; + try { + Properties properties = AppiumConfig.getConfiguration(); + //根据配置自动启动Appiume服务 + if(Boolean.parseBoolean(properties.getProperty("autoRunAppiumService"))){ + as =new AppiumService(); + as.start(); + Thread.sleep(10000); + } + + ad = AppiumInitialization.setAndroidAppium(properties); + } catch (IOException e1) { + LogUtil.APP.error("初始化AndroidDriver出错!", e1); + } + serverOperation caselog = new serverOperation(); + // 删除旧的日志 + ProjectCase testcase = GetServerApi.cGetCaseByCaseId(caseId); + serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); + List pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); + LogUtil.APP.info("开始执行用例:【{}】......",testcase.getCaseSign()); + try { + List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); + AndroidCaseExecution.caseExcution(testcase, steps, taskid, ad, caselog, pcplist); + LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); + } catch (Exception e) { + LogUtil.APP.error("用户执行过程中抛出异常!", e); + } + serverOperation.updateTaskExecuteData(taskid, 0,2); + assert ad != null; + ad.closeApp(); + //关闭Appium服务的线程 + if(as!=null){ + as.interrupt(); + } + } + +} diff --git a/src/main/java/luckyclient/execution/appium/iosex/IosBaseAppium.java b/src/main/java/luckyclient/execution/appium/iosex/IosBaseAppium.java index 2ab83a9..79c189e 100644 --- a/src/main/java/luckyclient/execution/appium/iosex/IosBaseAppium.java +++ b/src/main/java/luckyclient/execution/appium/iosex/IosBaseAppium.java @@ -1,216 +1,220 @@ -package luckyclient.execution.appium.iosex; - -import java.io.File; -import java.io.IOException; -import java.time.Duration; -import java.util.HashMap; - -import org.apache.commons.io.FileUtils; -import org.openqa.selenium.JavascriptExecutor; -import org.openqa.selenium.OutputType; -import org.openqa.selenium.TakesScreenshot; -import org.openqa.selenium.remote.Augmenter; - -import io.appium.java_client.ios.IOSDriver; -import io.appium.java_client.ios.IOSElement; -import io.appium.java_client.ios.IOSTouchAction; -import io.appium.java_client.touch.WaitOptions; -import io.appium.java_client.touch.offset.PointOption; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * @author: seagull - * @date 2018年2月2日 - * - */ -public class IosBaseAppium { - - /** - * @param args - * @throws IOException - * IOS手机报错截图 - */ - public static void screenShot(IOSDriver appium, String imagname){ - imagname = imagname + ".png"; - String relativelyPath = System.getProperty("user.dir"); - String pngpath=relativelyPath +File.separator+ "log"+File.separator+"ScreenShot" +File.separator+ imagname; - - try { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - LogUtil.APP.error("IOS手机报错截图休眠出现异常", e); - } - File imageFile = ((TakesScreenshot) (new Augmenter().augment(appium))).getScreenshotAs(OutputType.FILE); - File screenFile = new File(pngpath); - FileUtils.copyFile(imageFile, screenFile); - imageFile.deleteOnExit(); - LogUtil.APP - .info("已对当前界面进行截图操作,可通过用例执行界面的日志明细查看,也可以前往客户端上查看...【{}】",pngpath); - } catch (IOException e) { - LogUtil.APP.error("IOS手机报错截图出现异常", e); - } - } - - /** - * @param args - * @throws IOException - * appium不支持中文输入 参考了robotium的以js方式为元素直接设置value的做法 - * 利用Selenium中Webdriver执行js方法实现中文输入 - */ - public static void sendChinese(IOSDriver appium, String preferences, String value) { - org.openqa.selenium.JavascriptExecutor jse = (org.openqa.selenium.JavascriptExecutor) appium; - jse.executeScript("document.getElementByName('" + preferences + "').value='" + value + "'"); - } - - /** - * @param args - * js webview 支持4.1~4.4 - */ - public static void webViewSwipe(IOSDriver appium, Double sX, Double sY, Double eX, Double eY, Double duration) - throws Exception { - JavascriptExecutor js; - HashMap swipeObject; - try { - // 滑动 - js = (JavascriptExecutor) appium; - swipeObject = new HashMap(5); - swipeObject.put("startX", sX); - swipeObject.put("startY", sY); - swipeObject.put("endX", eX); - swipeObject.put("endY", eY); - swipeObject.put("duration", duration); - js.executeScript("mobile: swipe", swipeObject); - } catch (Exception e) { - // TODO Auto-generated catch block - LogUtil.APP.error("IOS手机滑动出现异常", e); - } finally { - // 释放变量 - } - - } - - /** - * @param args - * 调用 ADB直接滑动 支持4.1~4.4 - */ - public static void adbSwipe(IOSDriver appium, Double sX, Double sY, Double eX, Double eY) throws Exception { - int xLine; - int yLine; - int sX2; - int sY2; - int eX2; - int eY2; - try { - // 滑动 - xLine = appium.manage().window().getSize().getWidth(); - yLine = appium.manage().window().getSize().getHeight(); - - sX2 = (int) (xLine * sX); - sY2 = (int) (yLine * sY); - eX2 = (int) (xLine * eX); - eY2 = (int) (yLine * eY); - // logger.info("滑动11111111"); - Runtime.getRuntime() - .exec("adb -s " + "IOS" + " shell input swipe " + sX2 + " " + sY2 + " " + eX2 + " " + eY2); - } catch (Exception e) { - // TODO Auto-generated catch block - LogUtil.APP.error("IOS手机调用 ADB直接滑动出现异常", e); - } finally { - // 释放变量 - } - - } - - /** - * @param args - * 屏幕点击事件 - */ - public static void clickScreenForJs(IOSDriver drivers, int x, int y, int duration) { - JavascriptExecutor js = (JavascriptExecutor) drivers; - HashMap tapObject = new HashMap(3); - tapObject.put("x", x); - tapObject.put("y", y); - tapObject.put("duration", duration); - js.executeScript("mobile: tap", tapObject); - } - - /** - * 拖住页面按屏幕比例向上滑动(手指向下,页面向上) - * @param driver - * @param second 持续时间 - * @param num 滚动次数 - */ - public static void swipePageUp(IOSDriver driver, Double second, int num) { - int nanos = (int) (second * 1000); - Duration duration = Duration.ofNanos(nanos); - int width = driver.manage().window().getSize().width; - int height = driver.manage().window().getSize().height; - IOSTouchAction action = new IOSTouchAction(driver); - - for (int i = 0; i <= num; i++) { - action.press(PointOption.point(width / 2, 20)).waitAction(WaitOptions.waitOptions(duration)) - .moveTo(PointOption.point(width / 2, height-20)).release().perform(); - } - } - - /** - * 拖住页面按屏幕比例向下滑动(手指向上,页面向下) - * @param driver - * @param second - * @param num - */ - public static void swipePageDown(IOSDriver driver,Double second,int num){ - int nanos = (int) (second * 1000); - Duration duration = Duration.ofNanos(nanos); - int width = driver.manage().window().getSize().width; - int height = driver.manage().window().getSize().height; - IOSTouchAction action = new IOSTouchAction(driver); - for (int i = 0; i <= num; i++) { - action.press(PointOption.point(width / 2, height-20)).waitAction(WaitOptions.waitOptions(duration)) - .moveTo(PointOption.point(width / 2, 20)).release().perform(); - } - } - - /** - * 拖住页面按屏幕比例向左滑动(手指向左,页面向左滚动) - * @param driver - * @param second - * @param num - */ - public static void swipePageLeft(IOSDriver driver, Double second, int num) { - int nanos = (int) (second * 1000); - Duration duration = Duration.ofNanos(nanos); - int width = driver.manage().window().getSize().width; - int height = driver.manage().window().getSize().height; - IOSTouchAction action = new IOSTouchAction(driver); - for (int i = 0; i <= num; i++) { - action.press(PointOption.point(width - 10, height / 2)).waitAction(WaitOptions.waitOptions(duration)) - .moveTo(PointOption.point(10, height / 2)).release().perform(); - } - } - - /** - * 拖住页面按屏幕比例向右滑动(手指向右,页面向右) - * @param driver - * @param second - * @param num - */ - public static void swipePageRight(IOSDriver driver, Double second, int num) { - int nanos = (int) (second * 1000); - Duration duration = Duration.ofNanos(nanos); - int width = driver.manage().window().getSize().width; - int height = driver.manage().window().getSize().height; - IOSTouchAction action = new IOSTouchAction(driver); - for (int i = 0; i <= num; i++) { - action.press(PointOption.point(10, height / 2)).waitAction(WaitOptions.waitOptions(duration)) - .moveTo(PointOption.point(width - 10, height / 2)).release().perform(); - } - } - -} +package luckyclient.execution.appium.iosex; + +import java.io.File; +import java.io.IOException; +import java.time.Duration; +import java.util.HashMap; + +import org.apache.commons.io.FileUtils; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.OutputType; +import org.openqa.selenium.TakesScreenshot; +import org.openqa.selenium.remote.Augmenter; + +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.IOSElement; +import io.appium.java_client.ios.IOSTouchAction; +import io.appium.java_client.touch.WaitOptions; +import io.appium.java_client.touch.offset.PointOption; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * @author: seagull + * @date 2018年2月2日 + * + */ +public class IosBaseAppium { + + /** + * IOS手机报错截图 + * @param appium appium对象 + * @param imagname 截图名称 + */ + public static void screenShot(IOSDriver appium, String imagname){ + imagname = imagname + ".png"; + String relativelyPath = System.getProperty("user.dir"); + String pngpath=relativelyPath +File.separator+ "log"+File.separator+"ScreenShot" +File.separator+ imagname; + + try { + try { + Thread.sleep(3000); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + LogUtil.APP.error("IOS手机报错截图休眠出现异常", e); + } + File imageFile = ((TakesScreenshot) (new Augmenter().augment(appium))).getScreenshotAs(OutputType.FILE); + File screenFile = new File(pngpath); + FileUtils.copyFile(imageFile, screenFile); + imageFile.deleteOnExit(); + LogUtil.APP + .info("已对当前界面进行截图操作,可通过用例执行界面的日志明细查看,也可以前往客户端上查看...【{}】",pngpath); + } catch (IOException e) { + LogUtil.APP.error("IOS手机报错截图出现异常", e); + } + } + + /** + * appium不支持中文输入 参考了robotium的以js方式为元素直接设置value的做法 + * 利用Selenium中Webdriver执行js方法实现中文输入 + * @param appium appium对象 + * @param preferences 操作对象名称 + * @param value 操作值 + */ + public static void sendChinese(IOSDriver appium, String preferences, String value) { + ((JavascriptExecutor) appium).executeScript("document.getElementByName('" + preferences + "').value='" + value + "'"); + } + + /** + * js webview 支持4.1~4.4 页面滑动 + * @param appium appium初始化对象 + * @param sX 开始X坐标 + * @param sY 开始Y坐标 + * @param eX 结束X坐标 + * @param eY 结束Y坐标 + * @param duration 持续时间 + */ + public static void webViewSwipe(IOSDriver appium, Double sX, Double sY, Double eX, Double eY, Double duration) { + JavascriptExecutor js; + HashMap swipeObject; + try { + // 滑动 + js = appium; + swipeObject = new HashMap<>(5); + swipeObject.put("startX", sX); + swipeObject.put("startY", sY); + swipeObject.put("endX", eX); + swipeObject.put("endY", eY); + swipeObject.put("duration", duration); + js.executeScript("mobile: swipe", swipeObject); + } catch (Exception e) { + // TODO Auto-generated catch block + LogUtil.APP.error("IOS手机滑动出现异常", e); + } + } + + /** + * 调用 ADB直接滑动 支持4.1~4.4 + * @param appium appium初始化对象 + * @param sX 开始X坐标 + * @param sY 开始Y坐标 + * @param eX 结束X坐标 + * @param eY 结束Y坐标 + */ + public static void adbSwipe(IOSDriver appium, Double sX, Double sY, Double eX, Double eY) { + int xLine; + int yLine; + int sX2; + int sY2; + int eX2; + int eY2; + try { + // 滑动 + xLine = appium.manage().window().getSize().getWidth(); + yLine = appium.manage().window().getSize().getHeight(); + + sX2 = (int) (xLine * sX); + sY2 = (int) (yLine * sY); + eX2 = (int) (xLine * eX); + eY2 = (int) (yLine * eY); + // logger.info("滑动11111111"); + Runtime.getRuntime() + .exec("adb -s " + "IOS" + " shell input swipe " + sX2 + " " + sY2 + " " + eX2 + " " + eY2); + } catch (Exception e) { + // TODO Auto-generated catch block + LogUtil.APP.error("IOS手机调用 ADB直接滑动出现异常", e); + } + } + + /** + * 屏幕点击事件 + * @param drivers appium初始化对象 + * @param x 点击X坐标 + * @param y 点击Y坐标 + * @param duration 持续时间 + */ + public static void clickScreenForJs(IOSDriver drivers, int x, int y, int duration) { + HashMap tapObject = new HashMap<>(3); + tapObject.put("x", x); + tapObject.put("y", y); + tapObject.put("duration", duration); + ((JavascriptExecutor) drivers).executeScript("mobile: tap", tapObject); + } + + /** + * 拖住页面按屏幕比例向上滑动(手指向下,页面向上) + * @param driver appium初始化对象 + * @param second 持续时间 + * @param num 滚动次数 + */ + public static void swipePageUp(IOSDriver driver, Double second, int num) { + int nanos = (int) (second * 1000); + Duration duration = Duration.ofNanos(nanos); + int width = driver.manage().window().getSize().width; + int height = driver.manage().window().getSize().height; + IOSTouchAction action = new IOSTouchAction(driver); + + for (int i = 0; i <= num; i++) { + action.press(PointOption.point(width / 2, 20)).waitAction(WaitOptions.waitOptions(duration)) + .moveTo(PointOption.point(width / 2, height-20)).release().perform(); + } + } + + /** + * 拖住页面按屏幕比例向下滑动(手指向上,页面向下) + * @param driver appium初始化对象 + * @param second 持续时间 + * @param num 滑动次数 + */ + public static void swipePageDown(IOSDriver driver,Double second,int num){ + int nanos = (int) (second * 1000); + Duration duration = Duration.ofNanos(nanos); + int width = driver.manage().window().getSize().width; + int height = driver.manage().window().getSize().height; + IOSTouchAction action = new IOSTouchAction(driver); + for (int i = 0; i <= num; i++) { + action.press(PointOption.point(width / 2, height-20)).waitAction(WaitOptions.waitOptions(duration)) + .moveTo(PointOption.point(width / 2, 20)).release().perform(); + } + } + + /** + * 拖住页面按屏幕比例向左滑动(手指向左,页面向左滚动) + * @param driver appium初始化对象 + * @param second 持续时间 + * @param num 滑动次数 + */ + public static void swipePageLeft(IOSDriver driver, Double second, int num) { + int nanos = (int) (second * 1000); + Duration duration = Duration.ofNanos(nanos); + int width = driver.manage().window().getSize().width; + int height = driver.manage().window().getSize().height; + IOSTouchAction action = new IOSTouchAction(driver); + for (int i = 0; i <= num; i++) { + action.press(PointOption.point(width - 10, height / 2)).waitAction(WaitOptions.waitOptions(duration)) + .moveTo(PointOption.point(10, height / 2)).release().perform(); + } + } + + /** + * 拖住页面按屏幕比例向右滑动(手指向右,页面向右) + * @param driver appium初始化对象 + * @param second 持续时间 + * @param num 滑动次数 + */ + public static void swipePageRight(IOSDriver driver, Double second, int num) { + int nanos = (int) (second * 1000); + Duration duration = Duration.ofNanos(nanos); + int width = driver.manage().window().getSize().width; + int height = driver.manage().window().getSize().height; + IOSTouchAction action = new IOSTouchAction(driver); + for (int i = 0; i <= num; i++) { + action.press(PointOption.point(10, height / 2)).waitAction(WaitOptions.waitOptions(duration)) + .moveTo(PointOption.point(width - 10, height / 2)).release().perform(); + } + } + +} diff --git a/src/main/java/luckyclient/execution/appium/iosex/IosBatchExecute.java b/src/main/java/luckyclient/execution/appium/iosex/IosBatchExecute.java index b6f1bb4..f16c2fc 100644 --- a/src/main/java/luckyclient/execution/appium/iosex/IosBatchExecute.java +++ b/src/main/java/luckyclient/execution/appium/iosex/IosBatchExecute.java @@ -1,95 +1,95 @@ -package luckyclient.execution.appium.iosex; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.List; -import java.util.Properties; - -import io.appium.java_client.ios.IOSDriver; -import io.appium.java_client.ios.IOSElement; -import luckyclient.execution.appium.AppiumInitialization; -import luckyclient.execution.appium.AppiumService; -import luckyclient.execution.httpinterface.TestControl; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.remote.entity.TaskExecute; -import luckyclient.utils.LogUtil; -import luckyclient.utils.config.AppiumConfig; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * @author: seagull - * @date 2018年2月2日 - * - */ -public class IosBatchExecute { - - public static void batchCaseExecuteForTast(String projectname, String taskid, String batchcase) throws IOException, InterruptedException { - // 记录日志到数据库 - serverOperation.exetype = 0; - TestControl.TASKID = taskid; - IOSDriver iosd = null; - AppiumService as=null; - try { - Properties properties = AppiumConfig.getConfiguration(); - //根据配置自动启动Appiume服务 - if(Boolean.valueOf(properties.getProperty("autoRunAppiumService"))){ - as =new AppiumService(); - as.start(); - Thread.sleep(10000); - } - - iosd = AppiumInitialization.setIosAppium(properties); - } catch (MalformedURLException e) { - // TODO Auto-generated catch block - LogUtil.APP.error("根据配置自动启动Appiume服务中抛出异常!", e); - } - serverOperation caselog = new serverOperation(); - TaskExecute task = GetServerApi.cgetTaskbyid(Integer.valueOf(taskid)); - List pcplist = GetServerApi - .cgetParamsByProjectid(task.getProjectId().toString()); - // 执行全部非成功状态用例 - if (batchcase.indexOf("ALLFAIL") > -1) { - List caseIdList = caselog.getCaseListForUnSucByTaskId(taskid); - for (int i = 0; i < caseIdList.size(); i++) { - ProjectCase testcase = GetServerApi.cGetCaseByCaseId(caseIdList.get(i)); - List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); - // 删除旧的日志 - serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); - try { - IosCaseExecution.caseExcution(testcase, steps, taskid, iosd, caselog, pcplist); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - LogUtil.APP.error("用户执行过程中抛出异常!", e); - } - } - } else { // 批量执行用例 - String[] temp = batchcase.split("\\#"); - for (int i = 0; i < temp.length; i++) { - ProjectCase testcase = GetServerApi.cGetCaseByCaseId(Integer.valueOf(temp[i])); - List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); - // 删除旧的日志 - serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); - try { - IosCaseExecution.caseExcution(testcase, steps, taskid, iosd, caselog, pcplist); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - LogUtil.APP.error("用户执行过程中抛出异常!", e); - } - } - } - serverOperation.updateTaskExecuteData(taskid, 0,2); - iosd.closeApp(); - //关闭Appium服务的线程 - if(as!=null){ - as.interrupt(); - } - } - -} +package luckyclient.execution.appium.iosex; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.List; +import java.util.Properties; + +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.IOSElement; +import luckyclient.execution.appium.AppiumInitialization; +import luckyclient.execution.appium.AppiumService; +import luckyclient.execution.httpinterface.TestControl; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.remote.entity.TaskExecute; +import luckyclient.utils.LogUtil; +import luckyclient.utils.config.AppiumConfig; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * @author: seagull + * @date 2018年2月2日 + * + */ +public class IosBatchExecute { + + public static void batchCaseExecuteForTast(String taskid, String batchcase) throws IOException, InterruptedException { + // 记录日志到数据库 + serverOperation.exetype = 0; + TestControl.TASKID = taskid; + IOSDriver iosd = null; + AppiumService as=null; + try { + Properties properties = AppiumConfig.getConfiguration(); + //根据配置自动启动Appiume服务 + if(Boolean.parseBoolean(properties.getProperty("autoRunAppiumService"))){ + as =new AppiumService(); + as.start(); + Thread.sleep(10000); + } + + iosd = AppiumInitialization.setIosAppium(properties); + } catch (MalformedURLException e) { + // TODO Auto-generated catch block + LogUtil.APP.error("根据配置自动启动Appiume服务中抛出异常!", e); + } + serverOperation caselog = new serverOperation(); + TaskExecute task = GetServerApi.cgetTaskbyid(Integer.parseInt(taskid)); + List pcplist = GetServerApi + .cgetParamsByProjectid(task.getProjectId().toString()); + // 执行全部非成功状态用例 + if (batchcase.contains("ALLFAIL")) { + List caseIdList = caselog.getCaseListForUnSucByTaskId(taskid); + for (Integer integer : caseIdList) { + ProjectCase testcase = GetServerApi.cGetCaseByCaseId(integer); + List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); + // 删除旧的日志 + serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); + try { + IosCaseExecution.caseExcution(testcase, steps, taskid, iosd, caselog, pcplist); + } catch (Exception e) { + LogUtil.APP.error("用户执行过程中抛出异常!", e); + } + } + } else { // 批量执行用例 + String[] temp = batchcase.split("#"); + for (String s : temp) { + ProjectCase testcase = GetServerApi.cGetCaseByCaseId(Integer.valueOf(s)); + List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); + // 删除旧的日志 + serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); + try { + IosCaseExecution.caseExcution(testcase, steps, taskid, iosd, caselog, pcplist); + } catch (Exception e) { + // TODO Auto-generated catch block + LogUtil.APP.error("用户执行过程中抛出异常!", e); + } + } + } + serverOperation.updateTaskExecuteData(taskid, 0,2); + assert iosd != null; + iosd.closeApp(); + //关闭Appium服务的线程 + if(as!=null){ + as.interrupt(); + } + } + +} diff --git a/src/main/java/luckyclient/execution/appium/iosex/IosCaseExecution.java b/src/main/java/luckyclient/execution/appium/iosex/IosCaseExecution.java index 492d1a4..89d17e9 100644 --- a/src/main/java/luckyclient/execution/appium/iosex/IosCaseExecution.java +++ b/src/main/java/luckyclient/execution/appium/iosex/IosCaseExecution.java @@ -1,334 +1,332 @@ -package luckyclient.execution.appium.iosex; - -import java.io.IOException; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import io.appium.java_client.ios.IOSDriver; -import io.appium.java_client.ios.IOSElement; -import luckyclient.execution.appium.AppDriverAnalyticCase; -import luckyclient.execution.dispose.ActionManageForSteps; -import luckyclient.execution.dispose.ChangString; -import luckyclient.execution.dispose.ParamsManageForSteps; -import luckyclient.execution.httpinterface.TestCaseExecution; -import luckyclient.execution.httpinterface.analyticsteps.InterfaceAnalyticCase; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.Constants; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author seagull - * @date 2018年1月21日 上午15:12:48 - */ -public class IosCaseExecution{ - static Map variable = new HashMap(); - private static String casenote = "备注初始化"; - private static String imagname = ""; - - public static void caseExcution(ProjectCase testcase, List steps,String taskid, IOSDriver appium,serverOperation caselog,List pcplist) - throws InterruptedException, IOException { - caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), 3); - // 把公共参数加入到MAP中 - for (ProjectCaseParams pcp : pcplist) { - variable.put(pcp.getParamsName(), pcp.getParamsValue()); - } - // 加入全局变量 - variable.putAll(ParamsManageForSteps.GLOBAL_VARIABLE); - - // 0:成功 1:失败 2:锁定 其他:锁定 - int setcaseresult = 0; - for (ProjectCaseSteps step : steps) { - Map params; - String result; - - // 根据步骤类型来分析步骤参数 - if (3 == step.getStepType()){ - params = AppDriverAnalyticCase.analyticCaseStep(testcase, step, taskid,caselog,variable); - }else{ - params = InterfaceAnalyticCase.analyticCaseStep(testcase, step, taskid, caselog,variable); - } - - if(null != params.get("exception") && params.get("exception").contains("解析异常")){ - setcaseresult = 2; - break; - } - - // 根据步骤类型来执行步骤 - if (3 == step.getStepType()){ - result = iosRunStep(params, variable, appium, taskid, testcase.getCaseId(), step.getStepSerialNumber(), caselog); - }else{ - TestCaseExecution testCaseExecution=new TestCaseExecution(); - result = testCaseExecution.runStep(params, taskid, testcase.getCaseSign(), step, caselog); - } - - String expectedResults = params.get("ExpectedResults").toString(); - expectedResults=ChangString.changparams(expectedResults, variable,"预期结果"); - - // 判断结果 - int stepresult = judgeResult(testcase, step, params, appium, taskid, expectedResults, result, caselog); - // 失败,并且不在继续,直接终止 - if (0 != stepresult) { - setcaseresult = stepresult; - if (testcase.getFailcontinue() == 0) { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),step.getStepSerialNumber()); - break; - } else { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),step.getStepSerialNumber()); - } - } - - } - - variable.clear(); - caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), setcaseresult); - if(setcaseresult==0){ - LogUtil.APP.info("用例【{}】全部步骤执行结果成功...",testcase.getCaseSign()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例全部步骤执行结果成功","info", "ending",""); - }else{ - LogUtil.APP.warn("用例【{}】步骤执行过程中失败或是锁定...请查看具体原因!{}",testcase.getCaseSign(),casenote); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例执行过程中失败或是锁定"+casenote,"error", "ending",""); - } - //LogOperation.UpdateTastdetail(taskid, 0); - } - - public static String iosRunStep(Map params, Map variable, IOSDriver appium,String taskid,Integer caseId,int stepno,serverOperation caselog) { - String result = ""; - String property; - String propertyValue; - String operation; - String operationValue; - - try { - property = params.get("property"); - propertyValue = params.get("property_value"); - operation = params.get("operation"); - operationValue = params.get("operation_value"); - - // 处理值传递 - property = ChangString.changparams(property, variable,"定位方式"); - propertyValue=ChangString.changparams(propertyValue, variable,"定位路径"); - operation=ChangString.changparams(operation, variable,"操作"); - operationValue=ChangString.changparams(operationValue, variable,"操作参数"); - - LogUtil.APP.info("二次解析用例过程完成,等待进行对象操作......"); - caselog.insertTaskCaseLog(taskid, caseId, "对象操作:"+operation+"; 操作值:"+operationValue,"info", String.valueOf(stepno),""); - } catch (Exception e) { - LogUtil.APP.error("二次解析用例过程抛出异常!",e); - return "步骤执行失败:解析用例失败!"; - } - - try { - //调用接口用例 - if(null != operation&&null != operationValue&&"runcase".equals(operation)){ - String[] temp=operationValue.split(",",-1); - TestCaseExecution testCaseExecution=new TestCaseExecution(); - String ex = testCaseExecution.oneCaseExecuteForUICase(temp[0], taskid, caselog, appium); - if(ex.indexOf("CallCase调用出错!")<=-1&&ex.indexOf("解析出错啦!")<=-1&&ex.indexOf("匹配失败")<=-1){ - return ex; - }else{ - return "步骤执行失败:调用接口用例过程失败"; - } - } - - IOSElement ae = null; - // 页面元素层 - if (null != property && null != propertyValue) { - ae = isElementExist(appium, property, propertyValue); - // 判断此元素是否存在 - if (null==ae) { - LogUtil.APP.warn("定位对象失败,isElementExist为null!"); - return "步骤执行失败:isElementExist定位元素过程失败!"; - } - - if (operation.indexOf("select") > -1) { - result = IosEncapsulateOperation.selectOperation(ae, operation, operationValue); - } else if (operation.indexOf("get") > -1){ - result = IosEncapsulateOperation.getOperation(ae, operation,operationValue); - } else { - result = IosEncapsulateOperation.objectOperation(appium, ae, operation, operationValue, property, propertyValue); - } - // Driver层操作 - } else if (null==property && null != operation) { - // 处理弹出框事件 - if (operation.indexOf("alert") > -1){ - result = IosEncapsulateOperation.alertOperation(appium, operation); - }else{ - result = IosEncapsulateOperation.driverOperation(appium, operation, operationValue); - } - }else{ - LogUtil.APP.warn("元素操作过程失败!"); - result = "步骤执行失败:元素操作过程失败!"; - } - } catch (Exception e) { - LogUtil.APP.error("元素定位过程或是操作过程失败或异常!",e); - return "步骤执行失败:元素定位过程或是操作过程失败或异常!" + e.getMessage(); - } - caselog.insertTaskCaseLog(taskid, caseId, result,"info", String.valueOf(stepno),""); - - if(result.indexOf("获取到的值是【")>-1&&result.indexOf("】")>-1){ - result = result.substring(result.indexOf("获取到的值是【")+7, result.length()-1); - } - return result; - - } - - public static IOSElement isElementExist(IOSDriver appium, String property, String propertyValue) { - try { - IOSElement ae = null; - property=property.toLowerCase(); - // 处理WebElement对象定位 - switch (property) { - case "id": - ae = appium.findElementById(propertyValue); - break; - case "name": - ae = appium.findElementByName(propertyValue); - break; - case "xpath": - ae = appium.findElementByXPath(propertyValue); - break; - case "linktext": - ae = appium.findElementByLinkText(propertyValue); - break; - case "tagname": - ae = appium.findElementByTagName(propertyValue); - break; - case "cssselector": - ae = appium.findElementByCssSelector(propertyValue); - break; - case "classname": - ae = appium.findElementByClassName(propertyValue); - break; - case "accessibilityid": - ae = appium.findElementByAccessibilityId(propertyValue); - break; - case "iosclasschain": - ae = appium.findElementByIosClassChain(propertyValue); - break; - case "iosnspredicate": - ae = appium.findElementByIosNsPredicate(propertyValue); - break; - default: - break; - } - - return ae; - - } catch (Exception e) { - LogUtil.APP.error("当前对象定位失败!",e); - return null; - } - - } - - public static int judgeResult(ProjectCase testcase, ProjectCaseSteps step, Map params, IOSDriver appium, String taskid, String expect, String result, serverOperation caselog) throws InterruptedException { - int setresult = 0; - java.text.DateFormat timeformat = new java.text.SimpleDateFormat("MMdd-hhmmss"); - imagname = timeformat.format(new Date()); - - result = ActionManageForSteps.actionManage(step.getAction(), result); - if (null != result && !result.contains("步骤执行失败:")) { - // 有预期结果 - if (null != expect && !expect.isEmpty()) { - LogUtil.APP.info("期望结果为【{}】",expect); - - // 赋值传参模式 - if (expect.length() > Constants.ASSIGNMENT_SIGN.length() && expect.startsWith(Constants.ASSIGNMENT_SIGN)) { - variable.put(expect.substring(Constants.ASSIGNMENT_SIGN.length()), result); - LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),result,expect.substring(Constants.ASSIGNMENT_SIGN.length())); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + result + "】赋值给变量【" + expect.substring(Constants.ASSIGNMENT_SIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); - } - // 赋值全局变量 - else if (expect.length() > Constants.ASSIGNMENT_GLOBALSIGN.length() && expect.startsWith(Constants.ASSIGNMENT_GLOBALSIGN)) { - variable.put(expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), result); - ParamsManageForSteps.GLOBAL_VARIABLE.put(expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), result); - LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给全局变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),result,expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length())); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + result + "】赋值给全局变量【" + expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); - } - // 移动端 UI检查模式 - else if (3 == step.getStepType() && params.get("checkproperty") != null && params.get("checkproperty_value") != null) { - String checkproperty = params.get("checkproperty"); - String checkPropertyValue = params.get("checkproperty_value"); - - IOSElement ae = isElementExist(appium, checkproperty, checkPropertyValue); - if (null != ae) { - LogUtil.APP.info("用例:{} 第{}步,在当前页面中找到预期结果中对象。当前步骤执行成功!",testcase.getCaseSign(),step.getStepSerialNumber()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在当前页面中找到预期结果中对象。当前步骤执行成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - casenote = "第" + step.getStepSerialNumber() + "步,没有在当前页面中找到预期结果中对象。执行失败!"; - setresult = 1; - IosBaseAppium.screenShot(appium, imagname); - LogUtil.APP.warn("用例:{} 第{}步,没有在当前页面中找到预期结果中对象。当前步骤执行失败!",testcase.getCaseSign(),step.getStepSerialNumber()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在当前页面中没有找到预期结果中对象。当前步骤执行失败!" + "checkproperty【" + checkproperty + "】 checkproperty_value【" + checkPropertyValue + "】", "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - } - // 其它匹配模式 - else { - // 模糊匹配预期结果模式 - if (expect.length() > Constants.FUZZY_MATCHING_SIGN.length() && expect.startsWith(Constants.FUZZY_MATCHING_SIGN)) { - if (result.contains(expect.substring(Constants.FUZZY_MATCHING_SIGN.length()))) { - LogUtil.APP.info("用例:{} 第{}步,模糊匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果成功!执行结果:" + result, "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - casenote = "第" + step.getStepSerialNumber() + "步,模糊匹配预期结果失败!"; - setresult = 1; - IosBaseAppium.screenShot(appium, imagname); - LogUtil.APP.warn("用例:{} 第{}步,模糊匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expect.substring(Constants.FUZZY_MATCHING_SIGN.length()),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果失败!预期结果:" + expect.substring(Constants.FUZZY_MATCHING_SIGN.length()) + ",测试结果:" + result, "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - } - // 正则匹配预期结果模式 - else if (expect.length() > Constants.REGULAR_MATCHING_SIGN.length() && expect.startsWith(Constants.REGULAR_MATCHING_SIGN)) { - Pattern pattern = Pattern.compile(expect.substring(Constants.REGULAR_MATCHING_SIGN.length())); - Matcher matcher = pattern.matcher(result); - if (matcher.find()) { - LogUtil.APP.info("用例:{} 第{}步,正则匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - casenote = "第" + step.getStepSerialNumber() + "步,正则匹配预期结果失败!"; - setresult = 1; - IosBaseAppium.screenShot(appium, imagname); - LogUtil.APP.warn("用例:{} 第{}步,正则匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expect.substring(Constants.REGULAR_MATCHING_SIGN.length()),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果失败!预期结果:" + expect.substring(Constants.REGULAR_MATCHING_SIGN.length()) + ",测试结果:" + result, "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - } - // 精确匹配预期结果模式 - else { - if (expect.equals(result)) { - LogUtil.APP.info("用例:{} 第{}步,精确匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "精确匹配预期结果成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - casenote = "第" + step.getStepSerialNumber() + "步,精确匹配预期结果失败!"; - setresult = 1; - IosBaseAppium.screenShot(appium, imagname); - LogUtil.APP.warn("用例:{} 第{}步,精确匹配预期结果失败!预期结果是:【{}】 执行结果:【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),expect,result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "精确匹配预期结果失败!预期结果是:【"+expect+"】 执行结果:【"+ result+"】", "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - } - } - } - } else { - casenote = (null != result) ? result : ""; - setresult = 2; - IosBaseAppium.screenShot(appium, imagname); - LogUtil.APP.warn("用例:{} 第{}步,执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),casenote); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "当前步骤在执行过程中解析|定位元素|操作对象失败!" + casenote, "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - - return setresult; - } - -} +package luckyclient.execution.appium.iosex; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.IOSElement; +import luckyclient.execution.appium.AppDriverAnalyticCase; +import luckyclient.execution.dispose.ActionManageForSteps; +import luckyclient.execution.dispose.ChangString; +import luckyclient.execution.dispose.ParamsManageForSteps; +import luckyclient.execution.httpinterface.TestCaseExecution; +import luckyclient.execution.httpinterface.analyticsteps.InterfaceAnalyticCase; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.Constants; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author seagull + * @date 2018年1月21日 上午15:12:48 + */ +public class IosCaseExecution{ + static Map variable = new HashMap<>(); + private static String casenote = "备注初始化"; + + public static void caseExcution(ProjectCase testcase, List steps,String taskid, IOSDriver appium,serverOperation caselog,List pcplist) { + caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), 3); + // 把公共参数加入到MAP中 + for (ProjectCaseParams pcp : pcplist) { + variable.put(pcp.getParamsName(), pcp.getParamsValue()); + } + // 加入全局变量 + variable.putAll(ParamsManageForSteps.GLOBAL_VARIABLE); + + // 0:成功 1:失败 2:锁定 其他:锁定 + int setcaseresult = 0; + for (ProjectCaseSteps step : steps) { + Map params; + String result; + + // 根据步骤类型来分析步骤参数 + if (3 == step.getStepType()){ + params = AppDriverAnalyticCase.analyticCaseStep(testcase, step, taskid,caselog,variable); + }else{ + params = InterfaceAnalyticCase.analyticCaseStep(testcase, step, taskid, caselog,variable); + } + + if(null != params.get("exception") && params.get("exception").contains("解析异常")){ + setcaseresult = 2; + break; + } + + // 根据步骤类型来执行步骤 + if (3 == step.getStepType()){ + result = iosRunStep(params, variable, appium, taskid, testcase.getCaseId(), step.getStepSerialNumber(), caselog); + }else{ + TestCaseExecution testCaseExecution=new TestCaseExecution(); + result = testCaseExecution.runStep(params, taskid, testcase.getCaseSign(), step, caselog); + } + + String expectedResults = params.get("ExpectedResults"); + expectedResults=ChangString.changparams(expectedResults, variable,"预期结果"); + + // 判断结果 + int stepresult = judgeResult(testcase, step, params, appium, taskid, expectedResults, result, caselog); + // 失败,并且不在继续,直接终止 + if (0 != stepresult) { + setcaseresult = stepresult; + if (testcase.getFailcontinue() == 0) { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),step.getStepSerialNumber()); + break; + } else { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),step.getStepSerialNumber()); + } + } + + } + + variable.clear(); + caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), setcaseresult); + if(setcaseresult==0){ + LogUtil.APP.info("用例【{}】全部步骤执行结果成功...",testcase.getCaseSign()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例全部步骤执行结果成功","info", "ending",""); + }else{ + LogUtil.APP.warn("用例【{}】步骤执行过程中失败或是锁定...请查看具体原因!{}",testcase.getCaseSign(),casenote); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例执行过程中失败或是锁定"+casenote,"error", "ending",""); + } + //LogOperation.UpdateTastdetail(taskid, 0); + } + + public static String iosRunStep(Map params, Map variable, IOSDriver appium,String taskid,Integer caseId,int stepno,serverOperation caselog) { + String result; + String property; + String propertyValue; + String operation; + String operationValue; + + try { + property = params.get("property"); + propertyValue = params.get("property_value"); + operation = params.get("operation"); + operationValue = params.get("operation_value"); + + // 处理值传递 + property = ChangString.changparams(property, variable,"定位方式"); + propertyValue=ChangString.changparams(propertyValue, variable,"定位路径"); + operation=ChangString.changparams(operation, variable,"操作"); + operationValue=ChangString.changparams(operationValue, variable,"操作参数"); + + LogUtil.APP.info("二次解析用例过程完成,等待进行对象操作......"); + caselog.insertTaskCaseLog(taskid, caseId, "对象操作:"+operation+"; 操作值:"+operationValue,"info", String.valueOf(stepno),""); + } catch (Exception e) { + LogUtil.APP.error("二次解析用例过程抛出异常!",e); + return "步骤执行失败:解析用例失败!"; + } + + try { + //调用接口用例 + if(null != operationValue && "runcase".equals(operation)){ + String[] temp=operationValue.split(",",-1); + TestCaseExecution testCaseExecution=new TestCaseExecution(); + String ex = testCaseExecution.oneCaseExecuteForUICase(temp[0], taskid, caselog, appium); + if(!ex.contains("CallCase调用出错!") && !ex.contains("解析出错啦!") && !ex.contains("匹配失败")){ + return ex; + }else{ + return "步骤执行失败:调用接口用例过程失败"; + } + } + + IOSElement ae; + // 页面元素层 + if (null != property && null != propertyValue) { + ae = isElementExist(appium, property, propertyValue); + // 判断此元素是否存在 + if (null==ae) { + LogUtil.APP.warn("定位对象失败,isElementExist为null!"); + return "步骤执行失败:isElementExist定位元素过程失败!"; + } + + assert operation != null; + if (operation.contains("select")) { + result = IosEncapsulateOperation.selectOperation(ae, operation, operationValue); + } else if (operation.contains("get")){ + result = IosEncapsulateOperation.getOperation(ae, operation,operationValue); + } else { + result = IosEncapsulateOperation.objectOperation(appium, ae, operation, operationValue, property, propertyValue); + } + // Driver层操作 + } else if (null==property && null != operation) { + // 处理弹出框事件 + if (operation.contains("alert")){ + result = IosEncapsulateOperation.alertOperation(appium, operation); + }else{ + result = IosEncapsulateOperation.driverOperation(appium, operation, operationValue); + } + }else{ + LogUtil.APP.warn("元素操作过程失败!"); + result = "步骤执行失败:元素操作过程失败!"; + } + } catch (Exception e) { + LogUtil.APP.error("元素定位过程或是操作过程失败或异常!",e); + return "步骤执行失败:元素定位过程或是操作过程失败或异常!" + e.getMessage(); + } + caselog.insertTaskCaseLog(taskid, caseId, result,"info", String.valueOf(stepno),""); + + if(result.contains("获取到的值是【") && result.contains("】")){ + result = result.substring(result.indexOf("获取到的值是【")+7, result.length()-1); + } + return result; + + } + + public static IOSElement isElementExist(IOSDriver appium, String property, String propertyValue) { + try { + IOSElement ae = null; + property=property.toLowerCase(); + // 处理WebElement对象定位 + switch (property) { + case "id": + ae = appium.findElementById(propertyValue); + break; + case "name": + ae = appium.findElementByName(propertyValue); + break; + case "xpath": + ae = appium.findElementByXPath(propertyValue); + break; + case "linktext": + ae = appium.findElementByLinkText(propertyValue); + break; + case "tagname": + ae = appium.findElementByTagName(propertyValue); + break; + case "cssselector": + ae = appium.findElementByCssSelector(propertyValue); + break; + case "classname": + ae = appium.findElementByClassName(propertyValue); + break; + case "accessibilityid": + ae = appium.findElementByAccessibilityId(propertyValue); + break; + case "iosclasschain": + ae = appium.findElementByIosClassChain(propertyValue); + break; + case "iosnspredicate": + ae = appium.findElementByIosNsPredicate(propertyValue); + break; + default: + break; + } + + return ae; + + } catch (Exception e) { + LogUtil.APP.error("当前对象定位失败!",e); + return null; + } + + } + + public static int judgeResult(ProjectCase testcase, ProjectCaseSteps step, Map params, IOSDriver appium, String taskid, String expect, String result, serverOperation caselog) { + int setresult = 0; + java.text.DateFormat timeformat = new java.text.SimpleDateFormat("MMdd-hhmmss"); + String imagname = timeformat.format(new Date()); + + result = ActionManageForSteps.actionManage(step.getAction(), result); + if (null != result && !result.contains("步骤执行失败:")) { + // 有预期结果 + if (null != expect && !expect.isEmpty()) { + LogUtil.APP.info("期望结果为【{}】",expect); + + // 赋值传参模式 + if (expect.length() > Constants.ASSIGNMENT_SIGN.length() && expect.startsWith(Constants.ASSIGNMENT_SIGN)) { + variable.put(expect.substring(Constants.ASSIGNMENT_SIGN.length()), result); + LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),result,expect.substring(Constants.ASSIGNMENT_SIGN.length())); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + result + "】赋值给变量【" + expect.substring(Constants.ASSIGNMENT_SIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); + } + // 赋值全局变量 + else if (expect.length() > Constants.ASSIGNMENT_GLOBALSIGN.length() && expect.startsWith(Constants.ASSIGNMENT_GLOBALSIGN)) { + variable.put(expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), result); + ParamsManageForSteps.GLOBAL_VARIABLE.put(expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), result); + LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给全局变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),result,expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length())); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + result + "】赋值给全局变量【" + expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); + } + // 移动端 UI检查模式 + else if (3 == step.getStepType() && params.get("checkproperty") != null && params.get("checkproperty_value") != null) { + String checkproperty = params.get("checkproperty"); + String checkPropertyValue = params.get("checkproperty_value"); + + IOSElement ae = isElementExist(appium, checkproperty, checkPropertyValue); + if (null != ae) { + LogUtil.APP.info("用例:{} 第{}步,在当前页面中找到预期结果中对象。当前步骤执行成功!",testcase.getCaseSign(),step.getStepSerialNumber()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在当前页面中找到预期结果中对象。当前步骤执行成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + casenote = "第" + step.getStepSerialNumber() + "步,没有在当前页面中找到预期结果中对象。执行失败!"; + setresult = 1; + IosBaseAppium.screenShot(appium, imagname); + LogUtil.APP.warn("用例:{} 第{}步,没有在当前页面中找到预期结果中对象。当前步骤执行失败!",testcase.getCaseSign(),step.getStepSerialNumber()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在当前页面中没有找到预期结果中对象。当前步骤执行失败!" + "checkproperty【" + checkproperty + "】 checkproperty_value【" + checkPropertyValue + "】", "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + } + // 其它匹配模式 + else { + // 模糊匹配预期结果模式 + if (expect.length() > Constants.FUZZY_MATCHING_SIGN.length() && expect.startsWith(Constants.FUZZY_MATCHING_SIGN)) { + if (result.contains(expect.substring(Constants.FUZZY_MATCHING_SIGN.length()))) { + LogUtil.APP.info("用例:{} 第{}步,模糊匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果成功!执行结果:" + result, "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + casenote = "第" + step.getStepSerialNumber() + "步,模糊匹配预期结果失败!"; + setresult = 1; + IosBaseAppium.screenShot(appium, imagname); + LogUtil.APP.warn("用例:{} 第{}步,模糊匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expect.substring(Constants.FUZZY_MATCHING_SIGN.length()),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果失败!预期结果:" + expect.substring(Constants.FUZZY_MATCHING_SIGN.length()) + ",测试结果:" + result, "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + } + // 正则匹配预期结果模式 + else if (expect.length() > Constants.REGULAR_MATCHING_SIGN.length() && expect.startsWith(Constants.REGULAR_MATCHING_SIGN)) { + Pattern pattern = Pattern.compile(expect.substring(Constants.REGULAR_MATCHING_SIGN.length())); + Matcher matcher = pattern.matcher(result); + if (matcher.find()) { + LogUtil.APP.info("用例:{} 第{}步,正则匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + casenote = "第" + step.getStepSerialNumber() + "步,正则匹配预期结果失败!"; + setresult = 1; + IosBaseAppium.screenShot(appium, imagname); + LogUtil.APP.warn("用例:{} 第{}步,正则匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expect.substring(Constants.REGULAR_MATCHING_SIGN.length()),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果失败!预期结果:" + expect.substring(Constants.REGULAR_MATCHING_SIGN.length()) + ",测试结果:" + result, "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + } + // 精确匹配预期结果模式 + else { + if (expect.equals(result)) { + LogUtil.APP.info("用例:{} 第{}步,精确匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "精确匹配预期结果成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + casenote = "第" + step.getStepSerialNumber() + "步,精确匹配预期结果失败!"; + setresult = 1; + IosBaseAppium.screenShot(appium, imagname); + LogUtil.APP.warn("用例:{} 第{}步,精确匹配预期结果失败!预期结果是:【{}】 执行结果:【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),expect,result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "精确匹配预期结果失败!预期结果是:【"+expect+"】 执行结果:【"+ result+"】", "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + } + } + } + } else { + casenote = (null != result) ? result : ""; + setresult = 2; + IosBaseAppium.screenShot(appium, imagname); + LogUtil.APP.warn("用例:{} 第{}步,执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),casenote); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "当前步骤在执行过程中解析|定位元素|操作对象失败!" + casenote, "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + + return setresult; + } + +} diff --git a/src/main/java/luckyclient/execution/appium/iosex/IosCaseLocalDebug.java b/src/main/java/luckyclient/execution/appium/iosex/IosCaseLocalDebug.java index 829a596..7ae77ad 100644 --- a/src/main/java/luckyclient/execution/appium/iosex/IosCaseLocalDebug.java +++ b/src/main/java/luckyclient/execution/appium/iosex/IosCaseLocalDebug.java @@ -1,73 +1,68 @@ -package luckyclient.execution.appium.iosex; - -import java.io.IOException; -import java.util.List; - -import io.appium.java_client.ios.IOSDriver; -import io.appium.java_client.ios.IOSElement; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author seagull - * @date 2018年1月29日 - * - */ -public class IosCaseLocalDebug { - - public static void oneCasedebug(IOSDriver iosdriver, String testCaseExternalId) { - // 不记录日志到数据库 - serverOperation.exetype = 1; - serverOperation caselog = new serverOperation(); - - try { - ProjectCase testcase = GetServerApi.cgetCaseBysign(testCaseExternalId); - List pcplist = GetServerApi - .cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); - LogUtil.APP.info("开始执行用例:【{}】......",testCaseExternalId); - List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); - IosCaseExecution.caseExcution(testcase, steps, "888888", iosdriver, caselog, pcplist); - - LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); - } catch (Exception e) { - LogUtil.APP.error("用户执行过程中抛出异常!", e); - } - } - - /** - * @param 项目名 - * @param 用例编号 - * @param 用例版本号 - * 用于在testlink上配置好用例参数后,做多条用例串行调试 - */ - public static void moreCaseDebug(IOSDriver iosdriver, String projectname, - List addtestcase) { - System.out.println("当前调试用例总共:"+addtestcase.size()); - for(String testCaseExternalId:addtestcase) { - try { - LogUtil.APP - .info("开始调用方法,项目名:{},用例编号:{}",projectname,testCaseExternalId); - oneCasedebug(iosdriver, testCaseExternalId); - } catch (Exception e) { - LogUtil.APP.error("多用例调试过程中抛出异常!", e); - continue; - } - } - // 关闭APP以及appium会话 - iosdriver.closeApp(); - } - - public static void main(String[] args) throws IOException { - // TODO Auto-generated method stub - } - -} +package luckyclient.execution.appium.iosex; + +import java.io.IOException; +import java.util.List; + +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.IOSElement; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author seagull + * @date 2018年1月29日 + * + */ +public class IosCaseLocalDebug { + + public static void oneCasedebug(IOSDriver iosdriver, String testCaseExternalId) { + // 不记录日志到数据库 + serverOperation.exetype = 1; + serverOperation caselog = new serverOperation(); + + try { + ProjectCase testcase = GetServerApi.cgetCaseBysign(testCaseExternalId); + List pcplist = GetServerApi + .cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); + LogUtil.APP.info("开始执行用例:【{}】......",testCaseExternalId); + List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); + IosCaseExecution.caseExcution(testcase, steps, "888888", iosdriver, caselog, pcplist); + + LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); + } catch (Exception e) { + LogUtil.APP.error("用户执行过程中抛出异常!", e); + } + } + + /** + * 用于做多条用例串行调试 + * @param iosdriver IOS驱动 + * @param projectname 项目名称 + * @param addtestcase 用例编号 + */ + public static void moreCaseDebug(IOSDriver iosdriver, String projectname, + List addtestcase) { + System.out.println("当前调试用例总共:"+addtestcase.size()); + for(String testCaseExternalId:addtestcase) { + try { + LogUtil.APP + .info("开始调用方法,项目名:{},用例编号:{}",projectname,testCaseExternalId); + oneCasedebug(iosdriver, testCaseExternalId); + } catch (Exception e) { + LogUtil.APP.error("多用例调试过程中抛出异常!", e); + } + } + // 关闭APP以及appium会话 + iosdriver.closeApp(); + } + +} diff --git a/src/main/java/luckyclient/execution/appium/iosex/IosEncapsulateOperation.java b/src/main/java/luckyclient/execution/appium/iosex/IosEncapsulateOperation.java index f4a03c4..1ad4005 100644 --- a/src/main/java/luckyclient/execution/appium/iosex/IosEncapsulateOperation.java +++ b/src/main/java/luckyclient/execution/appium/iosex/IosEncapsulateOperation.java @@ -1,539 +1,536 @@ -package luckyclient.execution.appium.iosex; - -import java.time.Duration; -import java.util.Date; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import org.openqa.selenium.Alert; -import org.openqa.selenium.JavascriptExecutor; -import org.openqa.selenium.support.ui.Select; - -import io.appium.java_client.ios.IOSDriver; -import io.appium.java_client.ios.IOSElement; -import io.appium.java_client.ios.IOSTouchAction; -import io.appium.java_client.touch.LongPressOptions; -import io.appium.java_client.touch.WaitOptions; -import io.appium.java_client.touch.offset.ElementOption; -import io.appium.java_client.touch.offset.PointOption; -import luckyclient.execution.dispose.ChangString; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author Seagull - * @date 2018年2月2日 - * - */ -public class IosEncapsulateOperation { - public static String selectOperation(IOSElement ie, String operation, String operationValue) throws Exception { - String result = ""; - // 下拉框对象处理 - Select select = new Select(ie); - - // 处理下拉框事件 - switch (operation) { - case "selectbyvisibletext": - select.selectByVisibleText(operationValue); - LogUtil.APP - .info("下拉框对象通过VisibleText属性选择...【VisibleText属性值:{}】",operationValue); - break; - case "selectbyvalue": - select.selectByValue(operationValue); - LogUtil.APP.info("下拉框对象通过Value属性选择...【Value属性值:{}】",operationValue); - break; - case "selectbyindex": - select.selectByIndex(Integer.valueOf(operationValue)); - LogUtil.APP.info("下拉框对象通过Index属性选择...【Index属性值:{}】",operationValue); - break; - case "isselect": - result = "获取到的值是【" + ie.isSelected() + "】"; - LogUtil.APP.info("判断对象是否已经被选择...【结果值:{}】",ie.isSelected()); - break; - default: - break; - } - return result; - } - - public static String getOperation(IOSElement ie, String operation, String value) throws Exception { - String result = ""; - // 获取对象处理 - switch (operation) { - case "gettext": - result = "获取到的值是【" + ie.getText() + "】"; - LogUtil.APP.info("getText获取对象text属性...【text属性值:{}】",result); - break; // 获取输入框内容 - case "gettagname": - result = "获取到的值是【" + ie.getTagName() + "】"; - LogUtil.APP.info("getTagName获取对象tagname属性...【tagname属性值:{}】",result); - break; - case "getattribute": - result = "获取到的值是【" + ie.getAttribute(value) + "】"; - LogUtil.APP - .info("getAttribute获取对象【{}】属性...【{}属性值:{}】",value,value,result); - break; - case "getcssvalue": - result = "获取到的值是【" + ie.getCssValue(value) + "】"; - LogUtil.APP - .info("getCssValue获取对象【{}】属性...【{}属性值:{}】",value,value,result); - break; - default: - break; - } - return result; - } - - public static String objectOperation(IOSDriver appium, IOSElement ie, String operation, - String operationValue, String property, String propertyValue) throws Exception { - String result = ""; - IOSTouchAction action = new IOSTouchAction(appium); - // 处理WebElement对象操作 - switch (operation) { - case "click": - ie.click(); - result = "click点击对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; - LogUtil.APP - .info("click点击对象...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); - break; - case "sendkeys": - ie.sendKeys(operationValue); - result = "sendKeys对象输入...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "; 操作值:" + operationValue - + "】"; - LogUtil.APP.info("sendkeys对象输入...【对象定位属性:{}; 定位属性值:{}; 操作值:{}】",property,propertyValue,operationValue); - break; - case "clear": - ie.clear(); - result = "clear清空输入框...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; - LogUtil.APP - .info("clear清空输入框...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); - break; // 清空输入框 - case "isenabled": - result = "获取到的值是【" + ie.isEnabled() + "】"; - LogUtil.APP.info("当前对象判断是否可用布尔值为【{}】",ie.isEnabled()); - break; - case "isdisplayed": - result = "获取到的值是【" + ie.isDisplayed() + "】"; - LogUtil.APP.info("当前对象判断是否可见布尔值为【{}】",ie.isDisplayed()); - break; - case "exjsob": - JavascriptExecutor jse = (JavascriptExecutor) appium; - jse.executeScript(operationValue, ie); - result = "执行JS...【" + operationValue + "】"; - LogUtil.APP.info("执行JS...【{}】",operationValue); - break; - case "longpresselement": - LongPressOptions lpoptions = new LongPressOptions(); - lpoptions.withElement(ElementOption.element(ie)); - if (null != operationValue && ChangString.isNumeric(operationValue)) { - int nanos = Integer.valueOf(operationValue) * 1000; - Duration duration = Duration.ofNanos(nanos); - lpoptions.withDuration(duration); - } - action.longPress(lpoptions).release().perform(); - result = "longpresselement在屏幕指定元素上按住" + operationValue + "秒...【对象定位属性:" + property + "; 定位属性值:" - + propertyValue + "】"; - LogUtil.APP.info("longpresselement在屏幕指定元素上按住{}秒...【对象定位属性:{}; 定位属性值:{}】",operationValue,property,propertyValue); - break; - default: - break; - } - return result; - } - - public static String alertOperation(IOSDriver appium, String operation) throws Exception { - String result = ""; - Alert alert = appium.switchTo().alert(); - switch (operation) { - case "alertaccept": - alert.accept(); - LogUtil.APP.info("弹出框对象点击同意..."); - break; - case "alertdismiss": - alert.dismiss(); - LogUtil.APP.info("弹出框对象点击取消..."); - break; - case "alertgettext": - result = "获取到的值是【" + alert.getText() + "】"; - LogUtil.APP.info("弹出框对象通过getText获取对象text属性...【Text属性值:{}】",alert.getText()); - break; - default: - break; - } - return result; - } - - public static String driverOperation(IOSDriver appium, String operation, String operationValue) - throws Exception { - String result = ""; - IOSTouchAction action = new IOSTouchAction(appium); - // 处理页面对象操作 - switch (operation) { - case "getcontexthandles": - Set handles = appium.getContextHandles(); - int handlenum = 1; - for (String handle : handles) { - if (String.valueOf(handlenum).equals(operationValue)) { - if (appium.getContext().equals(handle)) { - result = "请注意,你指定的ContextHandle就是当前页面哦,获取到的值是【" + handle + "】"; - } else { - result = "指定ContextHandler的顺序值是" + operationValue + ",获取到的值是【" + handle + "】"; - } - break; - } - handlenum++; - } - LogUtil.APP.info("getContext获取窗口句柄...{}",result); - break; - case "exjs": - JavascriptExecutor jse = (JavascriptExecutor) appium; - jse.executeScript(operationValue); - result = "执行JS...【" + operationValue + "】"; - LogUtil.APP.info("执行JS...【{}】",operationValue); - break; - // 隐藏手机键盘 - case "hideKeyboard": - appium.hideKeyboard(); - result = "隐藏手机键盘...【hideKeyboard】"; - LogUtil.APP.info("隐藏手机键盘...【hideKeyboard】"); - break; - case "gotocontext": - Set ctNames = appium.getContextHandles(); - int flag = 0; - for (String contextName : ctNames) { - if (contextName.contains(operationValue)) { - flag = 1; - appium.context(contextName); - break; - } - } - if (flag == 1) { - result = "切换context至【" + operationValue + "】"; - LogUtil.APP.info("切换context至【{}】",operationValue); - } else { - result = "切换context失败,未找到contextName值为【" + operationValue + "】的对象"; - LogUtil.APP.info("切换context失败,未找到contextName值为【{}】的对象",operationValue); - } - break; - case "getcontext": - result = "获取到的值是【" + appium.getContext() + "】"; - LogUtil.APP.info("获取页面Context...【{}】",appium.getContext()); - break; - case "gettitle": - result = "获取到的值是【" + appium.getTitle() + "】"; - LogUtil.APP.info("获取页面gettitle...【{}】",appium.getTitle()); - break; - case "swipeup": - String[] tempup = operationValue.split("\\|", -1); - if (null != tempup[0] && ChangString.isNumeric(tempup[0])) { - Double second = Double.valueOf(tempup[0]); - if (null != tempup[1] && ChangString.isNumeric(tempup[1])) { - int num = Integer.valueOf(tempup[1]); - IosBaseAppium.swipePageDown(appium, second, num); - result = "swipeup手指向上滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipeup手指向上滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipeup手指向上滑动参数判断次数出现异常【" + tempup[1] + "】"; - LogUtil.APP.info("swipeup手指向上滑动参数判断次数出现异常【{}】",tempup[1]); - } - } else { - result = "swipeup手指向上滑动参数判断时间出现异常【" + tempup[0] + "】"; - LogUtil.APP.info("swipeup手指向上滑动参数判断时间出现异常【{}】",tempup[0]); - } - break; - case "swipedown": - String[] tempdown = operationValue.split("\\|", -1); - if (null != tempdown[0] && ChangString.isNumeric(tempdown[0])) { - Double second = Double.valueOf(tempdown[0]); - if (null != tempdown[1] && ChangString.isNumeric(tempdown[1])) { - int num = Integer.valueOf(tempdown[1]); - IosBaseAppium.swipePageUp(appium, second, num); - result = "swipedown手指向下滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipedown手指向下滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipedown手指向下滑动参数判断次数出现异常【" + tempdown[1] + "】"; - LogUtil.APP.info("swipedown手指向下滑动参数判断次数出现异常【{}】",tempdown[1]); - } - } else { - result = "swipedown手指向下滑动参数判断时间出现异常【" + tempdown[0] + "】"; - LogUtil.APP.info("swipedown手指向下滑动参数判断时间出现异常【{}】",tempdown[0]); - } - break; - case "swipeleft": - String[] templeft = operationValue.split("\\|", -1); - if (null != templeft[0] && ChangString.isNumeric(templeft[0])) { - Double second = Double.valueOf(templeft[0]); - if (null != templeft[1] && ChangString.isNumeric(templeft[1])) { - int num = Integer.valueOf(templeft[1]); - IosBaseAppium.swipePageRight(appium, second, num); - result = "swipleft手指向左滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipleft手指向左滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipleft手指向左滑动参数判断次数出现异常【" + templeft[1] + "】"; - LogUtil.APP.info("swipleft手指向左滑动参数判断次数出现异常【{}】",templeft[1]); - } - } else { - result = "swipleft手指向左滑动参数判断时间出现异常【" + templeft[0] + "】"; - LogUtil.APP.info("swipleft手指向左滑动参数判断时间出现异常【{}】",templeft[0]); - } - break; - case "swiperight": - String[] tempright = operationValue.split("\\|", -1); - if (null != tempright[0] && ChangString.isNumeric(tempright[0])) { - Double second = Double.valueOf(tempright[0]); - if (null != tempright[1] && ChangString.isNumeric(tempright[1])) { - int num = Integer.valueOf(tempright[1]); - IosBaseAppium.swipePageLeft(appium, second, num); - result = "swipright手指向右滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipright手指向右滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipright手指向右滑动参数判断次数出现异常【" + tempright[1] + "】"; - LogUtil.APP.info("swipright手指向右滑动参数判断次数出现异常【{}】",tempright[1]); - } - } else { - result = "swipright手指向右滑动参数判断时间出现异常【" + tempright[0] + "】"; - LogUtil.APP.info("swipright手指向右滑动参数判断时间出现异常【{}】",tempright[0]); - } - break; - case "swipepageup": - String[] tempPageUp = operationValue.split("\\|", -1); - if (null != tempPageUp[0] && ChangString.isNumeric(tempPageUp[0])) { - Double second = Double.valueOf(tempPageUp[0]); - if (null != tempPageUp[1] && ChangString.isNumeric(tempPageUp[1])) { - int num = Integer.valueOf(tempPageUp[1]); - IosBaseAppium.swipePageUp(appium, second, num); - result = "swipeup页面向上滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipeup页面向上滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipeup页面向上滑动参数判断次数出现异常【" + tempPageUp[1] + "】"; - LogUtil.APP.info("swipeup页面向上滑动参数判断次数出现异常【{}】",tempPageUp[1]); - } - } else { - result = "swipeup页面向上滑动参数判断时间出现异常【" + tempPageUp[0] + "】"; - LogUtil.APP.info("swipeup页面向上滑动参数判断时间出现异常【{}】",tempPageUp[0]); - } - break; - case "swipepagedown": - String[] tempPageDown = operationValue.split("\\|", -1); - if (null != tempPageDown[0] && ChangString.isNumeric(tempPageDown[0])) { - Double second = Double.valueOf(tempPageDown[0]); - if (null != tempPageDown[1] && ChangString.isNumeric(tempPageDown[1])) { - int num = Integer.valueOf(tempPageDown[1]); - IosBaseAppium.swipePageDown(appium, second, num); - result = "swipedown页面向下滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipedown页面向下滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipedown页面向下滑动参数判断次数出现异常【" + tempPageDown[1] + "】"; - LogUtil.APP.info("swipedown页面向下滑动参数判断次数出现异常【{}】",tempPageDown[1]); - } - } else { - result = "swipedown页面向下滑动参数判断时间出现异常【" + tempPageDown[0] + "】"; - LogUtil.APP.info("swipedown页面向下滑动参数判断时间出现异常【{}】",tempPageDown[0]); - } - break; - case "swipepageleft": - String[] tempPageLeft = operationValue.split("\\|", -1); - if (null != tempPageLeft[0] && ChangString.isNumeric(tempPageLeft[0])) { - Double second = Double.valueOf(tempPageLeft[0]); - if (null != tempPageLeft[1] && ChangString.isNumeric(tempPageLeft[1])) { - int num = Integer.valueOf(tempPageLeft[1]); - IosBaseAppium.swipePageLeft(appium, second, num); - result = "swipleft页面向左滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipleft页面向左滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipleft页面向左滑动参数判断次数出现异常【" + tempPageLeft[1] + "】"; - LogUtil.APP.info("swipleft页面向左滑动参数判断次数出现异常【{}】",tempPageLeft[1]); - } - } else { - result = "swipleft页面向左滑动参数判断时间出现异常【" + tempPageLeft[0] + "】"; - LogUtil.APP.info("swipleft页面向左滑动参数判断时间出现异常【{}】",tempPageLeft[0]); - } - break; - case "swipepageright": - String[] tempPageRight = operationValue.split("\\|", -1); - if (null != tempPageRight[0] && ChangString.isNumeric(tempPageRight[0])) { - Double second = Double.valueOf(tempPageRight[0]); - if (null != tempPageRight[1] && ChangString.isNumeric(tempPageRight[1])) { - int num = Integer.valueOf(tempPageRight[1]); - IosBaseAppium.swipePageRight(appium, second, num); - result = "swipright页面向右滑动参数...秒|次数【" + second + "|" + num + "】"; - LogUtil.APP.info("swipright页面向右滑动参数...秒|次数【{}|{}】",second,num); - } else { - result = "swipright页面向右滑动参数判断次数出现异常【" + tempPageRight[1] + "】"; - LogUtil.APP.info("swipright页面向右滑动参数判断次数出现异常【{}】",tempPageRight[1]); - } - } else { - result = "swipright页面向右滑动参数判断时间出现异常【" + tempPageRight[0] + "】"; - LogUtil.APP.info("swipright页面向右滑动参数判断时间出现异常【{}】",tempPageRight[0]); - } - break; - case "longpressxy": - String[] longpressxy = operationValue.split("\\|", -1); - if (null != longpressxy[0] && ChangString.isNumeric(longpressxy[0])) { - int longpressx = Integer.valueOf(longpressxy[0]); - if (null != longpressxy[1] && ChangString.isNumeric(longpressxy[1])) { - int longpressy = Integer.valueOf(longpressxy[1]); - if (null != longpressxy[2] && ChangString.isNumeric(longpressxy[2])) { - LongPressOptions lpoptions = new LongPressOptions(); - lpoptions.withPosition(PointOption.point(longpressx, longpressy)); - int nanos = Integer.valueOf(longpressxy[2]) * 1000; - Duration duration = Duration.ofNanos(nanos); - lpoptions.withDuration(duration); - action.longPress(lpoptions).release().perform(); - result = "longpressxy在屏幕指定XY坐标上按住" + longpressxy[2] + "秒...X|Y【" + longpressx + "|" + longpressy - + "】"; - LogUtil.APP.info("longpressxy在屏幕指定XY坐标上按住{}秒...X|Y【{}|{}】",longpressxy[2],longpressx,longpressy); - } else { - action.longPress(PointOption.point(longpressx, longpressy)).release().perform(); - result = "longpressxy在屏幕指定XY坐标上长按...X|Y【" + longpressx + "|" + longpressy + "】"; - LogUtil.APP.info("longpressxy在屏幕指定XY坐标上长按...X|Y【{}|{}】",longpressx,longpressy); - } - } else { - result = "longpressxy参数指定的Y坐标处理出现异常【" + longpressxy[1] + "】"; - LogUtil.APP.info("longpressxy参数指定的Y坐标处理出现异常【{}】",longpressxy[1]); - } - } else { - result = "longpressxy参数指定的X坐标处理出现异常【" + longpressxy[0] + "】"; - LogUtil.APP.info("longpressxy参数指定的X坐标处理出现异常【{}】",longpressxy[0]); - } - break; - case "pressxy": - String[] pressxy = operationValue.split("\\|", -1); - if (null != pressxy[0] && ChangString.isNumeric(pressxy[0])) { - int pressx = Integer.valueOf(pressxy[0]); - if (null != pressxy[1] && ChangString.isNumeric(pressxy[1])) { - int pressy = Integer.valueOf(pressxy[1]); - action.press(PointOption.point(pressx, pressy)).release().perform(); - result = "pressxy在屏幕指定XY坐标上点击...X|Y【" + pressx + "|" + pressy + "】"; - LogUtil.APP.info("pressxy在屏幕指定XY坐标上点击...X|Y【{}|{}】",pressx,pressy); - } else { - result = "pressxy参数指定的Y坐标处理出现异常【" + pressxy[1] + "】"; - LogUtil.APP.info("pressxy参数指定的Y坐标处理出现异常【{}】",pressxy[1]); - } - } else { - result = "pressxy参数指定的X坐标处理出现异常【" + pressxy[0] + "】"; - LogUtil.APP.info("pressxy参数指定的X坐标处理出现异常【{}】",pressxy[0]); - } - break; - case "tapxy": - String[] tapxy = operationValue.split("\\|", -1); - if (null != tapxy[0] && ChangString.isNumeric(tapxy[0])) { - int tapx = Integer.valueOf(tapxy[0]); - if (null != tapxy[1] && ChangString.isNumeric(tapxy[1])) { - int tapy = Integer.valueOf(tapxy[1]); - action.tap(PointOption.point(tapx, tapy)).release().perform(); - result = "tapxy在屏幕指定XY坐标上轻击...X|Y【" + tapx + "|" + tapy + "】"; - LogUtil.APP.info("tapxy在屏幕指定XY坐标上轻击...X|Y【{}|{}】",tapx,tapy); - } else { - result = "tapxy参数指定的Y坐标处理出现异常【" + tapxy[1] + "】"; - LogUtil.APP.info("tapxy参数指定的Y坐标处理出现异常【{}】",tapxy[1]); - } - } else { - result = "tapxy参数指定的X坐标处理出现异常【" + tapxy[0] + "】"; - LogUtil.APP.info("tapxy参数指定的X坐标处理出现异常【{}】",tapxy[0]); - } - break; - case "jspressxy": - String[] jspressxy = operationValue.split("\\|", -1); - if (null != jspressxy[0] && ChangString.isNumeric(jspressxy[0])) { - int jspressx = Integer.valueOf(jspressxy[0]); - if (null != jspressxy[1] && ChangString.isNumeric(jspressxy[1])) { - int jspressy = Integer.valueOf(jspressxy[1]); - if (null != jspressxy[2] && ChangString.isNumeric(jspressxy[2])) { - IosBaseAppium.clickScreenForJs(appium, jspressx, jspressy, Integer.valueOf(jspressxy[2])); - result = "jspressxy在屏幕指定XY坐标上按" + jspressxy[2] + "秒...X|Y【" + jspressx + "|" + jspressy + "】"; - LogUtil.APP.info("jspressxy在屏幕指定XY坐标上按{}秒...X|Y【{}|{}】",jspressxy[2],jspressx,jspressy); - } else { - IosBaseAppium.clickScreenForJs(appium, jspressx, jspressy, 2); - result = "jspressxy在屏幕指定XY坐标上按2秒(持续时间判断异常,使用默认2秒时间)...X|Y【" + jspressx + "|" + jspressy + "】"; - LogUtil.APP.info("jspressxy在屏幕指定XY坐标上按2秒(持续时间判断异常,使用默认2秒时间)...X|Y【{}|{}】",jspressx,jspressy); - } - } else { - result = "jspressxy参数指定的Y坐标处理出现异常【" + jspressxy[1] + "】"; - LogUtil.APP.info("jspressxy参数指定的Y坐标处理出现异常【{}】",jspressxy[1]); - } - } else { - result = "jspressxy参数指定的X坐标处理出现异常【" + jspressxy[0] + "】"; - LogUtil.APP.info("jspressxy参数指定的X坐标处理出现异常【{}】",jspressxy[0]); - } - break; - case "moveto": - String[] movexy = operationValue.split("\\|", -1); - if (null != movexy[0] && !"".equals(movexy[0])) { - String[] startxy = movexy[0].split(",", -1); - int startx = Integer.valueOf(startxy[0]); - int starty = Integer.valueOf(startxy[1]); - for (int movexyi = 1; movexyi < movexy.length; movexyi++) { - if (null != movexy[movexyi] && !"".equals(movexy[movexyi])) { - String[] endxy = movexy[movexyi].split(",", -1); - int endx = Integer.valueOf(endxy[0]); - int endy = Integer.valueOf(endxy[1]); - // 不确定是否是API的bug,只有一次MOVE时,是XY坐标,当大于一次MOVE时,坐标是偏移坐标 - if (movexy.length < 3) { - action.press(PointOption.point(startx, starty)) - .waitAction(WaitOptions.waitOptions(Duration.ofNanos(1500))) - .moveTo(PointOption.point(endx, endy)); - LogUtil.APP.info("从开始坐标【{},{}】拖动至坐标【{},{}】",startxy[0],startxy[1],endxy[0],endxy[1]); - } else { - if (movexyi == 1) { - action.press(PointOption.point(startx, starty)) - .waitAction(WaitOptions.waitOptions(Duration.ofNanos(1500))) - .moveTo(PointOption.point(endx - startx, endy - starty)); - LogUtil.APP.info("从开始坐标【{},{}】拖动至坐标【{},{}】",startxy[0],startxy[1],endxy[0],endxy[1]); - } else { - action.waitAction(WaitOptions.waitOptions(Duration.ofNanos(1500))) - .moveTo(PointOption.point(endx - startx, endy - starty)); - LogUtil.APP - .info("第{}次拖动至坐标【{},{}】",movexyi,endxy[0],endxy[1]); - } - startx = endx; - starty = endy; - } - } else { - LogUtil.APP.warn("判断结束坐标位置出现异常,结束坐标参数【{}】",movexy[movexyi]); - } - } - action.release().perform(); - result = "moveto全部拖动释放并完成发送...开始位置【" + startxy[0] + "," + startxy[1] + "】"; - LogUtil.APP.info("moveto全部拖动释放并完成发送...开始位置【{},{}】",startxy[0],startxy[1]); - } else { - result = "moveto参数指定的起始坐标处理出现异常【" + movexy[0] + "】,请检查!"; - LogUtil.APP.info("moveto参数指定的起始坐标处理出现异常【{}】,请检查!",movexy[0]); - } - break; - case "timeout": - if (null != operationValue && ChangString.isNumeric(operationValue)) { - // 设置页面加载最大时长30秒 - appium.manage().timeouts().pageLoadTimeout(Integer.valueOf(operationValue), TimeUnit.SECONDS); - // 设置元素出现最大时长30秒 - appium.manage().timeouts().implicitlyWait(Integer.valueOf(operationValue), TimeUnit.SECONDS); - result = "设置全局页面加载&元素出现最大等待时间【" + operationValue + "】秒..."; - LogUtil.APP.info("设置全局页面加载&元素出现最大等待时间【{}】秒...",operationValue); - } else { - result = "【等待时间转换出错,请检查参数】"; - LogUtil.APP.info(result + "原因是因为判断你的等待时间不是数字..."); - } - break; - case "screenshot": - java.text.DateFormat timeformat = new java.text.SimpleDateFormat("MMdd-HHmmss"); - String imagname = "FunctionScreenShot_" + timeformat.format(new Date()); - IosBaseAppium.screenShot(appium, imagname); - result = "截图名称【" + imagname + "】..."; - LogUtil.APP.info("使用方法主动截取当前屏幕...{}",result); - break; - default: - break; - } - return result; - } - - public static void main(String[] args) { - // TODO Auto-generated method stub - - } - -} +package luckyclient.execution.appium.iosex; + +import java.time.Duration; +import java.util.Date; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.openqa.selenium.Alert; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.support.ui.Select; + +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.IOSElement; +import io.appium.java_client.ios.IOSTouchAction; +import io.appium.java_client.touch.LongPressOptions; +import io.appium.java_client.touch.WaitOptions; +import io.appium.java_client.touch.offset.ElementOption; +import io.appium.java_client.touch.offset.PointOption; +import luckyclient.execution.dispose.ChangString; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author Seagull + * @date 2018年2月2日 + * + */ +public class IosEncapsulateOperation { + public static String selectOperation(IOSElement ie, String operation, String operationValue) { + String result = ""; + // 下拉框对象处理 + Select select = new Select(ie); + + // 处理下拉框事件 + switch (operation) { + case "selectbyvisibletext": + select.selectByVisibleText(operationValue); + LogUtil.APP + .info("下拉框对象通过VisibleText属性选择...【VisibleText属性值:{}】",operationValue); + break; + case "selectbyvalue": + select.selectByValue(operationValue); + LogUtil.APP.info("下拉框对象通过Value属性选择...【Value属性值:{}】",operationValue); + break; + case "selectbyindex": + select.selectByIndex(Integer.parseInt(operationValue)); + LogUtil.APP.info("下拉框对象通过Index属性选择...【Index属性值:{}】",operationValue); + break; + case "isselect": + result = "获取到的值是【" + ie.isSelected() + "】"; + LogUtil.APP.info("判断对象是否已经被选择...【结果值:{}】",ie.isSelected()); + break; + default: + break; + } + return result; + } + + public static String getOperation(IOSElement ie, String operation, String value) { + String result = ""; + // 获取对象处理 + switch (operation) { + case "gettext": + result = "获取到的值是【" + ie.getText() + "】"; + LogUtil.APP.info("getText获取对象text属性...【text属性值:{}】",result); + break; // 获取输入框内容 + case "gettagname": + result = "获取到的值是【" + ie.getTagName() + "】"; + LogUtil.APP.info("getTagName获取对象tagname属性...【tagname属性值:{}】",result); + break; + case "getattribute": + result = "获取到的值是【" + ie.getAttribute(value) + "】"; + LogUtil.APP + .info("getAttribute获取对象【{}】属性...【{}属性值:{}】",value,value,result); + break; + case "getcssvalue": + result = "获取到的值是【" + ie.getCssValue(value) + "】"; + LogUtil.APP + .info("getCssValue获取对象【{}】属性...【{}属性值:{}】",value,value,result); + break; + default: + break; + } + return result; + } + + public static String objectOperation(IOSDriver appium, IOSElement ie, String operation, + String operationValue, String property, String propertyValue) { + String result = ""; + IOSTouchAction action = new IOSTouchAction(appium); + // 处理WebElement对象操作 + switch (operation) { + case "click": + ie.click(); + result = "click点击对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; + LogUtil.APP + .info("click点击对象...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); + break; + case "sendkeys": + ie.sendKeys(operationValue); + result = "sendKeys对象输入...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "; 操作值:" + operationValue + + "】"; + LogUtil.APP.info("sendkeys对象输入...【对象定位属性:{}; 定位属性值:{}; 操作值:{}】",property,propertyValue,operationValue); + break; + case "clear": + ie.clear(); + result = "clear清空输入框...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; + LogUtil.APP + .info("clear清空输入框...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); + break; // 清空输入框 + case "isenabled": + result = "获取到的值是【" + ie.isEnabled() + "】"; + LogUtil.APP.info("当前对象判断是否可用布尔值为【{}】",ie.isEnabled()); + break; + case "isdisplayed": + result = "获取到的值是【" + ie.isDisplayed() + "】"; + LogUtil.APP.info("当前对象判断是否可见布尔值为【{}】",ie.isDisplayed()); + break; + case "exjsob": + ((JavascriptExecutor) appium).executeScript(operationValue, ie); + result = "执行JS...【" + operationValue + "】"; + LogUtil.APP.info("执行JS...【{}】",operationValue); + break; + case "longpresselement": + LongPressOptions lpoptions = new LongPressOptions(); + lpoptions.withElement(ElementOption.element(ie)); + if (null != operationValue && ChangString.isNumeric(operationValue)) { + int nanos = Integer.parseInt(operationValue) * 1000; + Duration duration = Duration.ofNanos(nanos); + lpoptions.withDuration(duration); + } + action.longPress(lpoptions).release().perform(); + result = "longpresselement在屏幕指定元素上按住" + operationValue + "秒...【对象定位属性:" + property + "; 定位属性值:" + + propertyValue + "】"; + LogUtil.APP.info("longpresselement在屏幕指定元素上按住{}秒...【对象定位属性:{}; 定位属性值:{}】",operationValue,property,propertyValue); + break; + default: + break; + } + return result; + } + + public static String alertOperation(IOSDriver appium, String operation) { + String result = ""; + Alert alert = appium.switchTo().alert(); + switch (operation) { + case "alertaccept": + alert.accept(); + LogUtil.APP.info("弹出框对象点击同意..."); + break; + case "alertdismiss": + alert.dismiss(); + LogUtil.APP.info("弹出框对象点击取消..."); + break; + case "alertgettext": + result = "获取到的值是【" + alert.getText() + "】"; + LogUtil.APP.info("弹出框对象通过getText获取对象text属性...【Text属性值:{}】",alert.getText()); + break; + default: + break; + } + return result; + } + + public static String driverOperation(IOSDriver appium, String operation, String operationValue) { + String result = ""; + IOSTouchAction action = new IOSTouchAction(appium); + // 处理页面对象操作 + switch (operation) { + case "getcontexthandles": + Set handles = appium.getContextHandles(); + int handlenum = 1; + for (String handle : handles) { + if (String.valueOf(handlenum).equals(operationValue)) { + if (appium.getContext().equals(handle)) { + result = "请注意,你指定的ContextHandle就是当前页面哦,获取到的值是【" + handle + "】"; + } else { + result = "指定ContextHandler的顺序值是" + operationValue + ",获取到的值是【" + handle + "】"; + } + break; + } + handlenum++; + } + LogUtil.APP.info("getContext获取窗口句柄...{}",result); + break; + case "exjs": + ((JavascriptExecutor) appium).executeScript(operationValue); + result = "执行JS...【" + operationValue + "】"; + LogUtil.APP.info("执行JS...【{}】",operationValue); + break; + // 隐藏手机键盘 + case "hideKeyboard": + appium.hideKeyboard(); + result = "隐藏手机键盘...【hideKeyboard】"; + LogUtil.APP.info("隐藏手机键盘...【hideKeyboard】"); + break; + case "gotocontext": + Set ctNames = appium.getContextHandles(); + int flag = 0; + for (String contextName : ctNames) { + if (contextName.contains(operationValue)) { + flag = 1; + appium.context(contextName); + break; + } + } + if (flag == 1) { + result = "切换context至【" + operationValue + "】"; + LogUtil.APP.info("切换context至【{}】",operationValue); + } else { + result = "切换context失败,未找到contextName值为【" + operationValue + "】的对象"; + LogUtil.APP.info("切换context失败,未找到contextName值为【{}】的对象",operationValue); + } + break; + case "getcontext": + result = "获取到的值是【" + appium.getContext() + "】"; + LogUtil.APP.info("获取页面Context...【{}】",appium.getContext()); + break; + case "gettitle": + result = "获取到的值是【" + appium.getTitle() + "】"; + LogUtil.APP.info("获取页面gettitle...【{}】",appium.getTitle()); + break; + case "swipeup": + String[] tempup = operationValue.split("\\|", -1); + if (null != tempup[0] && ChangString.isNumeric(tempup[0])) { + Double second = Double.valueOf(tempup[0]); + if (null != tempup[1] && ChangString.isNumeric(tempup[1])) { + int num = Integer.parseInt(tempup[1]); + IosBaseAppium.swipePageDown(appium, second, num); + result = "swipeup手指向上滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipeup手指向上滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipeup手指向上滑动参数判断次数出现异常【" + tempup[1] + "】"; + LogUtil.APP.info("swipeup手指向上滑动参数判断次数出现异常【{}】",tempup[1]); + } + } else { + result = "swipeup手指向上滑动参数判断时间出现异常【" + tempup[0] + "】"; + LogUtil.APP.info("swipeup手指向上滑动参数判断时间出现异常【{}】",tempup[0]); + } + break; + case "swipedown": + String[] tempdown = operationValue.split("\\|", -1); + if (null != tempdown[0] && ChangString.isNumeric(tempdown[0])) { + Double second = Double.valueOf(tempdown[0]); + if (null != tempdown[1] && ChangString.isNumeric(tempdown[1])) { + int num = Integer.parseInt(tempdown[1]); + IosBaseAppium.swipePageUp(appium, second, num); + result = "swipedown手指向下滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipedown手指向下滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipedown手指向下滑动参数判断次数出现异常【" + tempdown[1] + "】"; + LogUtil.APP.info("swipedown手指向下滑动参数判断次数出现异常【{}】",tempdown[1]); + } + } else { + result = "swipedown手指向下滑动参数判断时间出现异常【" + tempdown[0] + "】"; + LogUtil.APP.info("swipedown手指向下滑动参数判断时间出现异常【{}】",tempdown[0]); + } + break; + case "swipeleft": + String[] templeft = operationValue.split("\\|", -1); + if (null != templeft[0] && ChangString.isNumeric(templeft[0])) { + Double second = Double.valueOf(templeft[0]); + if (null != templeft[1] && ChangString.isNumeric(templeft[1])) { + int num = Integer.parseInt(templeft[1]); + IosBaseAppium.swipePageRight(appium, second, num); + result = "swipleft手指向左滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipleft手指向左滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipleft手指向左滑动参数判断次数出现异常【" + templeft[1] + "】"; + LogUtil.APP.info("swipleft手指向左滑动参数判断次数出现异常【{}】",templeft[1]); + } + } else { + result = "swipleft手指向左滑动参数判断时间出现异常【" + templeft[0] + "】"; + LogUtil.APP.info("swipleft手指向左滑动参数判断时间出现异常【{}】",templeft[0]); + } + break; + case "swiperight": + String[] tempright = operationValue.split("\\|", -1); + if (null != tempright[0] && ChangString.isNumeric(tempright[0])) { + Double second = Double.valueOf(tempright[0]); + if (null != tempright[1] && ChangString.isNumeric(tempright[1])) { + int num = Integer.parseInt(tempright[1]); + IosBaseAppium.swipePageLeft(appium, second, num); + result = "swipright手指向右滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipright手指向右滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipright手指向右滑动参数判断次数出现异常【" + tempright[1] + "】"; + LogUtil.APP.info("swipright手指向右滑动参数判断次数出现异常【{}】",tempright[1]); + } + } else { + result = "swipright手指向右滑动参数判断时间出现异常【" + tempright[0] + "】"; + LogUtil.APP.info("swipright手指向右滑动参数判断时间出现异常【{}】",tempright[0]); + } + break; + case "swipepageup": + String[] tempPageUp = operationValue.split("\\|", -1); + if (null != tempPageUp[0] && ChangString.isNumeric(tempPageUp[0])) { + Double second = Double.valueOf(tempPageUp[0]); + if (null != tempPageUp[1] && ChangString.isNumeric(tempPageUp[1])) { + int num = Integer.parseInt(tempPageUp[1]); + IosBaseAppium.swipePageUp(appium, second, num); + result = "swipeup页面向上滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipeup页面向上滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipeup页面向上滑动参数判断次数出现异常【" + tempPageUp[1] + "】"; + LogUtil.APP.info("swipeup页面向上滑动参数判断次数出现异常【{}】",tempPageUp[1]); + } + } else { + result = "swipeup页面向上滑动参数判断时间出现异常【" + tempPageUp[0] + "】"; + LogUtil.APP.info("swipeup页面向上滑动参数判断时间出现异常【{}】",tempPageUp[0]); + } + break; + case "swipepagedown": + String[] tempPageDown = operationValue.split("\\|", -1); + if (null != tempPageDown[0] && ChangString.isNumeric(tempPageDown[0])) { + Double second = Double.valueOf(tempPageDown[0]); + if (null != tempPageDown[1] && ChangString.isNumeric(tempPageDown[1])) { + int num = Integer.parseInt(tempPageDown[1]); + IosBaseAppium.swipePageDown(appium, second, num); + result = "swipedown页面向下滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipedown页面向下滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipedown页面向下滑动参数判断次数出现异常【" + tempPageDown[1] + "】"; + LogUtil.APP.info("swipedown页面向下滑动参数判断次数出现异常【{}】",tempPageDown[1]); + } + } else { + result = "swipedown页面向下滑动参数判断时间出现异常【" + tempPageDown[0] + "】"; + LogUtil.APP.info("swipedown页面向下滑动参数判断时间出现异常【{}】",tempPageDown[0]); + } + break; + case "swipepageleft": + String[] tempPageLeft = operationValue.split("\\|", -1); + if (null != tempPageLeft[0] && ChangString.isNumeric(tempPageLeft[0])) { + Double second = Double.valueOf(tempPageLeft[0]); + if (null != tempPageLeft[1] && ChangString.isNumeric(tempPageLeft[1])) { + int num = Integer.parseInt(tempPageLeft[1]); + IosBaseAppium.swipePageLeft(appium, second, num); + result = "swipleft页面向左滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipleft页面向左滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipleft页面向左滑动参数判断次数出现异常【" + tempPageLeft[1] + "】"; + LogUtil.APP.info("swipleft页面向左滑动参数判断次数出现异常【{}】",tempPageLeft[1]); + } + } else { + result = "swipleft页面向左滑动参数判断时间出现异常【" + tempPageLeft[0] + "】"; + LogUtil.APP.info("swipleft页面向左滑动参数判断时间出现异常【{}】",tempPageLeft[0]); + } + break; + case "swipepageright": + String[] tempPageRight = operationValue.split("\\|", -1); + if (null != tempPageRight[0] && ChangString.isNumeric(tempPageRight[0])) { + Double second = Double.valueOf(tempPageRight[0]); + if (null != tempPageRight[1] && ChangString.isNumeric(tempPageRight[1])) { + int num = Integer.parseInt(tempPageRight[1]); + IosBaseAppium.swipePageRight(appium, second, num); + result = "swipright页面向右滑动参数...秒|次数【" + second + "|" + num + "】"; + LogUtil.APP.info("swipright页面向右滑动参数...秒|次数【{}|{}】",second,num); + } else { + result = "swipright页面向右滑动参数判断次数出现异常【" + tempPageRight[1] + "】"; + LogUtil.APP.info("swipright页面向右滑动参数判断次数出现异常【{}】",tempPageRight[1]); + } + } else { + result = "swipright页面向右滑动参数判断时间出现异常【" + tempPageRight[0] + "】"; + LogUtil.APP.info("swipright页面向右滑动参数判断时间出现异常【{}】",tempPageRight[0]); + } + break; + case "longpressxy": + String[] longpressxy = operationValue.split("\\|", -1); + if (null != longpressxy[0] && ChangString.isNumeric(longpressxy[0])) { + int longpressx = Integer.parseInt(longpressxy[0]); + if (null != longpressxy[1] && ChangString.isNumeric(longpressxy[1])) { + int longpressy = Integer.parseInt(longpressxy[1]); + if (null != longpressxy[2] && ChangString.isNumeric(longpressxy[2])) { + LongPressOptions lpoptions = new LongPressOptions(); + lpoptions.withPosition(PointOption.point(longpressx, longpressy)); + int nanos = Integer.parseInt(longpressxy[2]) * 1000; + Duration duration = Duration.ofNanos(nanos); + lpoptions.withDuration(duration); + action.longPress(lpoptions).release().perform(); + result = "longpressxy在屏幕指定XY坐标上按住" + longpressxy[2] + "秒...X|Y【" + longpressx + "|" + longpressy + + "】"; + LogUtil.APP.info("longpressxy在屏幕指定XY坐标上按住{}秒...X|Y【{}|{}】",longpressxy[2],longpressx,longpressy); + } else { + action.longPress(PointOption.point(longpressx, longpressy)).release().perform(); + result = "longpressxy在屏幕指定XY坐标上长按...X|Y【" + longpressx + "|" + longpressy + "】"; + LogUtil.APP.info("longpressxy在屏幕指定XY坐标上长按...X|Y【{}|{}】",longpressx,longpressy); + } + } else { + result = "longpressxy参数指定的Y坐标处理出现异常【" + longpressxy[1] + "】"; + LogUtil.APP.info("longpressxy参数指定的Y坐标处理出现异常【{}】",longpressxy[1]); + } + } else { + result = "longpressxy参数指定的X坐标处理出现异常【" + longpressxy[0] + "】"; + LogUtil.APP.info("longpressxy参数指定的X坐标处理出现异常【{}】",longpressxy[0]); + } + break; + case "pressxy": + String[] pressxy = operationValue.split("\\|", -1); + if (null != pressxy[0] && ChangString.isNumeric(pressxy[0])) { + int pressx = Integer.parseInt(pressxy[0]); + if (null != pressxy[1] && ChangString.isNumeric(pressxy[1])) { + int pressy = Integer.parseInt(pressxy[1]); + action.press(PointOption.point(pressx, pressy)).release().perform(); + result = "pressxy在屏幕指定XY坐标上点击...X|Y【" + pressx + "|" + pressy + "】"; + LogUtil.APP.info("pressxy在屏幕指定XY坐标上点击...X|Y【{}|{}】",pressx,pressy); + } else { + result = "pressxy参数指定的Y坐标处理出现异常【" + pressxy[1] + "】"; + LogUtil.APP.info("pressxy参数指定的Y坐标处理出现异常【{}】",pressxy[1]); + } + } else { + result = "pressxy参数指定的X坐标处理出现异常【" + pressxy[0] + "】"; + LogUtil.APP.info("pressxy参数指定的X坐标处理出现异常【{}】",pressxy[0]); + } + break; + case "tapxy": + String[] tapxy = operationValue.split("\\|", -1); + if (null != tapxy[0] && ChangString.isNumeric(tapxy[0])) { + int tapx = Integer.parseInt(tapxy[0]); + if (null != tapxy[1] && ChangString.isNumeric(tapxy[1])) { + int tapy = Integer.parseInt(tapxy[1]); + action.tap(PointOption.point(tapx, tapy)).release().perform(); + result = "tapxy在屏幕指定XY坐标上轻击...X|Y【" + tapx + "|" + tapy + "】"; + LogUtil.APP.info("tapxy在屏幕指定XY坐标上轻击...X|Y【{}|{}】",tapx,tapy); + } else { + result = "tapxy参数指定的Y坐标处理出现异常【" + tapxy[1] + "】"; + LogUtil.APP.info("tapxy参数指定的Y坐标处理出现异常【{}】",tapxy[1]); + } + } else { + result = "tapxy参数指定的X坐标处理出现异常【" + tapxy[0] + "】"; + LogUtil.APP.info("tapxy参数指定的X坐标处理出现异常【{}】",tapxy[0]); + } + break; + case "jspressxy": + String[] jspressxy = operationValue.split("\\|", -1); + if (null != jspressxy[0] && ChangString.isNumeric(jspressxy[0])) { + int jspressx = Integer.parseInt(jspressxy[0]); + if (null != jspressxy[1] && ChangString.isNumeric(jspressxy[1])) { + int jspressy = Integer.parseInt(jspressxy[1]); + if (null != jspressxy[2] && ChangString.isNumeric(jspressxy[2])) { + IosBaseAppium.clickScreenForJs(appium, jspressx, jspressy, Integer.parseInt(jspressxy[2])); + result = "jspressxy在屏幕指定XY坐标上按" + jspressxy[2] + "秒...X|Y【" + jspressx + "|" + jspressy + "】"; + LogUtil.APP.info("jspressxy在屏幕指定XY坐标上按{}秒...X|Y【{}|{}】",jspressxy[2],jspressx,jspressy); + } else { + IosBaseAppium.clickScreenForJs(appium, jspressx, jspressy, 2); + result = "jspressxy在屏幕指定XY坐标上按2秒(持续时间判断异常,使用默认2秒时间)...X|Y【" + jspressx + "|" + jspressy + "】"; + LogUtil.APP.info("jspressxy在屏幕指定XY坐标上按2秒(持续时间判断异常,使用默认2秒时间)...X|Y【{}|{}】",jspressx,jspressy); + } + } else { + result = "jspressxy参数指定的Y坐标处理出现异常【" + jspressxy[1] + "】"; + LogUtil.APP.info("jspressxy参数指定的Y坐标处理出现异常【{}】",jspressxy[1]); + } + } else { + result = "jspressxy参数指定的X坐标处理出现异常【" + jspressxy[0] + "】"; + LogUtil.APP.info("jspressxy参数指定的X坐标处理出现异常【{}】",jspressxy[0]); + } + break; + case "moveto": + String[] movexy = operationValue.split("\\|", -1); + if (null != movexy[0] && !"".equals(movexy[0])) { + String[] startxy = movexy[0].split(",", -1); + int startx = Integer.parseInt(startxy[0]); + int starty = Integer.parseInt(startxy[1]); + for (int movexyi = 1; movexyi < movexy.length; movexyi++) { + if (null != movexy[movexyi] && !"".equals(movexy[movexyi])) { + String[] endxy = movexy[movexyi].split(",", -1); + int endx = Integer.parseInt(endxy[0]); + int endy = Integer.parseInt(endxy[1]); + // 不确定是否是API的bug,只有一次MOVE时,是XY坐标,当大于一次MOVE时,坐标是偏移坐标 + if (movexy.length < 3) { + action.press(PointOption.point(startx, starty)) + .waitAction(WaitOptions.waitOptions(Duration.ofNanos(1500))) + .moveTo(PointOption.point(endx, endy)); + LogUtil.APP.info("从开始坐标【{},{}】拖动至坐标【{},{}】",startxy[0],startxy[1],endxy[0],endxy[1]); + } else { + if (movexyi == 1) { + action.press(PointOption.point(startx, starty)) + .waitAction(WaitOptions.waitOptions(Duration.ofNanos(1500))) + .moveTo(PointOption.point(endx - startx, endy - starty)); + LogUtil.APP.info("从开始坐标【{},{}】拖动至坐标【{},{}】",startxy[0],startxy[1],endxy[0],endxy[1]); + } else { + action.waitAction(WaitOptions.waitOptions(Duration.ofNanos(1500))) + .moveTo(PointOption.point(endx - startx, endy - starty)); + LogUtil.APP + .info("第{}次拖动至坐标【{},{}】",movexyi,endxy[0],endxy[1]); + } + startx = endx; + starty = endy; + } + } else { + LogUtil.APP.warn("判断结束坐标位置出现异常,结束坐标参数【{}】",movexy[movexyi]); + } + } + action.release().perform(); + result = "moveto全部拖动释放并完成发送...开始位置【" + startxy[0] + "," + startxy[1] + "】"; + LogUtil.APP.info("moveto全部拖动释放并完成发送...开始位置【{},{}】",startxy[0],startxy[1]); + } else { + result = "moveto参数指定的起始坐标处理出现异常【" + movexy[0] + "】,请检查!"; + LogUtil.APP.info("moveto参数指定的起始坐标处理出现异常【{}】,请检查!",movexy[0]); + } + break; + case "timeout": + if (null != operationValue && ChangString.isNumeric(operationValue)) { + // 设置页面加载最大时长30秒 + appium.manage().timeouts().pageLoadTimeout(Integer.parseInt(operationValue), TimeUnit.SECONDS); + // 设置元素出现最大时长30秒 + appium.manage().timeouts().implicitlyWait(Integer.parseInt(operationValue), TimeUnit.SECONDS); + result = "设置全局页面加载&元素出现最大等待时间【" + operationValue + "】秒..."; + LogUtil.APP.info("设置全局页面加载&元素出现最大等待时间【{}】秒...",operationValue); + } else { + result = "【等待时间转换出错,请检查参数】"; + LogUtil.APP.info(result + "原因是因为判断你的等待时间不是数字..."); + } + break; + case "screenshot": + java.text.DateFormat timeformat = new java.text.SimpleDateFormat("MMdd-HHmmss"); + String imagname = "FunctionScreenShot_" + timeformat.format(new Date()); + IosBaseAppium.screenShot(appium, imagname); + result = "截图名称【" + imagname + "】..."; + LogUtil.APP.info("使用方法主动截取当前屏幕...{}",result); + break; + default: + break; + } + return result; + } + + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + +} diff --git a/src/main/java/luckyclient/execution/appium/iosex/IosOneCaseExecute.java b/src/main/java/luckyclient/execution/appium/iosex/IosOneCaseExecute.java index aa3de02..b986d1d 100644 --- a/src/main/java/luckyclient/execution/appium/iosex/IosOneCaseExecute.java +++ b/src/main/java/luckyclient/execution/appium/iosex/IosOneCaseExecute.java @@ -1,73 +1,74 @@ -package luckyclient.execution.appium.iosex; - -import java.io.IOException; -import java.util.List; -import java.util.Properties; - -import io.appium.java_client.ios.IOSDriver; -import io.appium.java_client.ios.IOSElement; -import luckyclient.execution.appium.AppiumInitialization; -import luckyclient.execution.appium.AppiumService; -import luckyclient.execution.httpinterface.TestControl; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.LogUtil; -import luckyclient.utils.config.AppiumConfig; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * @author: seagull - * @date 2018年2月2日 - * - */ -public class IosOneCaseExecute { - - public static void oneCaseExecuteForTast(String projectname, Integer caseId, int version, String taskid) - throws IOException, InterruptedException { - // 记录日志到数据库 - serverOperation.exetype = 0; - TestControl.TASKID = taskid; - IOSDriver iosd = null; - AppiumService as=null; - try { - Properties properties = AppiumConfig.getConfiguration(); - //根据配置自动启动Appiume服务 - if(Boolean.valueOf(properties.getProperty("autoRunAppiumService"))){ - as =new AppiumService(); - as.start(); - Thread.sleep(10000); - } - - iosd = AppiumInitialization.setIosAppium(properties); - } catch (IOException e1) { - LogUtil.APP.error("初始化IOSDriver出错!", e1); - } - serverOperation caselog = new serverOperation(); - ProjectCase testcase = GetServerApi.cGetCaseByCaseId(caseId); - // 删除旧的日志 - serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); - - List pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); - LogUtil.APP.info("开始执行用例:【{}】......",testcase.getCaseSign()); - try { - List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); - IosCaseExecution.caseExcution(testcase, steps, taskid, iosd, caselog, pcplist); - LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); - } catch (InterruptedException e) { - LogUtil.APP.error("用户执行过程中抛出异常!", e); - } - serverOperation.updateTaskExecuteData(taskid, 0,2); - iosd.closeApp(); - //关闭Appium服务的线程 - if(as!=null){ - as.interrupt(); - } - } - -} +package luckyclient.execution.appium.iosex; + +import java.io.IOException; +import java.util.List; +import java.util.Properties; + +import io.appium.java_client.ios.IOSDriver; +import io.appium.java_client.ios.IOSElement; +import luckyclient.execution.appium.AppiumInitialization; +import luckyclient.execution.appium.AppiumService; +import luckyclient.execution.httpinterface.TestControl; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.LogUtil; +import luckyclient.utils.config.AppiumConfig; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * @author: seagull + * @date 2018年2月2日 + * + */ +public class IosOneCaseExecute { + + public static void oneCaseExecuteForTast(Integer caseId, String taskid) + throws InterruptedException { + // 记录日志到数据库 + serverOperation.exetype = 0; + TestControl.TASKID = taskid; + IOSDriver iosd = null; + AppiumService as=null; + try { + Properties properties = AppiumConfig.getConfiguration(); + //根据配置自动启动Appiume服务 + if(Boolean.parseBoolean(properties.getProperty("autoRunAppiumService"))){ + as =new AppiumService(); + as.start(); + Thread.sleep(10000); + } + + iosd = AppiumInitialization.setIosAppium(properties); + } catch (IOException e1) { + LogUtil.APP.error("初始化IOSDriver出错!", e1); + } + serverOperation caselog = new serverOperation(); + ProjectCase testcase = GetServerApi.cGetCaseByCaseId(caseId); + // 删除旧的日志 + serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); + + List pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); + LogUtil.APP.info("开始执行用例:【{}】......",testcase.getCaseSign()); + try { + List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); + IosCaseExecution.caseExcution(testcase, steps, taskid, iosd, caselog, pcplist); + LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); + } catch (Exception e) { + LogUtil.APP.error("用户执行过程中抛出异常!", e); + } + serverOperation.updateTaskExecuteData(taskid, 0,2); + assert iosd != null; + iosd.closeApp(); + //关闭Appium服务的线程 + if(as!=null){ + as.interrupt(); + } + } + +} diff --git a/src/main/java/luckyclient/execution/dispose/ActionContext.java b/src/main/java/luckyclient/execution/dispose/ActionContext.java index 908f54f..08c9f69 100644 --- a/src/main/java/luckyclient/execution/dispose/ActionContext.java +++ b/src/main/java/luckyclient/execution/dispose/ActionContext.java @@ -1,63 +1,63 @@ -package luckyclient.execution.dispose; - -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import org.reflections.Reflections; - -import luckyclient.execution.dispose.actionkeyword.Action; -import luckyclient.execution.dispose.actionkeyword.ActionKeyWordParser; -import luckyclient.utils.LogUtil; - -/** - * 步骤动作容器,根据参数生成不同的动作关键字类型,执行相应的解析 - * @author: sunshaoyan@ - * @date: Created on 2019/4/13 - */ -@SuppressWarnings("rawtypes") -public class ActionContext { - - private static Map allActions; - - static { - Reflections reflections = new Reflections("luckyclient.execution.dispose.actionkeyword"); - Set> annotatedClasses = - reflections.getTypesAnnotatedWith(Action.class); - allActions = new ConcurrentHashMap(); - for (Class classObject : annotatedClasses) { - Action action = (Action) classObject - .getAnnotation(Action.class); - allActions.put(action.name(), classObject); - } - allActions = Collections.unmodifiableMap(allActions); - } - - private ActionKeyWordParser action; - - public ActionContext(String name){ - - if (allActions.containsKey(name)) { - LogUtil.APP.info("Created Action name is {}", name); - try { - action = (ActionKeyWordParser) allActions.get(name).newInstance(); - } catch (InstantiationException | IllegalAccessException ex) { - LogUtil.APP.error("Instantiate Action failed", ex); - } - } else { - LogUtil.APP.warn("Specified Action name {} does not exist", name); - } - } - - public String parse(String actionParams,String testResult,String actionKeyWord) { - if(null != action){ - testResult = action.parse(actionParams, testResult); - }else { - testResult="未检索到对应动作关键字,直接跳过此动作,请检查关键字:"+actionKeyWord; - LogUtil.APP.warn("未检索到对应动作关键字,直接跳过此动作,请检查关键字:{}",actionKeyWord); - } - return testResult; - } - -} +package luckyclient.execution.dispose; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.reflections.Reflections; + +import luckyclient.execution.dispose.actionkeyword.Action; +import luckyclient.execution.dispose.actionkeyword.ActionKeyWordParser; +import luckyclient.utils.LogUtil; + +/** + * 步骤动作容器,根据参数生成不同的动作关键字类型,执行相应的解析 + * @author: sunshaoyan@ + * @date: Created on 2019/4/13 + */ +@SuppressWarnings("rawtypes") +public class ActionContext { + + private static Map allActions; + + static { + Reflections reflections = new Reflections("luckyclient.execution.dispose.actionkeyword"); + Set> annotatedClasses = + reflections.getTypesAnnotatedWith(Action.class); + allActions = new ConcurrentHashMap<>(); + for (Class classObject : annotatedClasses) { + Action action = classObject + .getAnnotation(Action.class); + allActions.put(action.name(), classObject); + } + allActions = Collections.unmodifiableMap(allActions); + } + + private ActionKeyWordParser action; + + public ActionContext(String name){ + + if (allActions.containsKey(name)) { + LogUtil.APP.info("Created Action name is {}", name); + try { + action = (ActionKeyWordParser) allActions.get(name).newInstance(); + } catch (InstantiationException | IllegalAccessException ex) { + LogUtil.APP.error("Instantiate Action failed", ex); + } + } else { + LogUtil.APP.warn("Specified Action name {} does not exist", name); + } + } + + public String parse(String actionParams,String testResult,String actionKeyWord) { + if(null != action){ + testResult = action.parse(actionParams, testResult); + }else { + testResult="未检索到对应动作关键字,直接跳过此动作,请检查关键字:"+actionKeyWord; + LogUtil.APP.warn("未检索到对应动作关键字,直接跳过此动作,请检查关键字:{}",actionKeyWord); + } + return testResult; + } + +} diff --git a/src/main/java/luckyclient/execution/dispose/ActionManageForSteps.java b/src/main/java/luckyclient/execution/dispose/ActionManageForSteps.java index 4154a2a..1df301b 100644 --- a/src/main/java/luckyclient/execution/dispose/ActionManageForSteps.java +++ b/src/main/java/luckyclient/execution/dispose/ActionManageForSteps.java @@ -1,90 +1,90 @@ -package luckyclient.execution.dispose; - -import cn.hutool.core.util.StrUtil; -import luckyclient.utils.Constants; -import luckyclient.utils.LogUtil; - -/** - * 动作关键字处理 - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull - * ================================================================= - * @author Seagull - * @date 2019年1月15日 - */ -public class ActionManageForSteps { - - /** - * 解析用例步骤 - * @param stepsaction - * @param testresult - * @return - */ - public static String actionManage(String stepsaction,String testresult){ - LogUtil.APP.info("Action(动作)处理前,测试结果是:{}",testresult); - LogUtil.APP.info("现在进入到Action(动作)处理......ACTION值:{}",stepsaction); - if(null==stepsaction||"".equals(stepsaction.trim())){ - LogUtil.APP.info("Action(动作)无需处理......"); - return testresult; - } - - String responseHead=""; - String responseCode=""; - //去除测试响应头域消息 - if(testresult.startsWith(Constants.RESPONSE_HEAD)){ - responseHead = testresult.substring(0,testresult.indexOf(Constants.RESPONSE_END)+1); - testresult = testresult.substring(testresult.indexOf(responseHead)+responseHead.length()+1); - responseHead = responseHead+" "; - } - - //去除测试响应头域消息 - if(testresult.startsWith(Constants.RESPONSE_CODE)){ - responseCode = testresult.substring(0,testresult.indexOf(Constants.RESPONSE_END)+1); - testresult = testresult.substring(testresult.indexOf(responseCode)+responseCode.length()+1); - responseCode = responseCode+" "; - } - - stepsaction=stepsaction.trim(); - String[] temp=stepsaction.split("\\|",-1); - for(String actionorder:temp){ - if(null!=actionorder&&!"".equals(actionorder.trim())){ - testresult=actionExecute(actionorder,testresult); - } - } - - //返回处理结果时,再把响应头以及响应码加上 - return responseHead+responseCode+testresult; - } - - /** - * 动作关键字执行 - * @param actionKeyWord - * @param testResult - * @return - */ - private static String actionExecute(String actionKeyWord,String testResult){ - try{ - String keyWord = ""; - String actionParams = ""; - if(actionKeyWord.contains("#")){ - keyWord = actionKeyWord.substring(actionKeyWord.lastIndexOf("#")+1, actionKeyWord.length()); - actionParams = actionKeyWord.substring(0, actionKeyWord.lastIndexOf("#")); - } - - if(StrUtil.isNotEmpty(keyWord)&& keyWord.length()>0){ - ActionContext actionContext = new ActionContext(keyWord.toLowerCase()); - testResult = actionContext.parse(actionParams, testResult, actionKeyWord); - }else { - testResult="关键字语法书写有误,请检查关键字:"+actionKeyWord; - LogUtil.APP.warn("关键字语法书写有误,请检查关键字:{}",actionKeyWord); - } - return testResult; - }catch(Exception e){ - testResult="处理步骤动作事件过程中出现异常,直接返回测试结果:"+actionKeyWord; - LogUtil.APP.error("处理步骤动作事件过程中出现异常,直接返回测试结果!" ,e); - return testResult; - } - } - -} +package luckyclient.execution.dispose; + +import cn.hutool.core.util.StrUtil; +import luckyclient.utils.Constants; +import luckyclient.utils.LogUtil; + +/** + * 动作关键字处理 + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull + * ================================================================= + * @author Seagull + * @date 2019年1月15日 + */ +public class ActionManageForSteps { + + /** + * 解析用例步骤 + * @param stepsaction 步骤关键字 + * @param testresult 待处理测试结果 + * @return 返回处理后结果 + */ + public static String actionManage(String stepsaction,String testresult){ + LogUtil.APP.info("Action(动作)处理前,测试结果是:{}",testresult); + LogUtil.APP.info("现在进入到Action(动作)处理......ACTION值:{}",stepsaction); + if(null==stepsaction||"".equals(stepsaction.trim())){ + LogUtil.APP.info("Action(动作)无需处理......"); + return testresult; + } + + String responseHead=""; + String responseCode=""; + //去除测试响应头域消息 + if(testresult.startsWith(Constants.RESPONSE_HEAD)){ + responseHead = testresult.substring(0,testresult.indexOf(Constants.RESPONSE_END)+1); + testresult = testresult.substring(testresult.indexOf(responseHead)+responseHead.length()+1); + responseHead = responseHead+" "; + } + + //去除测试响应头域消息 + if(testresult.startsWith(Constants.RESPONSE_CODE)){ + responseCode = testresult.substring(0,testresult.indexOf(Constants.RESPONSE_END)+1); + testresult = testresult.substring(testresult.indexOf(responseCode)+responseCode.length()+1); + responseCode = responseCode+" "; + } + + stepsaction=stepsaction.trim(); + String[] temp=stepsaction.split("\\|",-1); + for(String actionorder:temp){ + if(null!=actionorder&&!"".equals(actionorder.trim())){ + testresult=actionExecute(actionorder,testresult); + } + } + + //返回处理结果时,再把响应头以及响应码加上 + return responseHead+responseCode+testresult; + } + + /** + * 动作关键字执行 + * @param actionKeyWord 步骤关键字 + * @param testResult 待处理测试结果 + * @return 关键字处理后返回结果 + */ + private static String actionExecute(String actionKeyWord,String testResult){ + try{ + String keyWord = ""; + String actionParams = ""; + if(actionKeyWord.contains("#")){ + keyWord = actionKeyWord.substring(actionKeyWord.lastIndexOf("#")+1); + actionParams = actionKeyWord.substring(0, actionKeyWord.lastIndexOf("#")); + } + + if(StrUtil.isNotEmpty(keyWord)&& keyWord.length()>0){ + ActionContext actionContext = new ActionContext(keyWord.toLowerCase()); + testResult = actionContext.parse(actionParams, testResult, actionKeyWord); + }else { + testResult="关键字语法书写有误,请检查关键字:"+actionKeyWord; + LogUtil.APP.warn("关键字语法书写有误,请检查关键字:{}",actionKeyWord); + } + return testResult; + }catch(Exception e){ + testResult="处理步骤动作事件过程中出现异常,直接返回测试结果:"+actionKeyWord; + LogUtil.APP.error("处理步骤动作事件过程中出现异常,直接返回测试结果!" ,e); + return testResult; + } + } + +} diff --git a/src/main/java/luckyclient/execution/dispose/ChangString.java b/src/main/java/luckyclient/execution/dispose/ChangString.java index 34fc2f7..cb0dc61 100644 --- a/src/main/java/luckyclient/execution/dispose/ChangString.java +++ b/src/main/java/luckyclient/execution/dispose/ChangString.java @@ -2,13 +2,7 @@ package luckyclient.execution.dispose; import java.math.BigDecimal; import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; import java.util.regex.Pattern; @@ -34,10 +28,10 @@ public class ChangString { /** * 替换变量中的字符 * - * @param str - * @param variable - * @param changname - * @return + * @param str 待处理字符串 + * @param variable 变量集(公共变量、全局变量、局部变量) + * @param changname 变量key + * @return 返回替换后的字符串 */ public static String changparams(String str, Map variable, String changname) { try { @@ -45,7 +39,7 @@ public class ChangString { return null; } str = str.replace(""", "\""); - str = str.replace("'", "\'"); + str = str.replace("'", "'"); // @@用来注释@的引用作用 int varcount = counter(str, "@") - counter(str, "@@") * 2; @@ -55,17 +49,14 @@ public class ChangString { int changcount = 0; // 准备将HASHMAP换成LINKMAP,对KEY进行排序,解决要先替换最长KEY的问题 - List> list = new ArrayList>(variable.entrySet()); + List> list = new ArrayList<>(variable.entrySet()); // 然后通过比较器来实现排序 - Collections.sort(list, new Comparator>() { - // 按KEY长度降序排序 - @Override - public int compare(Entry o1, Entry o2) { - return o2.getKey().length() - o1.getKey().length(); - } - }); + // 按KEY长度降序排序 + // 然后通过比较器来实现排序 + // 按KEY长度降序排序 + list.sort((o1, o2) -> o2.getKey().length() - o1.getKey().length()); - Map aMap2 = new LinkedHashMap(); + Map aMap2 = new LinkedHashMap<>(); for (Map.Entry mapping : list) { aMap2.put(mapping.getKey(), mapping.getValue()); } @@ -105,10 +96,9 @@ public class ChangString { /** * 统计字符 - * - * @param str1 - * @param str2 - * @return + * @param str1 原始字符串 + * @param str2 待统计字符串 + * @return 返回个数 */ public static int counter(String str1, String str2) { int total = 0; @@ -125,9 +115,8 @@ public class ChangString { /** * 判断是否是数字 - * - * @param str - * @return + * @param str 数字字符 + * @return 返回布尔值 */ public static boolean isNumeric(String str) { for (int i = 0; i < str.length(); i++) { @@ -140,22 +129,20 @@ public class ChangString { /** * 判断是否是整数 - * - * @param str - * @return + * @param str 数字字符 + * @return 返回布尔值 */ public static boolean isInteger(String str) { - String patternStr="^[-\\+]?[\\d]*$"; + String patternStr="^[-+]?[\\d]*$"; Pattern pattern = Pattern.compile(patternStr); return pattern.matcher(str).matches(); } /** * 替换变量类型 - * - * @param object - * @param str - * @return + * @param object 替换对象 + * @param str 替换字符串 + * @return 返回对象 */ public static Object settype(Object object, String str) { if (object instanceof Integer) { @@ -185,11 +172,11 @@ public class ChangString { private static Boolean BCHANG=false; /** * 遍历JSON对象 - * @param json - * @param key - * @param value - * @param keyindex - * @return + * @param json 原始json + * @param key 替换key + * @param value 替换值 + * @param keyindex 替换key索引 + * @return 返回json对象 */ public static JSONObject parseJsonString(String json,String key,String value,int keyindex){ LinkedHashMap jsonMap = JSON.parseObject(json, new TypeReference>(){}); @@ -201,14 +188,13 @@ public class ChangString { /** * 替换遍历后JSON对象中的KEY - * @param entry - * @param key - * @param value - * @param keyindex - * @return + * @param entry json对象转换成MAP + * @param key 待替换key + * @param value 替换值 + * @param keyindex 替换key索引 */ @SuppressWarnings("unchecked") - public static Map.Entry parseJsonMap(Map.Entry entry,String key,String value,int keyindex){ + public static void parseJsonMap(Entry entry, String key, String value, int keyindex){ //如果是字符串型的null直接把对象设置为对象null if("NULL".equals(value)){ value = null; @@ -273,6 +259,7 @@ public class ChangString { if(key.equals(entry.getKey())){ if(keyindex==COUNTER){ LogUtil.APP.info("对象原始Integer值:【{}】",entry.getValue()); + assert value != null; entry.setValue(Integer.valueOf(value)); LogUtil.APP.info("对象替换后Integer值:【{}】",entry.getValue()); BCHANG=true; @@ -285,6 +272,7 @@ public class ChangString { if(key.equals(entry.getKey())){ if(keyindex==COUNTER){ LogUtil.APP.info("对象原始Long值:【{}】",entry.getValue()); + assert value != null; entry.setValue(Long.valueOf(value)); LogUtil.APP.info("对象替换后Long值:【{}】",entry.getValue()); BCHANG=true; @@ -297,6 +285,7 @@ public class ChangString { if(key.equals(entry.getKey())){ if(keyindex==COUNTER){ LogUtil.APP.info("对象原始BigDecimal值:【{}】",entry.getValue()); + assert value != null; BigDecimal bd = new BigDecimal(value); entry.setValue(bd); LogUtil.APP.info("对象替换后BigDecimal值:【{}】",entry.getValue()); @@ -317,28 +306,27 @@ public class ChangString { COUNTER++; } } - - return entry; - } + + } /** * 替换json对象中指定KEY入口方法 - * @param json - * @param key - * @param value - * @param index - * @return + * @param json 待替换原始json + * @param key 替换key + * @param value 替换值 + * @param index 替换key索引 + * @return 返回替换后的MAP对象 */ public static Map changjson(String json, String key, String value,int index) { json=json.trim(); LogUtil.APP.info("原始JSON:【{}】,待替换JSON KEY:【{}】,待替换JSON VALUE:【{}】,待替换JSON KEY序号:【{}】",json,key,value,index); - Map map = new HashMap(0); + Map map = new HashMap<>(0); map.put("json", json); map.put("boolean", BCHANG.toString().toLowerCase()); if (json.startsWith("{") && json.endsWith("}")) { try { - JSONObject jsonStr = JSONObject.parseObject(json); + JSONObject jsonStr; jsonStr=parseJsonString(json,key,value,index); if (BCHANG) { LogUtil.APP.info("JSON字符串替换成功,新JSON:【{}】",jsonStr.toJSONString()); diff --git a/src/main/java/luckyclient/execution/dispose/ParamsManageForSteps.java b/src/main/java/luckyclient/execution/dispose/ParamsManageForSteps.java index 7659665..e44a81f 100644 --- a/src/main/java/luckyclient/execution/dispose/ParamsManageForSteps.java +++ b/src/main/java/luckyclient/execution/dispose/ParamsManageForSteps.java @@ -1,113 +1,113 @@ -package luckyclient.execution.dispose; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import luckyclient.utils.LogUtil; - -/** - * 对内置参数进行处理 - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull - * ================================================================= - * @author Seagull - * @date 2019年1月15日 - */ -public class ParamsManageForSteps { - public static Map GLOBAL_VARIABLE = new HashMap<>(0); - /** - * 进内置参数管理 - * @param params - * @return - * @author Seagull - * @date 2019年1月15日 - */ - public static String paramsManage(String params) { - ParamsManageForSteps pmfs = new ParamsManageForSteps(); - params = pmfs.replaceRandomInt(params); - params = pmfs.replaceTimeNow(params); - return params; - } - - /** - * 内置参数生成替换(生成随机整数) - * @param params - * @return - * @author Seagull - * @date 2019年1月15日 - */ - private String replaceRandomInt(String params) { - try { - String str="(?i)@\\{random\\[(\\d+)\\]\\[(\\d+)\\]\\}"; - Pattern pattern = Pattern.compile(str); - Matcher m = pattern.matcher(params); - while (m.find()) { - String matcherstr = m.group(0); - int startnum = Integer - .valueOf(matcherstr.substring(matcherstr.indexOf("[") + 1, matcherstr.indexOf("]")).trim()); - int endnum = Integer - .valueOf(matcherstr.substring(matcherstr.lastIndexOf("[") + 1, matcherstr.lastIndexOf("]")).trim()); - Random random = new Random(); - String replacement = String.valueOf(random.nextInt(endnum - startnum + 1) + startnum); - params = m.replaceFirst(replacement); - LogUtil.APP.info("Params({}):替换成随机数后,字符串:{}",matcherstr,params); - m = pattern.matcher(params); - } - return params; - } catch (IllegalArgumentException iae) { - LogUtil.APP.error("处理随机数字参数过程中出现异常,请检查数字区间是否正常!",iae); - return params; - } catch (Exception e) { - LogUtil.APP.error("处理随机数字参数过程中出现异常,请检查你的格式是否正确!",e); - return params; - } - } - - /** - * 内置参数生成替换(生成当时时间指定格式) - * @param params - * @return - * @author Seagull - * @date 2019年1月15日 - */ - private String replaceTimeNow(String params) { - try { - String str="(?i)@\\{timenow\\[(.*?)\\]\\}"; - Pattern pattern = Pattern.compile(str); - Matcher m = pattern.matcher(params); - while (m.find()) { - String matcherstr = m.group(0); - String formart = matcherstr.substring(matcherstr.indexOf("[") + 1, matcherstr.indexOf("]")).trim(); - SimpleDateFormat df = null; - try { - if("".equals(formart)||"timestamp".equals(formart.toLowerCase())){ - long time = System.currentTimeMillis(); - matcherstr=String.valueOf(time); - }else{ - df = new SimpleDateFormat(formart); - matcherstr=df.format(new Date()); - } - } catch (IllegalArgumentException iae) { - LogUtil.APP.error("处理随机数字参数过程中出现异常,请检查你的格式是否正确!",iae); - df = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss"); - matcherstr=df.format(new Date()); - } finally { - params = m.replaceFirst(matcherstr); - LogUtil.APP.info("Params({}):替换成随机数后,字符串:{}",matcherstr,params); - m = pattern.matcher(params); - } - } - return params; - } catch (Exception e) { - LogUtil.APP.error("处理随机数字参数过程中出现异常,请检查你的格式是否正确!",e); - return params; - } - } - -} +package luckyclient.execution.dispose; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import luckyclient.utils.LogUtil; + +/** + * 对内置参数进行处理 + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull + * ================================================================= + * @author Seagull + * @date 2019年1月15日 + */ +public class ParamsManageForSteps { + public static Map GLOBAL_VARIABLE = new HashMap<>(0); + /** + * 进内置参数管理 + * @param params 内置参数关键字 + * @return 返回参数处理结果 + * @author Seagull + * @date 2019年1月15日 + */ + public static String paramsManage(String params) { + ParamsManageForSteps pmfs = new ParamsManageForSteps(); + params = pmfs.replaceRandomInt(params); + params = pmfs.replaceTimeNow(params); + return params; + } + + /** + * 内置参数生成替换(生成随机整数) + * @param params 参数关键字 + * @return 返回随机数 + * @author Seagull + * @date 2019年1月15日 + */ + private String replaceRandomInt(String params) { + try { + String str="(?i)@\\{random\\[(\\d+)]\\[(\\d+)]}"; + Pattern pattern = Pattern.compile(str); + Matcher m = pattern.matcher(params); + while (m.find()) { + String matcherstr = m.group(0); + int startnum = Integer + .parseInt(matcherstr.substring(matcherstr.indexOf("[") + 1, matcherstr.indexOf("]")).trim()); + int endnum = Integer + .parseInt(matcherstr.substring(matcherstr.lastIndexOf("[") + 1, matcherstr.lastIndexOf("]")).trim()); + Random random = new Random(); + String replacement = String.valueOf(random.nextInt(endnum - startnum + 1) + startnum); + params = m.replaceFirst(replacement); + LogUtil.APP.info("Params({}):替换成随机数后,字符串:{}",matcherstr,params); + m = pattern.matcher(params); + } + return params; + } catch (IllegalArgumentException iae) { + LogUtil.APP.error("处理随机数字参数过程中出现异常,请检查数字区间是否正常!",iae); + return params; + } catch (Exception e) { + LogUtil.APP.error("处理随机数字参数过程中出现异常,请检查你的格式是否正确!",e); + return params; + } + } + + /** + * 内置参数生成替换(生成当时时间指定格式) + * @param params 参数关键字 + * @return 返回生成的参数 + * @author Seagull + * @date 2019年1月15日 + */ + private String replaceTimeNow(String params) { + try { + String str="(?i)@\\{timenow\\[(.*?)]}"; + Pattern pattern = Pattern.compile(str); + Matcher m = pattern.matcher(params); + while (m.find()) { + String matcherstr = m.group(0); + String formart = matcherstr.substring(matcherstr.indexOf("[") + 1, matcherstr.indexOf("]")).trim(); + SimpleDateFormat df; + try { + if("".equals(formart)||"timestamp".equals(formart.toLowerCase())){ + long time = System.currentTimeMillis(); + matcherstr=String.valueOf(time); + }else{ + df = new SimpleDateFormat(formart); + matcherstr=df.format(new Date()); + } + } catch (IllegalArgumentException iae) { + LogUtil.APP.error("处理随机数字参数过程中出现异常,请检查你的格式是否正确!",iae); + df = new SimpleDateFormat("yyyy-mm-dd hh:mm:ss"); + matcherstr=df.format(new Date()); + } finally { + params = m.replaceFirst(matcherstr); + LogUtil.APP.info("Params({}):替换成随机数后,字符串:{}",matcherstr,params); + m = pattern.matcher(params); + } + } + return params; + } catch (Exception e) { + LogUtil.APP.error("处理随机数字参数过程中出现异常,请检查你的格式是否正确!",e); + return params; + } + } + +} diff --git a/src/main/java/luckyclient/execution/dispose/actionkeyword/Action.java b/src/main/java/luckyclient/execution/dispose/actionkeyword/Action.java index 015c61b..fde8194 100644 --- a/src/main/java/luckyclient/execution/dispose/actionkeyword/Action.java +++ b/src/main/java/luckyclient/execution/dispose/actionkeyword/Action.java @@ -1,17 +1,17 @@ -package luckyclient.execution.dispose.actionkeyword; - -/** - * 动作关键字注解定义 - * @author: sunshaoyan - * @date: Created on 2019/4/13 - */ - -import java.lang.annotation.*; - -@Target(ElementType.TYPE) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -public @interface Action { - String name() default ""; -} +package luckyclient.execution.dispose.actionkeyword; + +import java.lang.annotation.*; + +/** + * 动作关键字注解定义 + * @author: sunshaoyan + * @date: Created on 2019/4/13 + */ + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface Action { + String name() default ""; +} diff --git a/src/main/java/luckyclient/execution/dispose/actionkeyword/ActionKeyWordParser.java b/src/main/java/luckyclient/execution/dispose/actionkeyword/ActionKeyWordParser.java index e891365..36fab81 100644 --- a/src/main/java/luckyclient/execution/dispose/actionkeyword/ActionKeyWordParser.java +++ b/src/main/java/luckyclient/execution/dispose/actionkeyword/ActionKeyWordParser.java @@ -1,19 +1,19 @@ -package luckyclient.execution.dispose.actionkeyword; - -/** - * 动作关键字的处理接口 - * @author: sunshaoyan - * @date: Created on 2019/4/13 - */ -public interface ActionKeyWordParser { - - /** - * 针对关键字的抽象方法 - * @param actionParams - * @param testResult - * @return - * @author Seagull - * @date 2019年8月8日 - */ - String parse(String actionParams, String testResult); -} +package luckyclient.execution.dispose.actionkeyword; + +/** + * 动作关键字的处理接口 + * @author: sunshaoyan + * @date: Created on 2019/4/13 + */ +public interface ActionKeyWordParser { + + /** + * 针对关键字的抽象方法 + * @param actionParams 关键字 + * @param testResult 待处理的测试结果 + * @return 返回处理结果 + * @author Seagull + * @date 2019年8月8日 + */ + String parse(String actionParams, String testResult); +} diff --git a/src/main/java/luckyclient/execution/dispose/actionkeyword/GetJsonActionParser.java b/src/main/java/luckyclient/execution/dispose/actionkeyword/GetJsonActionParser.java index 736a9ca..4ba2cb0 100644 --- a/src/main/java/luckyclient/execution/dispose/actionkeyword/GetJsonActionParser.java +++ b/src/main/java/luckyclient/execution/dispose/actionkeyword/GetJsonActionParser.java @@ -19,7 +19,7 @@ public class GetJsonActionParser implements ActionKeyWordParser { */ @Override public String parse(String actionParams, String testResult) { - String key=""; + String key; String index="1"; if(actionParams.endsWith("]")&&actionParams.contains("[")){ key=actionParams.substring(0,actionParams.indexOf("[")); diff --git a/src/main/java/luckyclient/execution/dispose/actionkeyword/HeaderParser.java b/src/main/java/luckyclient/execution/dispose/actionkeyword/HeaderParser.java index cb585fe..ab263cd 100644 --- a/src/main/java/luckyclient/execution/dispose/actionkeyword/HeaderParser.java +++ b/src/main/java/luckyclient/execution/dispose/actionkeyword/HeaderParser.java @@ -16,9 +16,9 @@ public class HeaderParser implements ActionKeyWordParser { /** * 动作关键字 - * @param actionParams - * @param testResult - * @return + * @param actionParams 关键字参数 + * @param testResult 待处理的测试结果 + * @return 返回处理结果 */ @Override public String parse(String actionParams, String testResult) { diff --git a/src/main/java/luckyclient/execution/dispose/actionkeyword/SubCentresStrActionParser.java b/src/main/java/luckyclient/execution/dispose/actionkeyword/SubCentresStrActionParser.java index ca505ed..f599492 100644 --- a/src/main/java/luckyclient/execution/dispose/actionkeyword/SubCentresStrActionParser.java +++ b/src/main/java/luckyclient/execution/dispose/actionkeyword/SubCentresStrActionParser.java @@ -19,8 +19,8 @@ public class SubCentresStrActionParser implements ActionKeyWordParser { */ @Override public String parse(String actionParams, String testResult) { - String startstr=""; - String endstr=""; + String startstr; + String endstr; if(actionParams.startsWith("[")&&actionParams.endsWith("]")){ startstr=actionParams.substring(actionParams.indexOf("[")+1, actionParams.indexOf("]")); endstr=actionParams.substring(actionParams.lastIndexOf("[")+1, actionParams.lastIndexOf("]")); diff --git a/src/main/java/luckyclient/execution/dispose/actionkeyword/SubStrRegxActionParser.java b/src/main/java/luckyclient/execution/dispose/actionkeyword/SubStrRegxActionParser.java index cde2035..5f26c53 100644 --- a/src/main/java/luckyclient/execution/dispose/actionkeyword/SubStrRegxActionParser.java +++ b/src/main/java/luckyclient/execution/dispose/actionkeyword/SubStrRegxActionParser.java @@ -19,7 +19,7 @@ public class SubStrRegxActionParser implements ActionKeyWordParser { */ @Override public String parse(String actionParams, String testResult) { - String key=""; + String key; String index="1"; if(actionParams.endsWith("]")&&actionParams.contains("[")){ key=actionParams.substring(0,actionParams.lastIndexOf("[")); diff --git a/src/main/java/luckyclient/execution/dispose/actionkeyword/ThreadWaitAction.java b/src/main/java/luckyclient/execution/dispose/actionkeyword/ThreadWaitAction.java index e6f8cd2..81478d2 100644 --- a/src/main/java/luckyclient/execution/dispose/actionkeyword/ThreadWaitAction.java +++ b/src/main/java/luckyclient/execution/dispose/actionkeyword/ThreadWaitAction.java @@ -15,9 +15,9 @@ public class ThreadWaitAction implements ActionKeyWordParser { /** * 动作关键字 - * @param actionParams - * @param testResult - * @return + * @param actionParams 关键字参数 + * @param testResult 待处理测试结果 + * @return 返回处理后结果 */ @Override public String parse(String actionParams, String testResult) { diff --git a/src/main/java/luckyclient/execution/httpinterface/ApiTestCaseDebug.java b/src/main/java/luckyclient/execution/httpinterface/ApiTestCaseDebug.java index 9766190..1a866ec 100644 --- a/src/main/java/luckyclient/execution/httpinterface/ApiTestCaseDebug.java +++ b/src/main/java/luckyclient/execution/httpinterface/ApiTestCaseDebug.java @@ -1,239 +1,230 @@ -package luckyclient.execution.httpinterface; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import luckyclient.execution.dispose.ActionManageForSteps; -import luckyclient.execution.httpinterface.analyticsteps.InterfaceAnalyticCase; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.InvokeMethod; -import luckyclient.utils.LogUtil; -import luckyclient.utils.httputils.HttpRequest; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @ClassName: TestCaseDebug - * @Description: 针对自动化用例在编写过程中,对用例脚本进行调试 @author: seagull - * @date 2018年3月1日 - * - */ -public class ApiTestCaseDebug { - private static final String ASSIGNMENT_SIGN = "$="; - private static final String FUZZY_MATCHING_SIGN = "%="; - private static final String REGULAR_MATCHING_SIGN = "~="; - - /** - * 用于在本地做单条用例调试 - * - * @param projectname - * @param testCaseExternalId - */ - public static void oneCaseDebug(String projectname, String testCaseExternalId) { - Map variable = new HashMap(0); - String packagename = null; - String functionname = null; - String expectedresults = null; - Integer setcaseresult = 0; - Object[] getParameterValues = null; - String testnote = "初始化测试结果"; - int k = 0; - ProjectCase testcase = GetServerApi.cgetCaseBysign(testCaseExternalId); - List pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); - // 把公共参数加入到MAP中 - for (ProjectCaseParams pcp : pcplist) { - variable.put(pcp.getParamsName(), pcp.getParamsValue()); - } - List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); - if (steps.size() == 0) { - setcaseresult = 2; - LogUtil.APP.warn("用例中未找到步骤,请检查!"); - testnote = "用例中未找到步骤,请检查!"; - } - // 进入循环,解析用例所有步骤 - for (int i = 0; i < steps.size(); i++) { - Map casescript = InterfaceAnalyticCase.analyticCaseStep(testcase, steps.get(i), "888888", - null,variable); - try { - packagename = casescript.get("PackageName").toString(); - functionname = casescript.get("FunctionName").toString(); - } catch (Exception e) { - k = 0; - LogUtil.APP.error("用例:{} 解析包名或是方法名失败,请检查!",testcase.getCaseSign(),e); - break; // 某一步骤失败后,此条用例置为失败退出 - } - // 用例名称解析出现异常或是单个步骤参数解析异常 - if (functionname.indexOf("解析异常") > -1 || k == 1) { - k = 0; - testnote = "用例第" + (i + 1) + "步解析出错啦!"; - break; - } - expectedresults = casescript.get("ExpectedResults").toString(); - // 判断方法是否带参数 - if (casescript.size() > 4) { - // 获取传入参数,放入对象中,初始化参数对象个数 - getParameterValues = new Object[casescript.size() - 4]; - for (int j = 0; j < casescript.size() - 4; j++) { - if (casescript.get("FunctionParams" + (j + 1)) == null) { - k = 1; - break; - } - String parameterValues = casescript.get("FunctionParams" + (j + 1)); - LogUtil.APP.info("用例:{} 解析包名:{} 方法名:{} 第{}个参数:{}",testcase.getCaseSign(),packagename,functionname,(j+1),parameterValues); - getParameterValues[j] = parameterValues; - } - } else { - getParameterValues = null; - } - // 调用动态方法,执行测试用例 - try { - LogUtil.APP.info("开始调用方法:{} .....",functionname); - testnote = InvokeMethod.callCase(packagename, functionname, getParameterValues, - steps.get(i).getStepType(), steps.get(i).getExtend()); - testnote = ActionManageForSteps.actionManage(casescript.get("Action"), testnote); - if (null != expectedresults && !expectedresults.isEmpty()) { - LogUtil.APP.info("expectedResults=【{}】",expectedresults); - // 赋值传参 - if (expectedresults.length() > ASSIGNMENT_SIGN.length() - && expectedresults.startsWith(ASSIGNMENT_SIGN)) { - variable.put(expectedresults.substring(ASSIGNMENT_SIGN.length()), testnote); - LogUtil.APP - .info("用例:{} 第{}步,将测试结果【{}】赋值给变量【{}】",testcase.getCaseSign(),(i+1),testnote,expectedresults.substring(ASSIGNMENT_SIGN.length())); - } - // 模糊匹配 - else if (expectedresults.length() > FUZZY_MATCHING_SIGN.length() - && expectedresults.startsWith(FUZZY_MATCHING_SIGN)) { - if (testnote.contains(expectedresults.substring(FUZZY_MATCHING_SIGN.length()))) { - LogUtil.APP.info( - "用例:{} 第{}步,模糊匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),(i+1),testnote); - } else { - setcaseresult = 1; - LogUtil.APP.warn("用例:{} 第{}步,模糊匹配预期结果失败!预期结果{},测试结果:{}",testcase.getCaseSign(),(i+1),expectedresults.substring(FUZZY_MATCHING_SIGN.length()),testnote); - testnote = "用例第" + (i + 1) + "步,模糊匹配预期结果失败!"; - if (testcase.getFailcontinue() == 0) { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); - break; - } else { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); - } - } - } - // 正则匹配 - else if (expectedresults.length() > REGULAR_MATCHING_SIGN.length() - && expectedresults.startsWith(REGULAR_MATCHING_SIGN)) { - Pattern pattern = Pattern.compile(expectedresults.substring(REGULAR_MATCHING_SIGN.length())); - Matcher matcher = pattern.matcher(testnote); - if (matcher.find()) { - LogUtil.APP.info( - "用例:{} 第{}步,正则匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),(i+1),testnote); - } else { - setcaseresult = 1; - LogUtil.APP.warn("用例:{} 第{}步,正则匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),(i+1),expectedresults.substring(REGULAR_MATCHING_SIGN.length()),testnote); - testnote = "用例第" + (i + 1) + "步,正则匹配预期结果失败!"; - if (testcase.getFailcontinue() == 0) { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); - break; - } else { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); - } - } - } - // 完全相等 - else { - if (expectedresults.equals(testnote)) { - LogUtil.APP.info( - "用例:{} 第{}步,精确匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),(i+1),testnote); - } else { - setcaseresult = 1; - LogUtil.APP.warn("用例:{} 第{}步,精确匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),(i+1),expectedresults,testnote); - testnote = "用例第" + (i + 1) + "步,精确匹配预期结果失败!"; - if (testcase.getFailcontinue() == 0) { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); - break; - } else { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); - } - } - } - } - } catch (Exception e) { - setcaseresult = 1; - LogUtil.APP.error("调用方法过程出错,方法名:{} 请重新检查脚本方法名称以及参数!",functionname,e); - testnote = "CallCase调用出错!"; - if (testcase.getFailcontinue() == 0) { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); - break; - } else { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); - } - } - } - variable.clear(); // 清空传参MAP - // 如果调用方法过程中未出错,进入设置测试结果流程 - if (testnote.indexOf("CallCase调用出错!") <= -1 && testnote.indexOf("解析出错啦!") <= -1) { - LogUtil.APP.info("用例{}解析成功,并成功调用用例中方法,请继续查看执行结果!",testCaseExternalId); - } else { - LogUtil.APP.warn("用例{}解析或是调用步骤中的方法出错!",testCaseExternalId); - } - if (0 == setcaseresult) { - LogUtil.APP.info("用例{}步骤全部执行成功!",testCaseExternalId); - } else { - LogUtil.APP.warn("用例{}在执行过程中失败,请检查日志!",testCaseExternalId); - } - } - - /** - * 用于在本地做多条用例串行调试 - * - * @param projectname - * @param addtestcase - */ - public static void moreCaseDebug(String projectname, List addtestcase) { - System.out.println("当前调试用例总共:"+addtestcase.size()); - for(String testCaseExternalId:addtestcase) { - try { - LogUtil.APP - .info("开始调用方法,项目名:{},用例编号:{}",projectname,testCaseExternalId); - oneCaseDebug(projectname, testCaseExternalId); - } catch (Exception e) { - LogUtil.APP.error("批量Debug用例出现异常!",e); - continue; - } - } - } - - /** - * 更新系统中用例指定步骤的预期结果 - */ - public static String setExpectedResults(String testCaseSign, int steps, String expectedResults) { - String results = "设置结果失败"; - String params = ""; - try { - expectedResults = expectedResults.replace("%", "BBFFHH"); - expectedResults = expectedResults.replace("=", "DHDHDH"); - expectedResults = expectedResults.replace("&", "ANDAND"); - params = "caseno=" + testCaseSign; - params += "&stepnum=" + steps; - params += "&expectedresults=" + expectedResults; - results = HttpRequest.sendPost("/projectCasesteps/cUpdateStepExpectedResults.do", params); - } catch (Exception e) { - LogUtil.APP.error("更新系统中用例指定步骤的预期结果出现异常!",e); - return "更新系统中用例指定步骤的预期结果出现异常!"; - } - return results; - - } - - public static void main(String[] args) throws Exception { - - } -} +package luckyclient.execution.httpinterface; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import luckyclient.execution.dispose.ActionManageForSteps; +import luckyclient.execution.httpinterface.analyticsteps.InterfaceAnalyticCase; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.InvokeMethod; +import luckyclient.utils.LogUtil; +import luckyclient.utils.httputils.HttpRequest; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @ClassName: TestCaseDebug + * @Description: 针对自动化用例在编写过程中,对用例脚本进行调试 @author: seagull + * @date 2018年3月1日 + * + */ +public class ApiTestCaseDebug { + private static final String ASSIGNMENT_SIGN = "$="; + private static final String FUZZY_MATCHING_SIGN = "%="; + private static final String REGULAR_MATCHING_SIGN = "~="; + + /** + * 用于在本地做单条用例调试 + * @param testCaseExternalId 用例编号 + */ + public static void oneCaseDebug(String testCaseExternalId) { + Map variable = new HashMap<>(0); + String packagename; + String functionname; + String expectedresults; + int setcaseresult = 0; + Object[] getParameterValues; + String testnote = "初始化测试结果"; + int k = 0; + ProjectCase testcase = GetServerApi.cgetCaseBysign(testCaseExternalId); + List pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); + // 把公共参数加入到MAP中 + for (ProjectCaseParams pcp : pcplist) { + variable.put(pcp.getParamsName(), pcp.getParamsValue()); + } + List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); + if (steps.size() == 0) { + setcaseresult = 2; + LogUtil.APP.warn("用例中未找到步骤,请检查!"); + testnote = "用例中未找到步骤,请检查!"; + } + // 进入循环,解析用例所有步骤 + for (int i = 0; i < steps.size(); i++) { + Map casescript = InterfaceAnalyticCase.analyticCaseStep(testcase, steps.get(i), "888888", + null,variable); + try { + packagename = casescript.get("PackageName"); + functionname = casescript.get("FunctionName"); + } catch (Exception e) { + LogUtil.APP.error("用例:{} 解析包名或是方法名失败,请检查!",testcase.getCaseSign(),e); + break; // 某一步骤失败后,此条用例置为失败退出 + } + // 用例名称解析出现异常或是单个步骤参数解析异常 + if (functionname.contains("解析异常") || k == 1) { + testnote = "用例第" + (i + 1) + "步解析出错啦!"; + break; + } + expectedresults = casescript.get("ExpectedResults"); + // 判断方法是否带参数 + if (casescript.size() > 4) { + // 获取传入参数,放入对象中,初始化参数对象个数 + getParameterValues = new Object[casescript.size() - 4]; + for (int j = 0; j < casescript.size() - 4; j++) { + if (casescript.get("FunctionParams" + (j + 1)) == null) { + k = 1; + break; + } + String parameterValues = casescript.get("FunctionParams" + (j + 1)); + LogUtil.APP.info("用例:{} 解析包名:{} 方法名:{} 第{}个参数:{}",testcase.getCaseSign(),packagename,functionname,(j+1),parameterValues); + getParameterValues[j] = parameterValues; + } + } else { + getParameterValues = null; + } + // 调用动态方法,执行测试用例 + try { + LogUtil.APP.info("开始调用方法:{} .....",functionname); + testnote = InvokeMethod.callCase(packagename, functionname, getParameterValues, + steps.get(i).getStepType(), steps.get(i).getExtend()); + testnote = ActionManageForSteps.actionManage(casescript.get("Action"), testnote); + if (null != expectedresults && !expectedresults.isEmpty()) { + LogUtil.APP.info("expectedResults=【{}】",expectedresults); + // 赋值传参 + if (expectedresults.length() > ASSIGNMENT_SIGN.length() + && expectedresults.startsWith(ASSIGNMENT_SIGN)) { + variable.put(expectedresults.substring(ASSIGNMENT_SIGN.length()), testnote); + LogUtil.APP + .info("用例:{} 第{}步,将测试结果【{}】赋值给变量【{}】",testcase.getCaseSign(),(i+1),testnote,expectedresults.substring(ASSIGNMENT_SIGN.length())); + } + // 模糊匹配 + else if (expectedresults.length() > FUZZY_MATCHING_SIGN.length() + && expectedresults.startsWith(FUZZY_MATCHING_SIGN)) { + if (testnote.contains(expectedresults.substring(FUZZY_MATCHING_SIGN.length()))) { + LogUtil.APP.info( + "用例:{} 第{}步,模糊匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),(i+1),testnote); + } else { + setcaseresult = 1; + LogUtil.APP.warn("用例:{} 第{}步,模糊匹配预期结果失败!预期结果{},测试结果:{}",testcase.getCaseSign(),(i+1),expectedresults.substring(FUZZY_MATCHING_SIGN.length()),testnote); + testnote = "用例第" + (i + 1) + "步,模糊匹配预期结果失败!"; + if (testcase.getFailcontinue() == 0) { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); + break; + } else { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); + } + } + } + // 正则匹配 + else if (expectedresults.length() > REGULAR_MATCHING_SIGN.length() + && expectedresults.startsWith(REGULAR_MATCHING_SIGN)) { + Pattern pattern = Pattern.compile(expectedresults.substring(REGULAR_MATCHING_SIGN.length())); + Matcher matcher = pattern.matcher(testnote); + if (matcher.find()) { + LogUtil.APP.info( + "用例:{} 第{}步,正则匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),(i+1),testnote); + } else { + setcaseresult = 1; + LogUtil.APP.warn("用例:{} 第{}步,正则匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),(i+1),expectedresults.substring(REGULAR_MATCHING_SIGN.length()),testnote); + testnote = "用例第" + (i + 1) + "步,正则匹配预期结果失败!"; + if (testcase.getFailcontinue() == 0) { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); + break; + } else { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); + } + } + } + // 完全相等 + else { + if (expectedresults.equals(testnote)) { + LogUtil.APP.info( + "用例:{} 第{}步,精确匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),(i+1),testnote); + } else { + setcaseresult = 1; + LogUtil.APP.warn("用例:{} 第{}步,精确匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),(i+1),expectedresults,testnote); + testnote = "用例第" + (i + 1) + "步,精确匹配预期结果失败!"; + if (testcase.getFailcontinue() == 0) { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); + break; + } else { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); + } + } + } + } + } catch (Exception e) { + setcaseresult = 1; + LogUtil.APP.error("调用方法过程出错,方法名:{} 请重新检查脚本方法名称以及参数!",functionname,e); + testnote = "CallCase调用出错!"; + if (testcase.getFailcontinue() == 0) { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); + break; + } else { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); + } + } + } + variable.clear(); // 清空传参MAP + // 如果调用方法过程中未出错,进入设置测试结果流程 + if (!testnote.contains("CallCase调用出错!") && !testnote.contains("解析出错啦!")) { + LogUtil.APP.info("用例{}解析成功,并成功调用用例中方法,请继续查看执行结果!",testCaseExternalId); + } else { + LogUtil.APP.warn("用例{}解析或是调用步骤中的方法出错!",testCaseExternalId); + } + if (0 == setcaseresult) { + LogUtil.APP.info("用例{}步骤全部执行成功!",testCaseExternalId); + } else { + LogUtil.APP.warn("用例{}在执行过程中失败,请检查日志!",testCaseExternalId); + } + } + + /** + * 用于在本地做多条用例串行调试 + * @param projectname 项目名称 + * @param addtestcase 用例集 + */ + public static void moreCaseDebug(String projectname, List addtestcase) { + System.out.println("当前调试用例总共:"+addtestcase.size()); + for(String testCaseExternalId:addtestcase) { + try { + LogUtil.APP + .info("开始调用方法,项目名:{},用例编号:{}",projectname,testCaseExternalId); + oneCaseDebug(testCaseExternalId); + } catch (Exception e) { + LogUtil.APP.error("批量Debug用例出现异常!",e); + } + } + } + + /** + * 更新系统中用例指定步骤的预期结果 + */ + public static String setExpectedResults(String testCaseSign, int steps, String expectedResults) { + String results; + String params; + try { + expectedResults = expectedResults.replace("%", "BBFFHH"); + expectedResults = expectedResults.replace("=", "DHDHDH"); + expectedResults = expectedResults.replace("&", "ANDAND"); + params = "caseno=" + testCaseSign; + params += "&stepnum=" + steps; + params += "&expectedresults=" + expectedResults; + results = HttpRequest.sendPost("/projectCasesteps/cUpdateStepExpectedResults.do", params); + } catch (Exception e) { + LogUtil.APP.error("更新系统中用例指定步骤的预期结果出现异常!",e); + return "更新系统中用例指定步骤的预期结果出现异常!"; + } + return results; + + } + +} diff --git a/src/main/java/luckyclient/execution/httpinterface/BatchTestCaseExecution.java b/src/main/java/luckyclient/execution/httpinterface/BatchTestCaseExecution.java index b128f61..9ab15d1 100644 --- a/src/main/java/luckyclient/execution/httpinterface/BatchTestCaseExecution.java +++ b/src/main/java/luckyclient/execution/httpinterface/BatchTestCaseExecution.java @@ -25,33 +25,32 @@ public class BatchTestCaseExecution { /** * 创建线程池,多线程执行用例 - * @param projectname - * @param taskid - * @param batchcase - * @throws Exception + * @param taskid 任务ID + * @param batchcase 批量用例字符串,#隔断 + * @throws Exception 抛异常 */ - public static void batchCaseExecuteForTast(String projectname,String taskid,String batchcase) throws Exception{ - int threadcount = GetServerApi.cGetTaskSchedulingByTaskId(Integer.valueOf(taskid)).getExThreadCount(); + public static void batchCaseExecuteForTast(String taskid, String batchcase) throws Exception{ + int threadcount = GetServerApi.cGetTaskSchedulingByTaskId(Integer.parseInt(taskid)).getExThreadCount(); ThreadPoolExecutor threadExecute = new ThreadPoolExecutor(threadcount, 30, 3, TimeUnit.SECONDS, - new ArrayBlockingQueue(1000), + new ArrayBlockingQueue<>(1000), new ThreadPoolExecutor.CallerRunsPolicy()); //执行全部非成功状态用例 - if(batchcase.indexOf("ALLFAIL")>-1){ + if(batchcase.contains("ALLFAIL")){ //初始化写用例结果以及日志模块 serverOperation caselog = new serverOperation(); List caseIdList = caselog.getCaseListForUnSucByTaskId(taskid); - for(int i=0;i VARIABLE = new HashMap(0); - - /** - * @param projectname 项目名 - * @param testCaseExternalId 用例编号 - * @param version 用例版本号 - * 用于单条用例调试,并通过日志框架写日志到UTP上,用做UTP上单条用例运行 - */ - public void oneCaseExecuteForTask(String projectname, Integer caseId, String taskid) { - TestControl.TASKID = taskid; - serverOperation.exetype = 0; - // 初始化写用例结果以及日志模块 - serverOperation caselog = new serverOperation(); - String packagename = null; - String functionname = null; - String expectedresults = null; - Integer setcaseresult = 0; - Object[] getParameterValues = null; - String testnote = "初始化测试结果"; - int k = 0; - ProjectCase testcase = GetServerApi.cGetCaseByCaseId(caseId); - //更新用例状态 - caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), 3); - // 删除旧的日志 - serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); - - List pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); - // 把公共参数加入到MAP中 - for (ProjectCaseParams pcp : pcplist) { - VARIABLE.put(pcp.getParamsName(), pcp.getParamsValue()); - } - // 加入全局变量 - VARIABLE.putAll(ParamsManageForSteps.GLOBAL_VARIABLE); - List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); - if (steps.size() == 0) { - setcaseresult = 2; - LogUtil.APP.warn("用例中未找到步骤,请检查!"); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例中未找到步骤,请检查!", "error", "1", ""); - testnote = "用例中未找到步骤,请检查!"; - } - // 进入循环,解析用例所有步骤 - for (int i = 0; i < steps.size(); i++) { - Map casescript = InterfaceAnalyticCase.analyticCaseStep(testcase, steps.get(i), taskid, caselog,VARIABLE); - try { - packagename = casescript.get("PackageName"); - functionname = casescript.get("FunctionName"); - } catch (Exception e) { - k = 0; - LogUtil.APP.error("用例:{} 解析包名或是方法名失败,请检查!",testcase.getCaseSign(),e); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "解析包名或是方法名失败,请检查!", "error", String.valueOf(i + 1), ""); - break; // 某一步骤失败后,此条用例置为失败退出 - } - // 用例名称解析出现异常或是单个步骤参数解析异常 - if ((null != functionname && functionname.contains("解析异常")) || k == 1) { - k = 0; - testnote = "用例第" + (i + 1) + "步解析出错啦!"; - break; - } - expectedresults = casescript.get("ExpectedResults"); - // 判断方法是否带参数 - if (casescript.size() > 4) { - // 获取传入参数,放入对象中,初始化参数对象个数 - getParameterValues = new Object[casescript.size() - 4]; - for (int j = 0; j < casescript.size() - 4; j++) { - if (casescript.get("FunctionParams" + (j + 1)) == null) { - k = 1; - break; - } - - String parameterValues = casescript.get("FunctionParams" + (j + 1)); - LogUtil.APP.info("用例:{} 解析包名:{} 方法名:{} 第{}个参数:{}",testcase.getCaseSign(),packagename,functionname,(j+1),parameterValues); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "解析包名:" + packagename + " 方法名:" + functionname + " 第" + (j + 1) + "个参数:" + parameterValues, "info", String.valueOf(i + 1), ""); - getParameterValues[j] = parameterValues; - } - } else { - getParameterValues = null; - } - // 调用动态方法,执行测试用例 - try { - LogUtil.APP.info("开始调用方法:{} .....",functionname); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "开始调用方法:" + functionname + " .....", "info", String.valueOf(i + 1), ""); - testnote = InvokeMethod.callCase(packagename, functionname, getParameterValues, steps.get(i).getStepType(), steps.get(i).getExtend()); - testnote = ActionManageForSteps.actionManage(casescript.get("Action"), testnote); - // 判断结果 - int stepresult = interfaceJudgeResult(testcase, steps.get(i), taskid, expectedresults, testnote, caselog); - // 失败,并且不在继续,直接终止 - if (0 != stepresult) { - setcaseresult = stepresult; - if (testcase.getFailcontinue() == 0) { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),steps.get(i).getStepSerialNumber()); - break; - } else { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),steps.get(i).getStepSerialNumber()); - } - } - - } catch (Exception e) { - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "调用方法过程出错,方法名:" + functionname + " 请重新检查脚本方法名称以及参数!", "error", String.valueOf(i + 1), ""); - LogUtil.APP.error("调用方法过程出错,方法名:{} 请重新检查脚本方法名称以及参数!",functionname, e); - testnote = "CallCase调用出错!"; - setcaseresult = 1; - e.printStackTrace(); - if (testcase.getFailcontinue() == 0) { - LogUtil.APP.error("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); - break; - } else { - LogUtil.APP.error("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); - } - } - } - - VARIABLE.clear(); // 清空传参MAP - // 如果调用方法过程中未出错,进入设置测试结果流程 - if (!testnote.contains("CallCase调用出错!") && !testnote.contains("解析出错啦!")) { - LogUtil.APP.info("用例{}解析成功,并成功调用用例中方法,请继续查看执行结果!",testcase.getCaseSign()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "解析成功,并成功调用用例中方法,请继续查看执行结果!", "info", "SETCASERESULT...", ""); - caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), setcaseresult); - } else { - setcaseresult = 1; - LogUtil.APP.warn("用例{}解析或是调用步骤中的方法出错!",testcase.getCaseSign()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "解析或是调用步骤中的方法出错!", "error", "SETCASERESULT...", ""); - caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), 2); - } - if (0 == setcaseresult) { - LogUtil.APP.info("用例{}步骤全部执行成功!",testcase.getCaseSign()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "步骤全部执行成功!", "info", "EXECUTECASESUC...", ""); - } else { - LogUtil.APP.warn("用例{}在执行过程中失败,请检查日志!",testcase.getCaseSign()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在执行过程中失败,请检查日志!", "error", "EXECUTECASESUC...", ""); - } - serverOperation.updateTaskExecuteData(taskid, 0, 2); - } - - /** - * - * @param testCaseExternalId - * @param taskid - * @param caselog - * @param driver - * @return - * @throws InterruptedException - * 提供给Web用例中,runcase的时候使用 - */ - @SuppressWarnings("unchecked") - public String oneCaseExecuteForUICase(String testCaseExternalId, String taskid, serverOperation caselog, Object driver) throws InterruptedException { - String expectedresults = null; - Integer setresult = 1; - String testnote = "初始化测试结果"; - ProjectCase testcase = GetServerApi.cgetCaseBysign(testCaseExternalId); - List pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); - // 把公共参数加入到MAP中 - for (ProjectCaseParams pcp : pcplist) { - VARIABLE.put(pcp.getParamsName(), pcp.getParamsValue()); - } - // 加入全局变量 - VARIABLE.putAll(ParamsManageForSteps.GLOBAL_VARIABLE); - List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); - if (steps.size() == 0) { - setresult = 2; - LogUtil.APP.warn("用例中未找到步骤,请检查!"); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例中未找到步骤,请检查!", "error", "1", ""); - testnote = "用例中未找到步骤,请检查!"; - } - - // 进入循环,解析用例所有步骤 - for (ProjectCaseSteps step : steps) { - Map params; - - // 根据步骤类型来分析步骤参数 - if (1 == step.getStepType()){ - params = WebDriverAnalyticCase.analyticCaseStep(testcase, step, taskid, caselog,VARIABLE); - }else if (3 == step.getStepType()){ - params = AppDriverAnalyticCase.analyticCaseStep(testcase, step, taskid,caselog,VARIABLE); - } else{ - params = InterfaceAnalyticCase.analyticCaseStep(testcase, step, taskid, caselog,VARIABLE); - } - - // 判断分析步骤参数是否有异常 - if (params.get("exception") != null && params.get("exception").contains("解析异常")) { - setresult = 2; - break; - } - - expectedresults = params.get("ExpectedResults"); - - // 根据步骤类型来执行步骤 - if (1 == step.getStepType()){ - WebDriver wd=(WebDriver)driver; - testnote = WebCaseExecution.runWebStep(params, wd, taskid, testcase.getCaseId(), step.getStepSerialNumber(), caselog); - // 判断结果 - setresult = WebCaseExecution.judgeResult(testcase, step, params, wd, taskid, expectedresults, testnote, caselog); - }else if (3 == step.getStepType()){ - if (driver instanceof AndroidDriver){ - AndroidDriver ad=(AndroidDriver)driver; - testnote = AndroidCaseExecution.androidRunStep(params, ad, taskid, testcase.getCaseId(), step.getStepSerialNumber(), caselog); - // 判断结果 - setresult = AndroidCaseExecution.judgeResult(testcase, step, params, ad, taskid, expectedresults, testnote, caselog); - }else{ - IOSDriver ios=(IOSDriver)driver; - testnote = IosCaseExecution.iosRunStep(params, VARIABLE, ios, taskid, testcase.getCaseId(), step.getStepSerialNumber(), caselog); - // 判断结果 - setresult = IosCaseExecution.judgeResult(testcase, step, params, ios, taskid, expectedresults, testnote, caselog); - } - - } else{ - testnote = runStep(params, taskid, testcase.getCaseSign(), step, caselog); - // 判断结果 - setresult = interfaceJudgeResult(testcase, step, taskid, expectedresults, testnote, caselog); - } - - if (0 != setresult){ - testnote = "【调用用例:"+testcase.getCaseSign()+" 第"+step.getStepSerialNumber()+"步在执行过程中失败】"; - LogUtil.APP.warn("调用用例:{} 第{}步在执行过程中失败,请检查日志!{}",testcase.getCaseSign(),step.getStepSerialNumber(),testnote); - break; - } - } - - VARIABLE.clear(); // 清空传参MAP - if (0 == setresult) { - LogUtil.APP.info("调用用例:{}步骤全部执行成功!",testcase.getCaseSign()); - } - - return testnote; - } - - /** - * 其他类型测试用例中调用接口测试步骤 - * @param params - * @param variable - * @param taskid - * @param casenum - * @param step - * @param caselog - * @return - */ - public String runStep(Map params, String taskid, String casenum, ProjectCaseSteps step, serverOperation caselog) { - String result = ""; - String packagename = ""; - String functionname = ""; - Object[] getParameterValues = null; - ProjectCase projectCase = GetServerApi.cgetCaseBysign(casenum); - try { - packagename = params.get("PackageName"); - functionname = params.get("FunctionName"); - - if (null != functionname && functionname.contains("解析异常")) { - LogUtil.APP.warn("用例:{}, 解析这个方法【{}】失败!",casenum,functionname); - caselog.insertTaskCaseLog(taskid, projectCase.getCaseId(), "用例: " + casenum + ", 解析这个方法【" + functionname + "】失败!", "error", String.valueOf(step.getStepSerialNumber()), ""); - result = "步骤执行失败:解析用例失败!"; - } else { - // 判断方法是否带参数 - if (params.size() > 4) { - // 获取传入参数,放入对象中 - getParameterValues = new Object[params.size() - 4]; - for (int j = 0; j < params.size() - 4; j++) { - if (params.get("FunctionParams" + (j + 1)) == null) { - break; - } - String parameterValues = params.get("FunctionParams" + (j + 1)); - LogUtil.APP.info("用例:{}, 解析包路径:{}; 方法名:{} 第{}个参数:{}",casenum,packagename,functionname,(j+1),parameterValues); - caselog.insertTaskCaseLog(taskid, projectCase.getCaseId(), "用例: " + casenum + ", 解析包名:" + packagename + " 方法名:" + functionname + " 第" + (j + 1) + "个参数:" + parameterValues, "info", String.valueOf(step.getStepSerialNumber()), ""); - getParameterValues[j] = parameterValues; - } - } else { - getParameterValues = null; - } - - LogUtil.APP.info("二次解析用例过程完成,等待进行接口操作......"); - caselog.insertTaskCaseLog(taskid, projectCase.getCaseId(), "包路径: " + packagename + "; 方法名: " + functionname, "info", String.valueOf(step.getStepSerialNumber()), ""); - - result = InvokeMethod.callCase(packagename, functionname, getParameterValues, step.getStepType(), step.getExtend()); - } - } catch (Exception e) { - LogUtil.APP.error("调用方法过程出错,方法名:{},请重新检查脚本方法名称以及参数!",functionname,e); - result = "步骤执行失败:接口调用出错!"; - } - if (result.contains("步骤执行失败:")){ - caselog.insertTaskCaseLog(taskid, projectCase.getCaseId(), result, "error", String.valueOf(step.getStepSerialNumber()), ""); - } else{ - caselog.insertTaskCaseLog(taskid, projectCase.getCaseId(), result, "info", String.valueOf(step.getStepSerialNumber()), ""); - } - return result; - } - - private int interfaceJudgeResult(ProjectCase testcase, ProjectCaseSteps step, String taskid, String expectedresults, String testnote, serverOperation caselog){ - int setresult = 0; - try{ - if (null != expectedresults && !expectedresults.isEmpty()) { - LogUtil.APP.info("expectedResults=【{}】",expectedresults); - // 赋值传参 - if (expectedresults.length() > Constants.ASSIGNMENT_SIGN.length() && expectedresults.startsWith(Constants.ASSIGNMENT_SIGN)) { - VARIABLE.put(expectedresults.substring(Constants.ASSIGNMENT_SIGN.length()), testnote); - LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),testnote,expectedresults.substring(Constants.ASSIGNMENT_SIGN.length())); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + testnote + "】赋值给变量【" + expectedresults.substring(Constants.ASSIGNMENT_SIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); - } - // 赋值全局变量 - else if (expectedresults.length() > Constants.ASSIGNMENT_GLOBALSIGN.length() && expectedresults.startsWith(Constants.ASSIGNMENT_GLOBALSIGN)) { - VARIABLE.put(expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), testnote); - ParamsManageForSteps.GLOBAL_VARIABLE.put(expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), testnote); - LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给全局变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),testnote,expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length())); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + testnote + "】赋值给全局变量【" + expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); - } - // 模糊匹配 - else if (expectedresults.length() > Constants.FUZZY_MATCHING_SIGN.length() && expectedresults.startsWith(Constants.FUZZY_MATCHING_SIGN)) { - if (testnote.contains(expectedresults.substring(Constants.FUZZY_MATCHING_SIGN.length()))) { - LogUtil.APP.info("用例:{} 第{}步,模糊匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),testnote); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果成功!执行结果:" + testnote, "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - setresult = 1; - LogUtil.APP.warn("用例:{} 第{}步,模糊匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expectedresults.substring(Constants.FUZZY_MATCHING_SIGN.length()),testnote); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果失败!预期结果:" + expectedresults.substring(Constants.FUZZY_MATCHING_SIGN.length()) + ",测试结果:" + testnote, "error", String.valueOf(step.getStepSerialNumber()), ""); - testnote = "用例第" + step.getStepSerialNumber() + "步,模糊匹配预期结果失败!"; - } - } - // 正则匹配 - else if (expectedresults.length() > Constants.REGULAR_MATCHING_SIGN.length() && expectedresults.startsWith(Constants.REGULAR_MATCHING_SIGN)) { - Pattern pattern = Pattern.compile(expectedresults.substring(Constants.REGULAR_MATCHING_SIGN.length())); - Matcher matcher = pattern.matcher(testnote); - if (matcher.find()) { - LogUtil.APP.info("用例:{} 第{}步,正则匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),testnote); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果成功!执行结果:" + testnote, "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - setresult = 1; - LogUtil.APP.warn("用例:{} 第{}步,正则匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expectedresults.substring(Constants.REGULAR_MATCHING_SIGN.length()),testnote); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果失败!预期结果:" + expectedresults.substring(Constants.REGULAR_MATCHING_SIGN.length()) + ",测试结果:" + testnote, "error", String.valueOf(step.getStepSerialNumber()), ""); - testnote = "用例第" + step.getStepSerialNumber() + "步,正则匹配预期结果失败!"; - } - } - //jsonpath断言 - else if (expectedresults.length() > Constants.JSONPATH_SIGN.length() && expectedresults.startsWith(Constants.JSONPATH_SIGN)) { - expectedresults = expectedresults.substring(Constants.JSONPATH_SIGN.length()); - String expression = expectedresults.split("(? VARIABLE = new HashMap<>(0); + + /** + * 用于单条用例调试,并通过日志框架写日志到UTP上,用做UTP上单条用例运行 + */ + public void oneCaseExecuteForTask(Integer caseId, String taskid) { + TestControl.TASKID = taskid; + serverOperation.exetype = 0; + // 初始化写用例结果以及日志模块 + serverOperation caselog = new serverOperation(); + String packagename; + String functionname; + String expectedresults; + int setcaseresult = 0; + Object[] getParameterValues; + String testnote = "初始化测试结果"; + int k = 0; + ProjectCase testcase = GetServerApi.cGetCaseByCaseId(caseId); + //更新用例状态 + caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), 3); + // 删除旧的日志 + serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); + + List pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); + // 把公共参数加入到MAP中 + for (ProjectCaseParams pcp : pcplist) { + VARIABLE.put(pcp.getParamsName(), pcp.getParamsValue()); + } + // 加入全局变量 + VARIABLE.putAll(ParamsManageForSteps.GLOBAL_VARIABLE); + List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); + if (steps.size() == 0) { + setcaseresult = 2; + LogUtil.APP.warn("用例中未找到步骤,请检查!"); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例中未找到步骤,请检查!", "error", "1", ""); + testnote = "用例中未找到步骤,请检查!"; + } + // 进入循环,解析用例所有步骤 + for (int i = 0; i < steps.size(); i++) { + Map casescript = InterfaceAnalyticCase.analyticCaseStep(testcase, steps.get(i), taskid, caselog,VARIABLE); + try { + packagename = casescript.get("PackageName"); + functionname = casescript.get("FunctionName"); + } catch (Exception e) { + LogUtil.APP.error("用例:{} 解析包名或是方法名失败,请检查!",testcase.getCaseSign(),e); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "解析包名或是方法名失败,请检查!", "error", String.valueOf(i + 1), ""); + break; // 某一步骤失败后,此条用例置为失败退出 + } + // 用例名称解析出现异常或是单个步骤参数解析异常 + if ((null != functionname && functionname.contains("解析异常")) || k == 1) { + testnote = "用例第" + (i + 1) + "步解析出错啦!"; + break; + } + expectedresults = casescript.get("ExpectedResults"); + // 判断方法是否带参数 + if (casescript.size() > 4) { + // 获取传入参数,放入对象中,初始化参数对象个数 + getParameterValues = new Object[casescript.size() - 4]; + for (int j = 0; j < casescript.size() - 4; j++) { + if (casescript.get("FunctionParams" + (j + 1)) == null) { + k = 1; + break; + } + + String parameterValues = casescript.get("FunctionParams" + (j + 1)); + LogUtil.APP.info("用例:{} 解析包名:{} 方法名:{} 第{}个参数:{}",testcase.getCaseSign(),packagename,functionname,(j+1),parameterValues); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "解析包名:" + packagename + " 方法名:" + functionname + " 第" + (j + 1) + "个参数:" + parameterValues, "info", String.valueOf(i + 1), ""); + getParameterValues[j] = parameterValues; + } + } else { + getParameterValues = null; + } + // 调用动态方法,执行测试用例 + try { + LogUtil.APP.info("开始调用方法:{} .....",functionname); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "开始调用方法:" + functionname + " .....", "info", String.valueOf(i + 1), ""); + testnote = InvokeMethod.callCase(packagename, functionname, getParameterValues, steps.get(i).getStepType(), steps.get(i).getExtend()); + testnote = ActionManageForSteps.actionManage(casescript.get("Action"), testnote); + // 判断结果 + int stepresult = interfaceJudgeResult(testcase, steps.get(i), taskid, expectedresults, testnote, caselog); + // 失败,并且不在继续,直接终止 + if (0 != stepresult) { + setcaseresult = stepresult; + if (testcase.getFailcontinue() == 0) { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),steps.get(i).getStepSerialNumber()); + break; + } else { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),steps.get(i).getStepSerialNumber()); + } + } + + } catch (Exception e) { + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "调用方法过程出错,方法名:" + functionname + " 请重新检查脚本方法名称以及参数!", "error", String.valueOf(i + 1), ""); + LogUtil.APP.error("调用方法过程出错,方法名:{} 请重新检查脚本方法名称以及参数!",functionname, e); + testnote = "CallCase调用出错!"; + setcaseresult = 1; + e.printStackTrace(); + if (testcase.getFailcontinue() == 0) { + LogUtil.APP.error("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); + break; + } else { + LogUtil.APP.error("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); + } + } + } + + VARIABLE.clear(); // 清空传参MAP + // 如果调用方法过程中未出错,进入设置测试结果流程 + if (!testnote.contains("CallCase调用出错!") && !testnote.contains("解析出错啦!")) { + LogUtil.APP.info("用例{}解析成功,并成功调用用例中方法,请继续查看执行结果!",testcase.getCaseSign()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "解析成功,并成功调用用例中方法,请继续查看执行结果!", "info", "SETCASERESULT...", ""); + caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), setcaseresult); + } else { + setcaseresult = 1; + LogUtil.APP.warn("用例{}解析或是调用步骤中的方法出错!",testcase.getCaseSign()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "解析或是调用步骤中的方法出错!", "error", "SETCASERESULT...", ""); + caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), 2); + } + if (0 == setcaseresult) { + LogUtil.APP.info("用例{}步骤全部执行成功!",testcase.getCaseSign()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "步骤全部执行成功!", "info", "EXECUTECASESUC...", ""); + } else { + LogUtil.APP.warn("用例{}在执行过程中失败,请检查日志!",testcase.getCaseSign()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在执行过程中失败,请检查日志!", "error", "EXECUTECASESUC...", ""); + } + serverOperation.updateTaskExecuteData(taskid, 0, 2); + } + + /** + * 提供给Web用例中,runcase的时候使用 + * @param testCaseExternalId 用例编号 + * @param taskid 任务ID + * @param caselog 用例日志对象 + * @param driver UI驱动 + * @return 返回执行结果 + */ + @SuppressWarnings("unchecked") + public String oneCaseExecuteForUICase(String testCaseExternalId, String taskid, serverOperation caselog, Object driver) throws InterruptedException { + String expectedresults; + int setresult = 1; + String testnote = "初始化测试结果"; + ProjectCase testcase = GetServerApi.cgetCaseBysign(testCaseExternalId); + List pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); + // 把公共参数加入到MAP中 + for (ProjectCaseParams pcp : pcplist) { + VARIABLE.put(pcp.getParamsName(), pcp.getParamsValue()); + } + // 加入全局变量 + VARIABLE.putAll(ParamsManageForSteps.GLOBAL_VARIABLE); + List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); + if (steps.size() == 0) { + setresult = 2; + LogUtil.APP.warn("用例中未找到步骤,请检查!"); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例中未找到步骤,请检查!", "error", "1", ""); + testnote = "用例中未找到步骤,请检查!"; + } + + // 进入循环,解析用例所有步骤 + for (ProjectCaseSteps step : steps) { + Map params; + + // 根据步骤类型来分析步骤参数 + if (1 == step.getStepType()){ + params = WebDriverAnalyticCase.analyticCaseStep(testcase, step, taskid, caselog,VARIABLE); + }else if (3 == step.getStepType()){ + params = AppDriverAnalyticCase.analyticCaseStep(testcase, step, taskid,caselog,VARIABLE); + } else{ + params = InterfaceAnalyticCase.analyticCaseStep(testcase, step, taskid, caselog,VARIABLE); + } + + // 判断分析步骤参数是否有异常 + if (params.get("exception") != null && params.get("exception").contains("解析异常")) { + setresult = 2; + break; + } + + expectedresults = params.get("ExpectedResults"); + + // 根据步骤类型来执行步骤 + if (1 == step.getStepType()){ + WebDriver wd=(WebDriver)driver; + testnote = WebCaseExecution.runWebStep(params, wd, taskid, testcase.getCaseId(), step.getStepSerialNumber(), caselog); + // 判断结果 + setresult = WebCaseExecution.judgeResult(testcase, step, params, wd, taskid, expectedresults, testnote, caselog); + }else if (3 == step.getStepType()){ + if (driver instanceof AndroidDriver){ + AndroidDriver ad=(AndroidDriver)driver; + testnote = AndroidCaseExecution.androidRunStep(params, ad, taskid, testcase.getCaseId(), step.getStepSerialNumber(), caselog); + // 判断结果 + setresult = AndroidCaseExecution.judgeResult(testcase, step, params, ad, taskid, expectedresults, testnote, caselog); + }else{ + IOSDriver ios=(IOSDriver)driver; + testnote = IosCaseExecution.iosRunStep(params, VARIABLE, ios, taskid, testcase.getCaseId(), step.getStepSerialNumber(), caselog); + // 判断结果 + setresult = IosCaseExecution.judgeResult(testcase, step, params, ios, taskid, expectedresults, testnote, caselog); + } + + } else{ + testnote = runStep(params, taskid, testcase.getCaseSign(), step, caselog); + // 判断结果 + setresult = interfaceJudgeResult(testcase, step, taskid, expectedresults, testnote, caselog); + } + + if (0 != setresult){ + testnote = "【调用用例:"+testcase.getCaseSign()+" 第"+step.getStepSerialNumber()+"步在执行过程中失败】"; + LogUtil.APP.warn("调用用例:{} 第{}步在执行过程中失败,请检查日志!{}",testcase.getCaseSign(),step.getStepSerialNumber(),testnote); + break; + } + } + + VARIABLE.clear(); // 清空传参MAP + if (0 == setresult) { + LogUtil.APP.info("调用用例:{}步骤全部执行成功!",testcase.getCaseSign()); + } + + return testnote; + } + + /** + * 其他类型测试用例中调用接口测试步骤 + * @param params 参数 + * @param taskid 任务ID + * @param casenum 用例编号 + * @param step 步骤对象 + * @param caselog 日志对象 + * @return 返回执行结果 + */ + public String runStep(Map params, String taskid, String casenum, ProjectCaseSteps step, serverOperation caselog) { + String result; + String packagename; + String functionname = ""; + Object[] getParameterValues; + ProjectCase projectCase = GetServerApi.cgetCaseBysign(casenum); + try { + packagename = params.get("PackageName"); + functionname = params.get("FunctionName"); + + if (null != functionname && functionname.contains("解析异常")) { + LogUtil.APP.warn("用例:{}, 解析这个方法【{}】失败!",casenum,functionname); + caselog.insertTaskCaseLog(taskid, projectCase.getCaseId(), "用例: " + casenum + ", 解析这个方法【" + functionname + "】失败!", "error", String.valueOf(step.getStepSerialNumber()), ""); + result = "步骤执行失败:解析用例失败!"; + } else { + // 判断方法是否带参数 + if (params.size() > 4) { + // 获取传入参数,放入对象中 + getParameterValues = new Object[params.size() - 4]; + for (int j = 0; j < params.size() - 4; j++) { + if (params.get("FunctionParams" + (j + 1)) == null) { + break; + } + String parameterValues = params.get("FunctionParams" + (j + 1)); + LogUtil.APP.info("用例:{}, 解析包路径:{}; 方法名:{} 第{}个参数:{}",casenum,packagename,functionname,(j+1),parameterValues); + caselog.insertTaskCaseLog(taskid, projectCase.getCaseId(), "用例: " + casenum + ", 解析包名:" + packagename + " 方法名:" + functionname + " 第" + (j + 1) + "个参数:" + parameterValues, "info", String.valueOf(step.getStepSerialNumber()), ""); + getParameterValues[j] = parameterValues; + } + } else { + getParameterValues = null; + } + + LogUtil.APP.info("二次解析用例过程完成,等待进行接口操作......"); + caselog.insertTaskCaseLog(taskid, projectCase.getCaseId(), "包路径: " + packagename + "; 方法名: " + functionname, "info", String.valueOf(step.getStepSerialNumber()), ""); + + result = InvokeMethod.callCase(packagename, functionname, getParameterValues, step.getStepType(), step.getExtend()); + } + } catch (Exception e) { + LogUtil.APP.error("调用方法过程出错,方法名:{},请重新检查脚本方法名称以及参数!",functionname,e); + result = "步骤执行失败:接口调用出错!"; + } + if (result.contains("步骤执行失败:")){ + caselog.insertTaskCaseLog(taskid, projectCase.getCaseId(), result, "error", String.valueOf(step.getStepSerialNumber()), ""); + } else{ + caselog.insertTaskCaseLog(taskid, projectCase.getCaseId(), result, "info", String.valueOf(step.getStepSerialNumber()), ""); + } + return result; + } + + private int interfaceJudgeResult(ProjectCase testcase, ProjectCaseSteps step, String taskid, String expectedresults, String testnote, serverOperation caselog){ + int setresult = 0; + try{ + if (null != expectedresults && !expectedresults.isEmpty()) { + LogUtil.APP.info("expectedResults=【{}】",expectedresults); + // 赋值传参 + if (expectedresults.length() > Constants.ASSIGNMENT_SIGN.length() && expectedresults.startsWith(Constants.ASSIGNMENT_SIGN)) { + VARIABLE.put(expectedresults.substring(Constants.ASSIGNMENT_SIGN.length()), testnote); + LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),testnote,expectedresults.substring(Constants.ASSIGNMENT_SIGN.length())); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + testnote + "】赋值给变量【" + expectedresults.substring(Constants.ASSIGNMENT_SIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); + } + // 赋值全局变量 + else if (expectedresults.length() > Constants.ASSIGNMENT_GLOBALSIGN.length() && expectedresults.startsWith(Constants.ASSIGNMENT_GLOBALSIGN)) { + VARIABLE.put(expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), testnote); + ParamsManageForSteps.GLOBAL_VARIABLE.put(expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), testnote); + LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给全局变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),testnote,expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length())); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + testnote + "】赋值给全局变量【" + expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); + } + // 模糊匹配 + else if (expectedresults.length() > Constants.FUZZY_MATCHING_SIGN.length() && expectedresults.startsWith(Constants.FUZZY_MATCHING_SIGN)) { + if (testnote.contains(expectedresults.substring(Constants.FUZZY_MATCHING_SIGN.length()))) { + LogUtil.APP.info("用例:{} 第{}步,模糊匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),testnote); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果成功!执行结果:" + testnote, "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + setresult = 1; + LogUtil.APP.warn("用例:{} 第{}步,模糊匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expectedresults.substring(Constants.FUZZY_MATCHING_SIGN.length()),testnote); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果失败!预期结果:" + expectedresults.substring(Constants.FUZZY_MATCHING_SIGN.length()) + ",测试结果:" + testnote, "error", String.valueOf(step.getStepSerialNumber()), ""); + } + } + // 正则匹配 + else if (expectedresults.length() > Constants.REGULAR_MATCHING_SIGN.length() && expectedresults.startsWith(Constants.REGULAR_MATCHING_SIGN)) { + Pattern pattern = Pattern.compile(expectedresults.substring(Constants.REGULAR_MATCHING_SIGN.length())); + Matcher matcher = pattern.matcher(testnote); + if (matcher.find()) { + LogUtil.APP.info("用例:{} 第{}步,正则匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),testnote); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果成功!执行结果:" + testnote, "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + setresult = 1; + LogUtil.APP.warn("用例:{} 第{}步,正则匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expectedresults.substring(Constants.REGULAR_MATCHING_SIGN.length()),testnote); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果失败!预期结果:" + expectedresults.substring(Constants.REGULAR_MATCHING_SIGN.length()) + ",测试结果:" + testnote, "error", String.valueOf(step.getStepSerialNumber()), ""); + } + } + //jsonpath断言 + else if (expectedresults.length() > Constants.JSONPATH_SIGN.length() && expectedresults.startsWith(Constants.JSONPATH_SIGN)) { + expectedresults = expectedresults.substring(Constants.JSONPATH_SIGN.length()); + String expression = expectedresults.split("(?(1000), new ThreadPoolExecutor.CallerRunsPolicy()); + new ArrayBlockingQueue<>(1000), new ThreadPoolExecutor.CallerRunsPolicy()); List testCases = GetServerApi.getCasesbyplanname(planname); - List pcplist = new ArrayList(); + List pcplist = new ArrayList<>(); if (testCases.size() != 0) { pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testCases.get(0).getProjectId())); } @@ -82,8 +81,7 @@ public class TestControl { /** * 计划任务模式调度计划执行用例 - * @param task - * @throws Exception + * @param task 任务对象 */ public static void taskExecutionPlan(TaskExecute task) throws Exception { serverOperation.exetype = 0; @@ -99,13 +97,13 @@ public class TestControl { // 初始化写用例结果以及日志模块 serverOperation caselog = new serverOperation(); // 判断是否要自动重启TOMCAT - if (restartstatus.indexOf("Status:true") > -1) { + if (restartstatus.contains("Status:true")) { // 判断是否构建是否成功 if (BuildResult.SUCCESS.equals(buildResult)) { int threadcount = taskScheduling.getExThreadCount(); // 创建线程池,多线程执行用例 ThreadPoolExecutor threadExecute = new ThreadPoolExecutor(threadcount, 20, 3, TimeUnit.SECONDS, - new ArrayBlockingQueue(1000), new ThreadPoolExecutor.CallerRunsPolicy()); + new ArrayBlockingQueue<>(1000), new ThreadPoolExecutor.CallerRunsPolicy()); List cases = GetServerApi.getCasesbyplanId(taskScheduling.getPlanId()); LogUtil.APP.info("当前测试任务 {} 中共有【{}】条待测试用例...",task.getTaskName(),cases.size()); diff --git a/src/main/java/luckyclient/execution/httpinterface/ThreadForBatchCase.java b/src/main/java/luckyclient/execution/httpinterface/ThreadForBatchCase.java index 34a7543..9f1775f 100644 --- a/src/main/java/luckyclient/execution/httpinterface/ThreadForBatchCase.java +++ b/src/main/java/luckyclient/execution/httpinterface/ThreadForBatchCase.java @@ -1,33 +1,31 @@ -package luckyclient.execution.httpinterface; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * @date 2017年12月1日 上午9:29:40 - * - */ -public class ThreadForBatchCase extends Thread{ - - private String projectname; - private Integer caseId; - private String taskid; - - public ThreadForBatchCase(String projectname,Integer caseId,String taskid){ - this.projectname = projectname; - this.caseId = caseId; - this.taskid = taskid; - } - - @Override - public void run(){ - TestCaseExecution testCaseExecution=new TestCaseExecution(); - testCaseExecution.oneCaseExecuteForTask(projectname, caseId, taskid); - TestControl.THREAD_COUNT--; //多线程计数--,用于检测线程是否全部执行完 - } - -} +package luckyclient.execution.httpinterface; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * @date 2017年12月1日 上午9:29:40 + * + */ +public class ThreadForBatchCase extends Thread{ + + private Integer caseId; + private String taskid; + + public ThreadForBatchCase(Integer caseId,String taskid){ + this.caseId = caseId; + this.taskid = taskid; + } + + @Override + public void run(){ + TestCaseExecution testCaseExecution=new TestCaseExecution(); + testCaseExecution.oneCaseExecuteForTask(caseId, taskid); + TestControl.THREAD_COUNT--; //多线程计数--,用于检测线程是否全部执行完 + } + +} diff --git a/src/main/java/luckyclient/execution/httpinterface/ThreadForExecuteCase.java b/src/main/java/luckyclient/execution/httpinterface/ThreadForExecuteCase.java index cff7d4c..b1f9d92 100644 --- a/src/main/java/luckyclient/execution/httpinterface/ThreadForExecuteCase.java +++ b/src/main/java/luckyclient/execution/httpinterface/ThreadForExecuteCase.java @@ -1,263 +1,261 @@ -package luckyclient.execution.httpinterface; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import luckyclient.driven.SubString; -import luckyclient.execution.dispose.ActionManageForSteps; -import luckyclient.execution.dispose.ParamsManageForSteps; -import luckyclient.execution.httpinterface.analyticsteps.InterfaceAnalyticCase; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.Constants; -import luckyclient.utils.InvokeMethod; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @ClassName: ThreadForExecuteCase - * @Description: 线程池方式执行用例 - * @author: seagull - * @date 2018年3月1日 - */ -public class ThreadForExecuteCase extends Thread { - private Integer caseId; - private String caseSign; - private ProjectCase testcase; - private String taskid; - private Integer projectId; - private List steps; - private List pcplist; - private serverOperation caselog; - - public ThreadForExecuteCase(ProjectCase projectcase, List steps, String taskid, List pcplist, serverOperation caselog) { - this.caseId = projectcase.getCaseId(); - this.testcase = projectcase; - this.projectId = projectcase.getProjectId(); - this.caseSign = projectcase.getCaseSign(); - this.taskid = taskid; - this.steps = steps; - this.pcplist = pcplist; - this.caselog = caselog; - } - - @Override - public void run() { - Map variable = new HashMap<>(0); - // 把公共参数加入到MAP中 - for (ProjectCaseParams pcp : pcplist) { - variable.put(pcp.getParamsName(), pcp.getParamsValue()); - } - // 加入全局变量 - variable.putAll(ParamsManageForSteps.GLOBAL_VARIABLE); - String functionname = null; - String packagename = null; - String expectedresults = null; - Integer setcaseresult = 0; - Object[] getParameterValues = null; - String testnote = "初始化测试结果"; - int k = 0; - // 进入循环,解析单个用例所有步骤 - // 插入开始执行的用例 - caselog.insertTaskCaseExecute(taskid, projectId, caseId, caseSign, testcase.getCaseName(), 3); - for (int i = 0; i < steps.size(); i++) { - // 解析单个步骤中的脚本 - Map casescript = InterfaceAnalyticCase.analyticCaseStep(testcase, steps.get(i), taskid, caselog,variable); - try { - packagename = casescript.get("PackageName"); - functionname = casescript.get("FunctionName"); - } catch (Exception e) { - k = 0; - LogUtil.APP.error("用例:{} 解析包名或是方法名出现异常,请检查!",testcase.getCaseSign(),e); - caselog.insertTaskCaseLog(taskid, caseId, "解析包名或是方法名失败,请检查!", "error", String.valueOf(i + 1), ""); - break; // 某一步骤失败后,此条用例置为失败退出 - } - // 用例名称解析出现异常或是单个步骤参数解析异常 - if ((null != functionname && functionname.contains("解析异常")) || k == 1) { - k = 0; - testnote = "用例第" + (i + 1) + "步解析出错啦!"; - break; - } - expectedresults = casescript.get("ExpectedResults"); - // 判断方法是否带参数 - if (casescript.size() > 4) { - // 获取传入参数,放入对象中 - getParameterValues = new Object[casescript.size() - 4]; - for (int j = 0; j < casescript.size() - 4; j++) { - if (casescript.get("FunctionParams" + (j + 1)) == null) { - k = 1; - break; - } - String parameterValues = casescript.get("FunctionParams" + (j + 1)); - LogUtil.APP.info("用例:{} 解析包名:{} 方法名:{} 第{}个参数:{}",testcase.getCaseSign(),packagename,functionname,(j+1),parameterValues); - caselog.insertTaskCaseLog(taskid, caseId, "解析包名:" + packagename + " 方法名:" + functionname + " 第" + (j + 1) + "个参数:" + parameterValues, "info", String.valueOf(i + 1), ""); - getParameterValues[j] = parameterValues; - } - } else { - getParameterValues = null; - } - // 调用动态方法,执行测试用例 - try { - LogUtil.APP.info("用例:{}开始调用方法:{} .....",testcase.getCaseSign(),functionname); - caselog.insertTaskCaseLog(taskid, caseId, "开始调用方法:" + functionname + " .....", "info", String.valueOf(i + 1), ""); - - testnote = InvokeMethod.callCase(packagename, functionname, getParameterValues, steps.get(i).getStepType(), steps.get(i).getExtend()); - testnote = ActionManageForSteps.actionManage(casescript.get("Action"), testnote); - if (null != expectedresults && !expectedresults.isEmpty()) { - LogUtil.APP.info("expectedResults=【{}】",expectedresults); - // 赋值传参 - if (expectedresults.length() > Constants.ASSIGNMENT_SIGN.length() && expectedresults.startsWith(Constants.ASSIGNMENT_SIGN)) { - variable.put(expectedresults.substring(Constants.ASSIGNMENT_SIGN.length()), testnote); - LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给变量【{}】",testcase.getCaseSign(),(i+1),testnote,expectedresults.substring(Constants.ASSIGNMENT_SIGN.length())); - caselog.insertTaskCaseLog(taskid, caseId, "将测试结果【" + testnote + "】赋值给变量【" + expectedresults.substring(Constants.ASSIGNMENT_SIGN.length()) + "】", "info", String.valueOf(i + 1), ""); - } - // 赋值全局变量 - else if (expectedresults.length() > Constants.ASSIGNMENT_GLOBALSIGN.length() && expectedresults.startsWith(Constants.ASSIGNMENT_GLOBALSIGN)) { - variable.put(expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), testnote); - ParamsManageForSteps.GLOBAL_VARIABLE.put(expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), testnote); - LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给全局变量【{}】",testcase.getCaseSign(),(i+1),testnote,expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length())); - caselog.insertTaskCaseLog(taskid, caseId, "将测试结果【" + testnote + "】赋值给全局变量【" + expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()) + "】", "info", String.valueOf(i + 1), ""); - } - // 模糊匹配 - else if (expectedresults.length() > Constants.FUZZY_MATCHING_SIGN.length() && expectedresults.startsWith(Constants.FUZZY_MATCHING_SIGN)) { - if (testnote.contains(expectedresults.substring(Constants.FUZZY_MATCHING_SIGN.length()))) { - LogUtil.APP.info("用例:{} 第{}步,模糊匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),(i+1),testnote); - caselog.insertTaskCaseLog(taskid, caseId, "模糊匹配预期结果成功!执行结果:" + testnote, "info", String.valueOf(i + 1), ""); - } else { - setcaseresult = 1; - LogUtil.APP.warn("用例:{} 第{}步,模糊匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),(i+1),expectedresults.substring(Constants.FUZZY_MATCHING_SIGN.length()),testnote); - caselog.insertTaskCaseLog(taskid, caseId, "第" + (i + 1) + "步,模糊匹配预期结果失败!预期结果:" + expectedresults.substring(Constants.FUZZY_MATCHING_SIGN.length()) + ",测试结果:" + testnote, "error", String.valueOf(i + 1), ""); - testnote = "用例第" + (i + 1) + "步,模糊匹配预期结果失败!"; - if (testcase.getFailcontinue() == 0) { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); - break; - } else { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); - } - } - } - // 正则匹配 - else if (expectedresults.length() > Constants.REGULAR_MATCHING_SIGN.length() && expectedresults.startsWith(Constants.REGULAR_MATCHING_SIGN)) { - Pattern pattern = Pattern.compile(expectedresults.substring(Constants.REGULAR_MATCHING_SIGN.length())); - Matcher matcher = pattern.matcher(testnote); - if (matcher.find()) { - LogUtil.APP.info("用例:{} 第{}步,正则匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),(i+1),testnote); - caselog.insertTaskCaseLog(taskid, caseId, "正则匹配预期结果成功!执行结果:" + testnote, "info", String.valueOf(i + 1), ""); - } else { - setcaseresult = 1; - LogUtil.APP.warn("用例:{} 第{}步,正则匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),(i+1),expectedresults.substring(Constants.REGULAR_MATCHING_SIGN.length()),testnote); - caselog.insertTaskCaseLog(taskid, caseId, "第" + (i + 1) + "步,正则匹配预期结果失败!预期结果:" + expectedresults.substring(Constants.REGULAR_MATCHING_SIGN.length()) + ",测试结果:" + testnote, "error", String.valueOf(i + 1), ""); - testnote = "用例第" + (i + 1) + "步,正则匹配预期结果失败!"; - if (testcase.getFailcontinue() == 0) { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); - break; - } else { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); - } - } - } - //jsonpath断言 - else if (expectedresults.length() > Constants.JSONPATH_SIGN.length() && expectedresults.startsWith(Constants.JSONPATH_SIGN)) { - expectedresults = expectedresults.substring(Constants.JSONPATH_SIGN.length()); - String expression = expectedresults.split("(? steps; + private List pcplist; + private serverOperation caselog; + + public ThreadForExecuteCase(ProjectCase projectcase, List steps, String taskid, List pcplist, serverOperation caselog) { + this.caseId = projectcase.getCaseId(); + this.testcase = projectcase; + this.projectId = projectcase.getProjectId(); + this.caseSign = projectcase.getCaseSign(); + this.taskid = taskid; + this.steps = steps; + this.pcplist = pcplist; + this.caselog = caselog; + } + + @Override + public void run() { + Map variable = new HashMap<>(0); + // 把公共参数加入到MAP中 + for (ProjectCaseParams pcp : pcplist) { + variable.put(pcp.getParamsName(), pcp.getParamsValue()); + } + // 加入全局变量 + variable.putAll(ParamsManageForSteps.GLOBAL_VARIABLE); + String functionname; + String packagename; + String expectedresults; + int setcaseresult = 0; + Object[] getParameterValues; + String testnote = "初始化测试结果"; + int k = 0; + // 进入循环,解析单个用例所有步骤 + // 插入开始执行的用例 + caselog.insertTaskCaseExecute(taskid, projectId, caseId, caseSign, testcase.getCaseName(), 3); + for (int i = 0; i < steps.size(); i++) { + // 解析单个步骤中的脚本 + Map casescript = InterfaceAnalyticCase.analyticCaseStep(testcase, steps.get(i), taskid, caselog,variable); + try { + packagename = casescript.get("PackageName"); + functionname = casescript.get("FunctionName"); + } catch (Exception e) { + LogUtil.APP.error("用例:{} 解析包名或是方法名出现异常,请检查!",testcase.getCaseSign(),e); + caselog.insertTaskCaseLog(taskid, caseId, "解析包名或是方法名失败,请检查!", "error", String.valueOf(i + 1), ""); + break; // 某一步骤失败后,此条用例置为失败退出 + } + // 用例名称解析出现异常或是单个步骤参数解析异常 + if ((null != functionname && functionname.contains("解析异常")) || k == 1) { + testnote = "用例第" + (i + 1) + "步解析出错啦!"; + break; + } + expectedresults = casescript.get("ExpectedResults"); + // 判断方法是否带参数 + if (casescript.size() > 4) { + // 获取传入参数,放入对象中 + getParameterValues = new Object[casescript.size() - 4]; + for (int j = 0; j < casescript.size() - 4; j++) { + if (casescript.get("FunctionParams" + (j + 1)) == null) { + k = 1; + break; + } + String parameterValues = casescript.get("FunctionParams" + (j + 1)); + LogUtil.APP.info("用例:{} 解析包名:{} 方法名:{} 第{}个参数:{}",testcase.getCaseSign(),packagename,functionname,(j+1),parameterValues); + caselog.insertTaskCaseLog(taskid, caseId, "解析包名:" + packagename + " 方法名:" + functionname + " 第" + (j + 1) + "个参数:" + parameterValues, "info", String.valueOf(i + 1), ""); + getParameterValues[j] = parameterValues; + } + } else { + getParameterValues = null; + } + // 调用动态方法,执行测试用例 + try { + LogUtil.APP.info("用例:{}开始调用方法:{} .....",testcase.getCaseSign(),functionname); + caselog.insertTaskCaseLog(taskid, caseId, "开始调用方法:" + functionname + " .....", "info", String.valueOf(i + 1), ""); + + testnote = InvokeMethod.callCase(packagename, functionname, getParameterValues, steps.get(i).getStepType(), steps.get(i).getExtend()); + testnote = ActionManageForSteps.actionManage(casescript.get("Action"), testnote); + if (null != expectedresults && !expectedresults.isEmpty()) { + LogUtil.APP.info("expectedResults=【{}】",expectedresults); + // 赋值传参 + if (expectedresults.length() > Constants.ASSIGNMENT_SIGN.length() && expectedresults.startsWith(Constants.ASSIGNMENT_SIGN)) { + variable.put(expectedresults.substring(Constants.ASSIGNMENT_SIGN.length()), testnote); + LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给变量【{}】",testcase.getCaseSign(),(i+1),testnote,expectedresults.substring(Constants.ASSIGNMENT_SIGN.length())); + caselog.insertTaskCaseLog(taskid, caseId, "将测试结果【" + testnote + "】赋值给变量【" + expectedresults.substring(Constants.ASSIGNMENT_SIGN.length()) + "】", "info", String.valueOf(i + 1), ""); + } + // 赋值全局变量 + else if (expectedresults.length() > Constants.ASSIGNMENT_GLOBALSIGN.length() && expectedresults.startsWith(Constants.ASSIGNMENT_GLOBALSIGN)) { + variable.put(expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), testnote); + ParamsManageForSteps.GLOBAL_VARIABLE.put(expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), testnote); + LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给全局变量【{}】",testcase.getCaseSign(),(i+1),testnote,expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length())); + caselog.insertTaskCaseLog(taskid, caseId, "将测试结果【" + testnote + "】赋值给全局变量【" + expectedresults.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()) + "】", "info", String.valueOf(i + 1), ""); + } + // 模糊匹配 + else if (expectedresults.length() > Constants.FUZZY_MATCHING_SIGN.length() && expectedresults.startsWith(Constants.FUZZY_MATCHING_SIGN)) { + if (testnote.contains(expectedresults.substring(Constants.FUZZY_MATCHING_SIGN.length()))) { + LogUtil.APP.info("用例:{} 第{}步,模糊匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),(i+1),testnote); + caselog.insertTaskCaseLog(taskid, caseId, "模糊匹配预期结果成功!执行结果:" + testnote, "info", String.valueOf(i + 1), ""); + } else { + setcaseresult = 1; + LogUtil.APP.warn("用例:{} 第{}步,模糊匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),(i+1),expectedresults.substring(Constants.FUZZY_MATCHING_SIGN.length()),testnote); + caselog.insertTaskCaseLog(taskid, caseId, "第" + (i + 1) + "步,模糊匹配预期结果失败!预期结果:" + expectedresults.substring(Constants.FUZZY_MATCHING_SIGN.length()) + ",测试结果:" + testnote, "error", String.valueOf(i + 1), ""); + testnote = "用例第" + (i + 1) + "步,模糊匹配预期结果失败!"; + if (testcase.getFailcontinue() == 0) { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); + break; + } else { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); + } + } + } + // 正则匹配 + else if (expectedresults.length() > Constants.REGULAR_MATCHING_SIGN.length() && expectedresults.startsWith(Constants.REGULAR_MATCHING_SIGN)) { + Pattern pattern = Pattern.compile(expectedresults.substring(Constants.REGULAR_MATCHING_SIGN.length())); + Matcher matcher = pattern.matcher(testnote); + if (matcher.find()) { + LogUtil.APP.info("用例:{} 第{}步,正则匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),(i+1),testnote); + caselog.insertTaskCaseLog(taskid, caseId, "正则匹配预期结果成功!执行结果:" + testnote, "info", String.valueOf(i + 1), ""); + } else { + setcaseresult = 1; + LogUtil.APP.warn("用例:{} 第{}步,正则匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),(i+1),expectedresults.substring(Constants.REGULAR_MATCHING_SIGN.length()),testnote); + caselog.insertTaskCaseLog(taskid, caseId, "第" + (i + 1) + "步,正则匹配预期结果失败!预期结果:" + expectedresults.substring(Constants.REGULAR_MATCHING_SIGN.length()) + ",测试结果:" + testnote, "error", String.valueOf(i + 1), ""); + testnote = "用例第" + (i + 1) + "步,正则匹配预期结果失败!"; + if (testcase.getFailcontinue() == 0) { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); + break; + } else { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),(i+1)); + } + } + } + //jsonpath断言 + else if (expectedresults.length() > Constants.JSONPATH_SIGN.length() && expectedresults.startsWith(Constants.JSONPATH_SIGN)) { + expectedresults = expectedresults.substring(Constants.JSONPATH_SIGN.length()); + String expression = expectedresults.split("(? variable = new HashMap<>(0); - String packagename = null; - String functionname = null; - String expectedresults = null; - Integer setcaseresult = 0; - Object[] getParameterValues = null; + String packagename; + String functionname; + String expectedresults; + int setcaseresult = 0; + Object[] getParameterValues; String testnote = "初始化测试结果"; int k = 0; Integer caseId = Integer.valueOf(caseIdStr); @@ -64,14 +64,12 @@ public class WebTestCaseDebug { packagename = casescript.get("PackageName"); functionname = casescript.get("FunctionName"); } catch (Exception e) { - k = 0; LogUtil.APP.error("解析包名或是方法名出现异常!",e); PostServerApi.cPostDebugLog(userId, caseId, "ERROR", "解析包名或是方法名失败,请检查!",2); break; //某一步骤失败后,此条用例置为失败退出 } //用例名称解析出现异常或是单个步骤参数解析异常 if ((null != functionname && functionname.contains("解析异常")) || k == 1) { - k = 0; testnote = "用例第" + (i + 1) + "步解析出错啦!"; break; } @@ -156,10 +154,10 @@ public class WebTestCaseDebug { if (exceptResult.equals(result)) { setcaseresult = 0; - PostServerApi.cPostDebugLog(userId, caseId, "INFO", "jsonpath断言预期结果成功!预期结果:" + exceptResult + " 测试结果: " + result.toString() + "校验结果: true", 0); + PostServerApi.cPostDebugLog(userId, caseId, "INFO", "jsonpath断言预期结果成功!预期结果:" + exceptResult + " 测试结果: " + result + "校验结果: true", 0); } else { setcaseresult = 1; - PostServerApi.cPostDebugLog(userId, caseId, "ERROR", "第" + (i + 1) + "步,jsonpath断言预期结果失败!预期结果:" + exceptResult + ",测试结果:" + result.toString(),0); + PostServerApi.cPostDebugLog(userId, caseId, "ERROR", "第" + (i + 1) + "步,jsonpath断言预期结果失败!预期结果:" + exceptResult + ",测试结果:" + result,0); testnote = "用例第" + (i + 1) + "步,jsonpath断言预期结果失败!"; if (testcase.getFailcontinue() == 0) { LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),(i+1)); @@ -211,7 +209,4 @@ public class WebTestCaseDebug { } } - public static void main(String[] args) throws Exception { - - } } diff --git a/src/main/java/luckyclient/execution/httpinterface/analyticsteps/InterfaceAnalyticCase.java b/src/main/java/luckyclient/execution/httpinterface/analyticsteps/InterfaceAnalyticCase.java index a526b62..0d7848e 100644 --- a/src/main/java/luckyclient/execution/httpinterface/analyticsteps/InterfaceAnalyticCase.java +++ b/src/main/java/luckyclient/execution/httpinterface/analyticsteps/InterfaceAnalyticCase.java @@ -1,186 +1,187 @@ -package luckyclient.execution.httpinterface.analyticsteps; - -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import luckyclient.execution.dispose.ChangString; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.LogUtil; -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * @ClassName: AnalyticCase - * @Description: 解析单个用例中描述部分的脚本 - * @author: seagull - * @date 2017年7月14日 上午9:29:40 - * - */ -public class InterfaceAnalyticCase{ - /** - * 解析用例步骤 - * @param projectcase - * @param step - * @param taskid - * @param caselog - * @return - */ - public static Map analyticCaseStep(ProjectCase projectcase,ProjectCaseSteps step,String taskid,serverOperation caselog, Map variable){ - Map params = new HashMap(0); - - try { - String resultstr = step.getExpectedResult(); - params.put("Action", step.getAction()); - // 处理值传递 - String packageName = ChangString.changparams(step.getStepPath().trim(), variable, "包路径"); - params.put("PackageName", packageName); - // 处理值传递 - String functionName = ChangString.changparams(step.getStepOperation().trim(), variable, "方法名"); - params.put("FunctionName", functionName); - String stepParams = replaceSpi(step.getStepParameters(),0); - String[] temp=stepParams.split("\\|",-1); - for(int i=0;i-1&&htmlStr.indexOf("*/")>-1){ - String commentstr = htmlStr.substring(htmlStr.trim().indexOf("/*"),htmlStr.indexOf("*/")+2); - //去注释 - scriptstr = htmlStr.replace(commentstr, ""); - }else{ - scriptstr = htmlStr; - } - //去掉字符串前后的空格 - scriptstr = trimInnerSpaceStr(scriptstr); - //替换空格转义 - scriptstr = scriptstr.replaceAll(" ", " "); - //转义双引号 - scriptstr = scriptstr.replaceAll(""", "\""); - //转义单引号 - scriptstr = scriptstr.replaceAll("'", "\'"); - //转义链接符 - scriptstr = scriptstr.replaceAll("&", "&"); - scriptstr = scriptstr.replaceAll("<", "<"); - scriptstr = scriptstr.replaceAll(">", ">"); - - return scriptstr; - } - - /*** - * 去掉字符串前后的空格,中间的空格保留 - * @param str - * @return - */ - public static String trimInnerSpaceStr(String str){ - str = str.trim(); - while(str.startsWith(" ")){ - str = str.substring(1,str.length()).trim(); - } - while(str.startsWith(" ")){ - str = str.substring(6,str.length()).trim(); - } - while(str.endsWith(" ")){ - str = str.substring(0,str.length()-1).trim(); - } - while(str.endsWith(" ")){ - str = str.substring(0,str.length()-6).trim(); - } - return str; - } - - /** - * 当遇到参数中带了|字符串时,在界面\\|进行转义 - * @param str - * @param flag - * @return - */ - private static String replaceSpi(String str,int flag){ - String replacestr="¦_rep;"; - if(null==str){ - str = ""; - } - String result=str; - if(str.contains("\\\\|")&&flag==0){ - result=str.replace("\\\\|", replacestr); - } - if(str.contains(replacestr)&&flag==1){ - result=str.replace(replacestr,"|"); - } - return result; - } - - public static void main(String[] args){ - // TODO Auto-generated method stub - - } -} +package luckyclient.execution.httpinterface.analyticsteps; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import luckyclient.execution.dispose.ChangString; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.LogUtil; +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * @ClassName: AnalyticCase + * @Description: 解析单个用例中描述部分的脚本 + * @author: seagull + * @date 2017年7月14日 上午9:29:40 + * + */ +public class InterfaceAnalyticCase{ + /** + * 解析用例步骤 + * @param projectcase 待解析用例对象 + * @param step 用例步骤对象 + * @param taskid 任务ID + * @param caselog 日志对象 + * @return 返回解析的用例MAP + */ + public static Map analyticCaseStep(ProjectCase projectcase,ProjectCaseSteps step,String taskid,serverOperation caselog, Map variable){ + Map params = new HashMap<>(0); + + try { + String resultstr = step.getExpectedResult(); + params.put("Action", step.getAction()); + // 处理值传递 + String packageName = ChangString.changparams(step.getStepPath().trim(), variable, "包路径"); + params.put("PackageName", packageName); + // 处理值传递 + String functionName = ChangString.changparams(step.getStepOperation().trim(), variable, "方法名"); + params.put("FunctionName", functionName); + String stepParams = replaceSpi(step.getStepParameters(),0); + String[] temp=stepParams.split("\\|",-1); + for(int i=0;i"); + + return scriptstr; + } + + /*** + * 去掉字符串前后的空格,中间的空格保留 + * @param str 待处理字符串 + * @return 返回去掉空格后的结果 + */ + public static String trimInnerSpaceStr(String str){ + str = str.trim(); + while(str.startsWith(" ")){ + str = str.substring(1).trim(); + } + while(str.startsWith(" ")){ + str = str.substring(6).trim(); + } + while(str.endsWith(" ")){ + str = str.substring(0,str.length()-1).trim(); + } + while(str.endsWith(" ")){ + str = str.substring(0,str.length()-6).trim(); + } + return str; + } + + /** + * 当遇到参数中带了|字符串时,在界面\\|进行转义 + * @param str 待处理字符串 + * @param flag 处理标识 + * @return 返回处理后结果 + */ + private static String replaceSpi(String str,int flag){ + String replacestr="¦_rep;"; + if(null==str){ + str = ""; + } + String result=str; + if(str.contains("\\\\|")&&flag==0){ + result=str.replace("\\\\|", replacestr); + } + if(str.contains(replacestr)&&flag==1){ + result=str.replace(replacestr,"|"); + } + return result; + } + + public static void main(String[] args){ + // TODO Auto-generated method stub + + } +} diff --git a/src/main/java/luckyclient/execution/webdriver/BaseWebDrive.java b/src/main/java/luckyclient/execution/webdriver/BaseWebDrive.java index 6cdafdc..4724e9d 100644 --- a/src/main/java/luckyclient/execution/webdriver/BaseWebDrive.java +++ b/src/main/java/luckyclient/execution/webdriver/BaseWebDrive.java @@ -31,12 +31,10 @@ public class BaseWebDrive { /** * 进测试结果进行截图 - * @param driver - * @param imgname - * @return + * @param driver 驱动 + * @param imgname 图片名称 */ - public static Boolean webScreenShot(WebDriver driver,String imgname) { - Boolean result = false; + public static void webScreenShot(WebDriver driver, String imgname) { String relativelyPath = System.getProperty("user.dir"); String pngpath=relativelyPath +File.separator+ "log"+File.separator+"ScreenShot" +File.separator+ imgname + ".png"; @@ -51,19 +49,18 @@ public class BaseWebDrive { scrFile.deleteOnExit(); LogUtil.APP .info("已对当前界面进行截图操作,可通过用例执行界面的日志明细查看,也可以前往客户端上查看...【{}】",pngpath); - return result; } /** * 在自动化过程中加入点击显示效果 - * @param driver - * @param element + * @param driver 驱动 + * @param element 定位元素 * @author Seagull * @date 2019年9月6日 */ public static void highLightElement(WebDriver driver, WebElement element){ Properties properties = SysConfig.getConfiguration(); - Boolean highLight = BooleanUtil.toBoolean(properties.getProperty("webdriver.highlight")); + boolean highLight = BooleanUtil.toBoolean(properties.getProperty("webdriver.highlight")); if(highLight){ JavascriptExecutor js = (JavascriptExecutor) driver; diff --git a/src/main/java/luckyclient/execution/webdriver/CaseLocalDebug.java b/src/main/java/luckyclient/execution/webdriver/CaseLocalDebug.java index b068d44..f28854b 100644 --- a/src/main/java/luckyclient/execution/webdriver/CaseLocalDebug.java +++ b/src/main/java/luckyclient/execution/webdriver/CaseLocalDebug.java @@ -1,73 +1,73 @@ -package luckyclient.execution.webdriver; - -import java.util.List; - -import org.openqa.selenium.WebDriver; - -import luckyclient.execution.webdriver.ex.WebCaseExecution; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * @date 2017年12月1日 上午9:29:40 - * - */ -public class CaseLocalDebug{ - - /** - * 单个用例Web UI调试 - * @param wd - * @param testCaseExternalId - * @author Seagull - * @date 2020年1月20日 - */ - public static void oneCasedebug(WebDriver wd,String testCaseExternalId){ - //不记录日志到数据库 - serverOperation.exetype = 1; - serverOperation caselog = new serverOperation(); - try { - ProjectCase testcase = GetServerApi.cgetCaseBysign(testCaseExternalId); - List pcplist=GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); - LogUtil.APP.info("开始执行用例:【{}】......",testCaseExternalId); - List steps=GetServerApi.getStepsbycaseid(testcase.getCaseId()); - WebCaseExecution.caseExcution(testcase,steps, "888888",wd,caselog,pcplist); - LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); - } catch (Exception e) { - LogUtil.APP.error("用户执行过程中抛出异常!", e); - } - //关闭浏览器 - wd.quit(); - } - - /** - * 多个用例串行Web UI调试 - * @param wd - * @param projectname - * @param addtestcase - * @author Seagull - * @date 2020年1月20日 - */ - public static void moreCaseDebug(WebDriver wd,String projectname,List addtestcase){ - System.out.println("当前调试用例总共:"+addtestcase.size()); - for(String testCaseExternalId:addtestcase) { - try{ - LogUtil.APP.info("开始调用方法,项目名:{},用例编号:{}",projectname,testCaseExternalId); - oneCasedebug(wd,testCaseExternalId); - }catch(Exception e){ - continue; - } - } - } - -} +package luckyclient.execution.webdriver; + +import java.util.List; + +import org.openqa.selenium.WebDriver; + +import luckyclient.execution.webdriver.ex.WebCaseExecution; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * @date 2017年12月1日 上午9:29:40 + * + */ +public class CaseLocalDebug{ + + /** + * 单个用例Web UI调试 + * @param wd 驱动 + * @param testCaseExternalId 用例编号 + * @author Seagull + * @date 2020年1月20日 + */ + public static void oneCasedebug(WebDriver wd,String testCaseExternalId){ + //不记录日志到数据库 + serverOperation.exetype = 1; + serverOperation caselog = new serverOperation(); + try { + ProjectCase testcase = GetServerApi.cgetCaseBysign(testCaseExternalId); + List pcplist=GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); + LogUtil.APP.info("开始执行用例:【{}】......",testCaseExternalId); + List steps=GetServerApi.getStepsbycaseid(testcase.getCaseId()); + WebCaseExecution.caseExcution(testcase,steps, "888888",wd,caselog,pcplist); + LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); + } catch (Exception e) { + LogUtil.APP.error("用户执行过程中抛出异常!", e); + } + //关闭浏览器 + wd.quit(); + } + + /** + * 多个用例串行Web UI调试 + * @param wd 驱动 + * @param projectname 项目名称 + * @param addtestcase 用例集 + * @author Seagull + * @date 2020年1月20日 + */ + public static void moreCaseDebug(WebDriver wd,String projectname,List addtestcase){ + System.out.println("当前调试用例总共:"+addtestcase.size()); + for(String testCaseExternalId:addtestcase) { + try{ + LogUtil.APP.info("开始调用方法,项目名:{},用例编号:{}",projectname,testCaseExternalId); + oneCasedebug(wd,testCaseExternalId); + }catch(Exception e){ + LogUtil.APP.error("用例运行出现异常,用例编号:{}",testCaseExternalId); + } + } + } + +} diff --git a/src/main/java/luckyclient/execution/webdriver/EncapsulateOperation.java b/src/main/java/luckyclient/execution/webdriver/EncapsulateOperation.java index b4a5534..c9713cc 100644 --- a/src/main/java/luckyclient/execution/webdriver/EncapsulateOperation.java +++ b/src/main/java/luckyclient/execution/webdriver/EncapsulateOperation.java @@ -1,607 +1,607 @@ -package luckyclient.execution.webdriver; - -import java.time.Duration; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import org.apache.commons.lang3.StringUtils; -import org.openqa.selenium.Alert; -import org.openqa.selenium.Cookie; -import org.openqa.selenium.JavascriptExecutor; -import org.openqa.selenium.Keys; -import org.openqa.selenium.NoSuchWindowException; -import org.openqa.selenium.Point; -import org.openqa.selenium.TimeoutException; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.support.ui.ExpectedCondition; -import org.openqa.selenium.support.ui.FluentWait; -import org.openqa.selenium.support.ui.Select; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; - -import luckyclient.execution.dispose.ChangString; -import luckyclient.execution.webdriver.ocr.Ocr; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * @date 2017年12月1日 上午9:29:40 - */ -public class EncapsulateOperation { - - public static String selectOperation(WebElement we, String operation, String operationValue) throws Exception { - String result = ""; - // 下拉框对象处理 - Select select = new Select(we); - - // 处理下拉框事件 - switch (operation) { - case "selectbyvisibletext": - select.selectByVisibleText(operationValue); - result = "下拉框对象通过VisibleText属性选择...【VisibleText属性值:" + operationValue + "】"; - LogUtil.APP.info("下拉框对象通过VisibleText属性选择...【VisibleText属性值:{}】",operationValue); - break; - case "selectbyvalue": - select.selectByValue(operationValue); - result = "下拉框对象通过Value属性选择...【Value属性值:" + operationValue + "】"; - LogUtil.APP.info("下拉框对象通过Value属性选择...【Value属性值:{}】",operationValue); - break; - case "selectbyindex": - select.selectByIndex(Integer.valueOf(operationValue)); - result = "下拉框对象通过Index属性选择...【Index属性值:" + operationValue + "】"; - LogUtil.APP.info("下拉框对象通过Index属性选择...【Index属性值:{}】",operationValue); - break; - case "isselect": - result = "获取到的值是【" + we.isSelected() + "】"; - LogUtil.APP.info("判断对象是否已经被选择...【结果值:{}】",we.isSelected()); - break; - default: - break; - } - return result; - } - - public static String getOperation(WebDriver wd, WebElement we, String operation, String value) throws Exception { - String result = ""; - // 获取对象处理 - switch (operation) { - case "gettext": - result = "获取到的值是【" + we.getText() + "】"; - LogUtil.APP.info("getText获取对象text属性...【text属性值:{}】",result); - break; // 获取输入框内容 - case "gettagname": - result = "获取到的值是【" + we.getTagName() + "】"; - LogUtil.APP.info("getTagName获取对象tagname属性...【tagname属性值:{}】",result); - break; - case "getattribute": - result = "获取到的值是【" + we.getAttribute(value) + "】"; - LogUtil.APP.info("getAttribute获取对象【{}】属性...【{}属性值:{}】",value,value,result); - break; - case "getcssvalue": - result = "获取到的值是【" + we.getCssValue(value) + "】"; - LogUtil.APP.info("getCssValue获取对象【{}】属性...【{}属性值:{}】",value,value,result); - break; - case "getcaptcha": - result = "获取到的值是【" + Ocr.getCAPTCHA(wd, we) + "】"; - LogUtil.APP.info("getcaptcha获取验证码...【验证码值:{}】",result); - break; - default: - break; - } - return result; - } - - public static String actionWeOperation(WebDriver wd, WebElement we, String operation, String operationValue, String property, String propertyValue) throws Exception { - String result = ""; - Actions action = new Actions(wd); - // action处理 - switch (operation) { - //鼠标左键点击 - case "mouselkclick": - action.click(we).perform(); - result = "mouselkclick鼠标左键点击对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; - LogUtil.APP.info("mouselkclick鼠标左键点击对象...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); - break; - case "mouserkclick": - action.contextClick(we).perform(); - result = "mouserkclick鼠标右键点击对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; - LogUtil.APP.info("mouserkclick鼠标右键点击对象...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); - break; - case "mousedclick": - action.doubleClick(we).perform(); - result = "mousedclick鼠标双击对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; - LogUtil.APP.info("mousedclick鼠标双击对象...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); - break; - case "mouseclickhold": - action.clickAndHold(we).perform(); - result = "mouseclickhold鼠标点击对象后不释放...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; - LogUtil.APP.info("mouseclickhold鼠标点击对象后不释放...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); - break; - case "mousedrag": - int[] location = getLocationFromParam(operationValue, ","); -// String[] temp = operationValue.split(",", -1); - action.dragAndDropBy(we, location[0], location[1]).perform(); - result = "mousedrag鼠标移动至对象相对坐标...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "; 相对坐标(x,y):" + location[0] + "," + location[1] + "】"; - LogUtil.APP.info("mousedrag鼠标移动至对象相对坐标...【对象定位属性:{}; 定位属性值:{}; 相对坐标(x,y):{},{}】",property,propertyValue,location[0],location[1]); - break; - case "mouseto": - int[] location1 = getLocationFromParam(operationValue, ","); -// String[] temp1 = operationValue.split(",", -1); - action.moveToElement(we, location1[0], location1[1]).perform(); - result = "mouseto鼠标移动至对象相对坐标...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "; 相对坐标(x,y):" + location1[0] + "," + location1[1] + "】"; - LogUtil.APP.info("mouseto鼠标移动至对象相对坐标...【对象定位属性:{}; 定位属性值:{}; 相对坐标(x,y):{},{}】",property,propertyValue,location1[0],location1[1]); - break; - case "mouserelease": - action.release(we).perform(); - result = "mouserelease鼠标释放..."; - LogUtil.APP.info("mouserelease鼠标释放..."); - break; - default: - break; - } - return result; - } - - public static String actionOperation(WebDriver wd, String operation, String operationValue) throws Exception { - String result = ""; - Actions action = new Actions(wd); - // action处理 - switch (operation) { - //鼠标左键点击 - case "mouselkclick": - action.click().perform(); - result = "mouselkclick鼠标左键点击当前位置..."; - LogUtil.APP.info(result); - break; - case "mouserkclick": - action.contextClick().perform(); - result = "mouserkclick鼠标右键点击当前位置..."; - LogUtil.APP.info(result); - break; - case "mousedclick": - action.doubleClick().perform(); - result = "mousedclick鼠标双击当前位置..."; - LogUtil.APP.info(result); - break; - case "mouseclickhold": - action.clickAndHold().perform(); - result = "mouseclickhold鼠标点击当前位置后不释放..."; - LogUtil.APP.info(result); - break; - case "mouseto": - int[] location = getLocationFromParam(operationValue, ","); -// String[] temp1 = operationValue.split(",", -1); - action.moveByOffset(location[0], location[1]).perform(); - result = "mouseto鼠标移动至对象相对坐标...坐标x:" + location[0] + " 坐标y:" + location[1]; - LogUtil.APP.info("mouseto鼠标移动至对象相对坐标...坐标x:{} 坐标y:{}",location[0],location[1]); - break; - case "mouserelease": - action.release().perform(); - result = "mouserelease鼠标释放..."; - LogUtil.APP.info(result); - break; - case "mousekey": - switch (operationValue) { - case "tab": - action.sendKeys(Keys.TAB).perform(); - result = "键盘操作TAB键..."; - LogUtil.APP.info(result); - break; - case "space": - action.sendKeys(Keys.SPACE).perform(); - result = "键盘操作SPACE键..."; - LogUtil.APP.info(result); - break; - case "ctrl": - action.sendKeys(Keys.CONTROL).perform(); - result = "键盘操作CONTROL键..."; - LogUtil.APP.info(result); - break; - case "shift": - action.sendKeys(Keys.SHIFT).perform(); - result = "键盘操作SHIFT键..."; - LogUtil.APP.info(result); - break; - case "enter": - action.sendKeys(Keys.ENTER).perform(); - result = "键盘操作ENTER键..."; - LogUtil.APP.info(result); - break; - default: - break; - } - break; - default: - break; - } - return result; - } - - public static String objectOperation(WebDriver wd, WebElement we, String operation, String operationValue, String property, String propertyValue) throws Exception { - String result = ""; - // 处理WebElement对象操作 - switch (operation) { - case "click": - we.click(); - result = "click点击对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; - LogUtil.APP.info("click点击对象...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); - break; - case "sendkeys": - we.sendKeys(operationValue); - result = "sendKeys对象输入...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "; 操作值:" + operationValue + "】"; - LogUtil.APP.info("sendKeys对象输入...【对象定位属性:{}; 定位属性值:{}; 操作值:{}】",property,propertyValue,operationValue); - break; - case "clear": - we.clear(); - result = "clear清空输入框...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; - LogUtil.APP.info("clear清空输入框...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); - break; // 清空输入框 - case "gotoframe": - wd.switchTo().frame(we); - result = "gotoframe切换Frame...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; - LogUtil.APP.info("gotoframe切换Frame...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); - break; - case "isenabled": - result = "获取到的值是【"+we.isEnabled()+"】"; - LogUtil.APP.info("获取到的值是【{}】",we.isEnabled()); - break; - case "isdisplayed": - result = "获取到的值是【" + String.valueOf(we.isDisplayed()) + "】"; - LogUtil.APP.info("获取到的值是【{}】",String.valueOf(we.isDisplayed())); - break; - case "exjsob": - JavascriptExecutor jse = (JavascriptExecutor) wd; - Object obj = jse.executeScript(operationValue, we); - if (null != obj) { - String tmp = obj.toString(); - result = (100 < tmp.length()) ? tmp.substring(0, 100) + "..." : tmp; - result = "获取到的值是【" + result + "】"; - LogUtil.APP.info("执行JS...【{}】,返回的结果为:{}",operationValue,result); - } else { - result = "执行JS...【" + operationValue + "】"; - LogUtil.APP.info("执行JS...【{}】",operationValue); - } - break; - case "scrollto": - Point location = we.getLocation(); - ((JavascriptExecutor) wd).executeScript("window.scrollTo(" + location.getX() + ", " + location.getY() + ")"); - result = "滚动到目标对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "; 对象坐标(x,y):" + location.getX() + "," + location.getY() + "】"; - LogUtil.APP.info("滚动到目标对象...【对象定位属性:{}; 定位属性值:{}; 对象坐标(x,y):{},{}】",property,propertyValue,location.getX(),location.getY()); - break; - case "scrollintoview": - // 此方法可以用执行js命令来代替 - ((JavascriptExecutor) wd).executeScript("arguments[0].scrollIntoView(" + operationValue + ")", we); - result = "将目标对象滚动到可视...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; - LogUtil.APP.info("将目标对象滚动到可视...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); - break; - default: - break; - } - return result; - } - - public static String alertOperation(WebDriver wd, String operation) throws Exception { - String result = ""; - Alert alert = wd.switchTo().alert(); - switch (operation) { - case "alertaccept": - alert.accept(); - result = "弹出框对象点击同意..."; - LogUtil.APP.info(result); - break; - case "alertdismiss": - alert.dismiss(); - result = "弹出框对象点击取消..."; - LogUtil.APP.info(result); - break; - case "alertgettext": - result = "获取到的值是【" + alert.getText() + "】"; - LogUtil.APP.info("弹出框对象通过getText获取对象text属性...【Text属性值:{}】",alert.getText()); - break; - default: - break; - } - return result; - } - - public static String driverOperation(WebDriver wd, String operation, String operationValue) throws Exception { - String result = ""; - // 处理页面对象操作 - switch (operation) { - case "open": - wd.get(operationValue); - result = "Open页面...【" + operationValue + "】"; - LogUtil.APP.info("Open页面...【{}】",operationValue); - break; - case "addcookie": - List cookies = buildCookie(operationValue); - if (null != cookies && cookies.size() > 0) { - for (Cookie cookie : cookies) { - wd.manage().addCookie(cookie); - LogUtil.APP.info("添加Cookie:【{}】成功!",cookie); - } - } - result = "添加cookie...【" + operationValue + "】"; - break; - case "exjs": - JavascriptExecutor jse = (JavascriptExecutor) wd; - Object obj = jse.executeScript(operationValue); - if (null != obj) { - String tmp = obj.toString(); - result = (100 < tmp.length()) ? tmp.substring(0, 100) + "..." : tmp; - result = "获取到的值是【" + result + "】"; - LogUtil.APP.info("执行JS...【{}】,返回的结果为:{}",operationValue,result); - } else { - result = "执行JS...【" + operationValue + "】"; - LogUtil.APP.info("{},执行JS返回null或没有返回",result); - } - break; - case "gotodefaultcontent": - wd.switchTo().defaultContent(); - result = "gotodefaultcontent切换至默认页面位置..."; - LogUtil.APP.info(result); - break; - case "gotoparentframe": - wd.switchTo().parentFrame(); - result = "gotoparentframe切换至上一级frame位置..."; - LogUtil.APP.info(result); - break; - case "gettitle": - result = "获取到的值是【" + wd.getTitle() + "】"; - LogUtil.APP.info("获取页面Title...【{}】",wd.getTitle()); - break; - case "getwindowhandle": - result = getTargetWindowHandle(wd, operationValue); - break; - case "gotowindow": - result = switchToTargetWindow(wd, operationValue); - break; - case "closewindow": - wd.close(); - result = "关闭当前浏览器窗口..."; - break; - case "pagerefresh": - wd.navigate().refresh(); - result = "刷新当前浏览器窗口..."; - break; - case "pageforward": - wd.navigate().forward(); - result = "前进当前浏览器窗口..."; - break; - case "pageback": - wd.navigate().back(); - result = "回退当前浏览器窗口..."; - break; - case "timeout": - try { - // 设置页面加载最大时长30秒 - wd.manage().timeouts().pageLoadTimeout(Integer.valueOf(operationValue), TimeUnit.SECONDS); - // 设置元素出现最大时长30秒 - wd.manage().timeouts().implicitlyWait(Integer.valueOf(operationValue), TimeUnit.SECONDS); - result = "当前任务操作等待【" + operationValue + "】秒..."; - LogUtil.APP.info("当前任务操作等待【{}】秒...",operationValue); - break; - } catch (NumberFormatException e) { - LogUtil.APP.error("等待时间转换出现异常!",e); - result = "【等待时间转换出错,请检查参数】"; - break; - } - default: - break; - } - return result; - } - - private static List buildCookie(String operationValue) { - if (StringUtils.isBlank(operationValue)) { - LogUtil.APP.info("获取Cookie值:operationValue为空!"); - return null; - } - try { - JSONArray objects = JSON.parseArray(operationValue); - if (null == objects) { - LogUtil.APP.info("格式化Cookie字符串成JSONArray,对象为空!"); - return null; - } - List result = new ArrayList<>(objects.size()); - for (int i = 0; i < objects.size(); i++) { - JSONObject jsonObject = objects.getJSONObject(i); - if (null == jsonObject) { - continue; - } - String name = jsonObject.getString("name"); - String val = jsonObject.getString("val"); - String domain = jsonObject.getString("domain"); - String path = jsonObject.getString("path"); - // TODO 缓存多长时间,算出失效时间,单位:秒 - //String expire = jsonObject.getString("expire"); - if (!StringUtils.isBlank(name) && !StringUtils.isBlank(val)) { - Cookie cookie = new Cookie(name, val, domain, path, null); - LogUtil.APP.info("解析Cookie成功:【{}】",cookie); - result.add(cookie); - }else{ - LogUtil.APP.warn("cookie:{} 错误,name或是val为空!",jsonObject); - } - } - return result; - } catch (Exception e) { - LogUtil.APP.error("格式化Cookie对象出错,请检查您的格式是否正确!【{}】",operationValue,e); - return null; - } - } - - private static int[] getLocationFromParam(String param, String split) { - int[] location = {0, 0}; - if (null == param || param.trim().isEmpty()) { - return location; - } else { - // 不包含分隔符 - if (! param.contains(split)) { - location[0] = Integer.valueOf(param.trim()); - } else { - String[] tmp = param.split(split, 2); - for (int i = 0; i < 2; i++) { - if (! tmp[i].trim().isEmpty()){ - location[i] = Integer.valueOf(tmp[i].trim()); - } - } - } - } - return location; - } - - /** - * operationValue为目标窗口句柄的下标, 1开始; 小于等于0即获取当前窗口的句柄值 - * 窗口句柄值都已CDwindow-开头, 可以作为预期结果的断言 - * @param driver - * @param target - * @return - * @author Seagull - * @date 2019年8月9日 - */ - private static String getTargetWindowHandle(WebDriver driver, String target) { - String result; - if (null != driver) { - if (!ChangString.isInteger(target)) { - result = windowHandleByTitle(driver, target); - } else { - int index = Integer.valueOf(target); - result = windowHandleByIndex(driver, index); - } - } else { - result = "获取窗口句柄值失败,WebDriver为空"; - } - if (result.contains("获取窗口句柄值失败")){ - LogUtil.APP.warn(result); - } else { - LogUtil.APP.info("获取窗口句柄值成功,目标窗口句柄值为【{}】",result); - } - return result; - } - - private static String windowHandleByTitle(WebDriver driver, String title) { - String result = ""; - String original = driver.getWindowHandle(); - if (title.isEmpty()) { - result = original; - } else { - Set windowHandles = driver.getWindowHandles(); - for (String windowHandle : windowHandles) { - driver.switchTo().window(windowHandle); - if (title.equals(driver.getTitle())) { - result = windowHandle; - break; - } - } - if (0 < windowHandles.size()){ - driver.switchTo().window(original); - } - } - result = result.isEmpty() ? "获取窗口句柄值失败,需要获取窗口句柄值的标题【" + title + "】没有找到" : "获取到的值是【" + result + "】"; - return result; - } - - private static String windowHandleByIndex(WebDriver driver, int index) { - String result; - try { - List windowHandles = new ArrayList<>(driver.getWindowHandles()); - if (index > windowHandles.size()) { - result = "获取窗口句柄值失败,需要获取窗口句柄值的下标【" + index + "】大于当前窗口句柄总数【" + windowHandles.size() + "】"; - } else { - if (0 >= index){ - result = "获取到的值是【" + driver.getWindowHandle() + "】"; - } else{ - result = "获取到的值是【" + windowHandles.get(index - 1) + "】"; - } - } - } catch (IndexOutOfBoundsException e) { - LogUtil.APP.error("获取窗口句柄值出现异常,需要获取窗口句柄值的下标【{}】越界",index,e); - result = "获取窗口句柄值失败,需要获取窗口句柄值的下标【" + index + "】越界"; - } - return result; - } - - // 最长等待30秒, 每500毫秒轮询一次 - private static FluentWait wait(WebDriver driver) { - return new FluentWait<>(driver).withTimeout(Duration.ofSeconds(30)).pollingEvery(Duration.ofMillis(500)); - } - - private static ExpectedCondition windowToBeAvailableAndSwitchToIt(final String nameOrHandleOrTitle) { - return driver -> { - try { - if (null != driver){ - return driver.switchTo().window(nameOrHandleOrTitle); - } else{ - return null; - } - - } catch (NoSuchWindowException windowWithNameOrHandleNotFound) { - try { - return windowByTitle(driver, nameOrHandleOrTitle); - } catch (NoSuchWindowException windowWithTitleNotFound) { - if (ChangString.isInteger(nameOrHandleOrTitle)){ - return windowByIndex(driver, Integer.valueOf(nameOrHandleOrTitle)); - } else{ - return null; - } - } - } - }; - } - - private static WebDriver windowByTitle(WebDriver driver, String title) { - String original = driver.getWindowHandle(); - Set windowHandles = driver.getWindowHandles(); - for (String windowHandle : windowHandles) { - driver.switchTo().window(windowHandle); - if (title.equals(driver.getTitle())) { - return driver; - } - } - if (0 < windowHandles.size()){ - driver.switchTo().window(original); - } - throw new NoSuchWindowException("Window with title[" + title + "] not found"); - } - - private static WebDriver windowByIndex(WebDriver driver, int index) { - try { - List windowHandles = new ArrayList<>(driver.getWindowHandles()); - return driver.switchTo().window(windowHandles.get(index)); - } catch (IndexOutOfBoundsException windowWithIndexNotFound) { - return null; - } - } - - private static String switchToTargetWindow(WebDriver driver, String target) { - String result; - try { - if (null == wait(driver).until(windowToBeAvailableAndSwitchToIt(target))) { - result = "步骤执行失败:切换窗口句柄失败,未找到句柄值为【" + target + "】的对象"; - LogUtil.APP.warn("切换窗口句柄失败,未找到句柄值为【{}】的对象",target); - } else { - result = "切换窗口句柄成功,找到句柄值为【" + target + "】的对象"; - LogUtil.APP.info("切换窗口句柄成功,找到句柄值为【{}】的对象",target); - } - return result; - } catch (TimeoutException e) { - result = "步骤执行失败:切换窗口句柄失败,等待超时,未找到句柄值为【" + target + "】的对象"; - LogUtil.APP.error("切换窗口句柄失败,等待超时,未找到句柄值为【{}】的对象",target,e); - return result; - } - } - -} - +package luckyclient.execution.webdriver; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang3.StringUtils; +import org.openqa.selenium.Alert; +import org.openqa.selenium.Cookie; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.Keys; +import org.openqa.selenium.NoSuchWindowException; +import org.openqa.selenium.Point; +import org.openqa.selenium.TimeoutException; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.support.ui.ExpectedCondition; +import org.openqa.selenium.support.ui.FluentWait; +import org.openqa.selenium.support.ui.Select; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import luckyclient.execution.dispose.ChangString; +import luckyclient.execution.webdriver.ocr.Ocr; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * @date 2017年12月1日 上午9:29:40 + */ +public class EncapsulateOperation { + + public static String selectOperation(WebElement we, String operation, String operationValue) { + String result = ""; + // 下拉框对象处理 + Select select = new Select(we); + + // 处理下拉框事件 + switch (operation) { + case "selectbyvisibletext": + select.selectByVisibleText(operationValue); + result = "下拉框对象通过VisibleText属性选择...【VisibleText属性值:" + operationValue + "】"; + LogUtil.APP.info("下拉框对象通过VisibleText属性选择...【VisibleText属性值:{}】",operationValue); + break; + case "selectbyvalue": + select.selectByValue(operationValue); + result = "下拉框对象通过Value属性选择...【Value属性值:" + operationValue + "】"; + LogUtil.APP.info("下拉框对象通过Value属性选择...【Value属性值:{}】",operationValue); + break; + case "selectbyindex": + select.selectByIndex(Integer.parseInt(operationValue)); + result = "下拉框对象通过Index属性选择...【Index属性值:" + operationValue + "】"; + LogUtil.APP.info("下拉框对象通过Index属性选择...【Index属性值:{}】",operationValue); + break; + case "isselect": + result = "获取到的值是【" + we.isSelected() + "】"; + LogUtil.APP.info("判断对象是否已经被选择...【结果值:{}】",we.isSelected()); + break; + default: + break; + } + return result; + } + + public static String getOperation(WebDriver wd, WebElement we, String operation, String value) { + String result = ""; + // 获取对象处理 + switch (operation) { + case "gettext": + result = "获取到的值是【" + we.getText() + "】"; + LogUtil.APP.info("getText获取对象text属性...【text属性值:{}】",result); + break; // 获取输入框内容 + case "gettagname": + result = "获取到的值是【" + we.getTagName() + "】"; + LogUtil.APP.info("getTagName获取对象tagname属性...【tagname属性值:{}】",result); + break; + case "getattribute": + result = "获取到的值是【" + we.getAttribute(value) + "】"; + LogUtil.APP.info("getAttribute获取对象【{}】属性...【{}属性值:{}】",value,value,result); + break; + case "getcssvalue": + result = "获取到的值是【" + we.getCssValue(value) + "】"; + LogUtil.APP.info("getCssValue获取对象【{}】属性...【{}属性值:{}】",value,value,result); + break; + case "getcaptcha": + result = "获取到的值是【" + Ocr.getCAPTCHA(wd, we) + "】"; + LogUtil.APP.info("getcaptcha获取验证码...【验证码值:{}】",result); + break; + default: + break; + } + return result; + } + + public static String actionWeOperation(WebDriver wd, WebElement we, String operation, String operationValue, String property, String propertyValue) { + String result = ""; + Actions action = new Actions(wd); + // action处理 + switch (operation) { + //鼠标左键点击 + case "mouselkclick": + action.click(we).perform(); + result = "mouselkclick鼠标左键点击对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; + LogUtil.APP.info("mouselkclick鼠标左键点击对象...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); + break; + case "mouserkclick": + action.contextClick(we).perform(); + result = "mouserkclick鼠标右键点击对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; + LogUtil.APP.info("mouserkclick鼠标右键点击对象...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); + break; + case "mousedclick": + action.doubleClick(we).perform(); + result = "mousedclick鼠标双击对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; + LogUtil.APP.info("mousedclick鼠标双击对象...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); + break; + case "mouseclickhold": + action.clickAndHold(we).perform(); + result = "mouseclickhold鼠标点击对象后不释放...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; + LogUtil.APP.info("mouseclickhold鼠标点击对象后不释放...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); + break; + case "mousedrag": + int[] location = getLocationFromParam(operationValue); +// String[] temp = operationValue.split(",", -1); + action.dragAndDropBy(we, location[0], location[1]).perform(); + result = "mousedrag鼠标移动至对象相对坐标...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "; 相对坐标(x,y):" + location[0] + "," + location[1] + "】"; + LogUtil.APP.info("mousedrag鼠标移动至对象相对坐标...【对象定位属性:{}; 定位属性值:{}; 相对坐标(x,y):{},{}】",property,propertyValue,location[0],location[1]); + break; + case "mouseto": + int[] location1 = getLocationFromParam(operationValue); +// String[] temp1 = operationValue.split(",", -1); + action.moveToElement(we, location1[0], location1[1]).perform(); + result = "mouseto鼠标移动至对象相对坐标...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "; 相对坐标(x,y):" + location1[0] + "," + location1[1] + "】"; + LogUtil.APP.info("mouseto鼠标移动至对象相对坐标...【对象定位属性:{}; 定位属性值:{}; 相对坐标(x,y):{},{}】",property,propertyValue,location1[0],location1[1]); + break; + case "mouserelease": + action.release(we).perform(); + result = "mouserelease鼠标释放..."; + LogUtil.APP.info("mouserelease鼠标释放..."); + break; + default: + break; + } + return result; + } + + public static String actionOperation(WebDriver wd, String operation, String operationValue) { + String result = ""; + Actions action = new Actions(wd); + // action处理 + switch (operation) { + //鼠标左键点击 + case "mouselkclick": + action.click().perform(); + result = "mouselkclick鼠标左键点击当前位置..."; + LogUtil.APP.info(result); + break; + case "mouserkclick": + action.contextClick().perform(); + result = "mouserkclick鼠标右键点击当前位置..."; + LogUtil.APP.info(result); + break; + case "mousedclick": + action.doubleClick().perform(); + result = "mousedclick鼠标双击当前位置..."; + LogUtil.APP.info(result); + break; + case "mouseclickhold": + action.clickAndHold().perform(); + result = "mouseclickhold鼠标点击当前位置后不释放..."; + LogUtil.APP.info(result); + break; + case "mouseto": + int[] location = getLocationFromParam(operationValue); +// String[] temp1 = operationValue.split(",", -1); + action.moveByOffset(location[0], location[1]).perform(); + result = "mouseto鼠标移动至对象相对坐标...坐标x:" + location[0] + " 坐标y:" + location[1]; + LogUtil.APP.info("mouseto鼠标移动至对象相对坐标...坐标x:{} 坐标y:{}",location[0],location[1]); + break; + case "mouserelease": + action.release().perform(); + result = "mouserelease鼠标释放..."; + LogUtil.APP.info(result); + break; + case "mousekey": + switch (operationValue) { + case "tab": + action.sendKeys(Keys.TAB).perform(); + result = "键盘操作TAB键..."; + LogUtil.APP.info(result); + break; + case "space": + action.sendKeys(Keys.SPACE).perform(); + result = "键盘操作SPACE键..."; + LogUtil.APP.info(result); + break; + case "ctrl": + action.sendKeys(Keys.CONTROL).perform(); + result = "键盘操作CONTROL键..."; + LogUtil.APP.info(result); + break; + case "shift": + action.sendKeys(Keys.SHIFT).perform(); + result = "键盘操作SHIFT键..."; + LogUtil.APP.info(result); + break; + case "enter": + action.sendKeys(Keys.ENTER).perform(); + result = "键盘操作ENTER键..."; + LogUtil.APP.info(result); + break; + default: + break; + } + break; + default: + break; + } + return result; + } + + public static String objectOperation(WebDriver wd, WebElement we, String operation, String operationValue, String property, String propertyValue) { + String result = ""; + // 处理WebElement对象操作 + switch (operation) { + case "click": + we.click(); + result = "click点击对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; + LogUtil.APP.info("click点击对象...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); + break; + case "sendkeys": + we.sendKeys(operationValue); + result = "sendKeys对象输入...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "; 操作值:" + operationValue + "】"; + LogUtil.APP.info("sendKeys对象输入...【对象定位属性:{}; 定位属性值:{}; 操作值:{}】",property,propertyValue,operationValue); + break; + case "clear": + we.clear(); + result = "clear清空输入框...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; + LogUtil.APP.info("clear清空输入框...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); + break; // 清空输入框 + case "gotoframe": + wd.switchTo().frame(we); + result = "gotoframe切换Frame...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; + LogUtil.APP.info("gotoframe切换Frame...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); + break; + case "isenabled": + result = "获取到的值是【"+we.isEnabled()+"】"; + LogUtil.APP.info("获取到的值是【{}】",we.isEnabled()); + break; + case "isdisplayed": + result = "获取到的值是【" + we.isDisplayed() + "】"; + LogUtil.APP.info("获取到的值是【{}】", we.isDisplayed()); + break; + case "exjsob": + JavascriptExecutor jse = (JavascriptExecutor) wd; + Object obj = jse.executeScript(operationValue, we); + if (null != obj) { + String tmp = obj.toString(); + result = (100 < tmp.length()) ? tmp.substring(0, 100) + "..." : tmp; + result = "获取到的值是【" + result + "】"; + LogUtil.APP.info("执行JS...【{}】,返回的结果为:{}",operationValue,result); + } else { + result = "执行JS...【" + operationValue + "】"; + LogUtil.APP.info("执行JS...【{}】",operationValue); + } + break; + case "scrollto": + Point location = we.getLocation(); + ((JavascriptExecutor) wd).executeScript("window.scrollTo(" + location.getX() + ", " + location.getY() + ")"); + result = "滚动到目标对象...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "; 对象坐标(x,y):" + location.getX() + "," + location.getY() + "】"; + LogUtil.APP.info("滚动到目标对象...【对象定位属性:{}; 定位属性值:{}; 对象坐标(x,y):{},{}】",property,propertyValue,location.getX(),location.getY()); + break; + case "scrollintoview": + // 此方法可以用执行js命令来代替 + ((JavascriptExecutor) wd).executeScript("arguments[0].scrollIntoView(" + operationValue + ")", we); + result = "将目标对象滚动到可视...【对象定位属性:" + property + "; 定位属性值:" + propertyValue + "】"; + LogUtil.APP.info("将目标对象滚动到可视...【对象定位属性:{}; 定位属性值:{}】",property,propertyValue); + break; + default: + break; + } + return result; + } + + public static String alertOperation(WebDriver wd, String operation) { + String result = ""; + Alert alert = wd.switchTo().alert(); + switch (operation) { + case "alertaccept": + alert.accept(); + result = "弹出框对象点击同意..."; + LogUtil.APP.info(result); + break; + case "alertdismiss": + alert.dismiss(); + result = "弹出框对象点击取消..."; + LogUtil.APP.info(result); + break; + case "alertgettext": + result = "获取到的值是【" + alert.getText() + "】"; + LogUtil.APP.info("弹出框对象通过getText获取对象text属性...【Text属性值:{}】",alert.getText()); + break; + default: + break; + } + return result; + } + + public static String driverOperation(WebDriver wd, String operation, String operationValue) { + String result = ""; + // 处理页面对象操作 + switch (operation) { + case "open": + wd.get(operationValue); + result = "Open页面...【" + operationValue + "】"; + LogUtil.APP.info("Open页面...【{}】",operationValue); + break; + case "addcookie": + List cookies = buildCookie(operationValue); + if (null != cookies && cookies.size() > 0) { + for (Cookie cookie : cookies) { + wd.manage().addCookie(cookie); + LogUtil.APP.info("添加Cookie:【{}】成功!",cookie); + } + } + result = "添加cookie...【" + operationValue + "】"; + break; + case "exjs": + JavascriptExecutor jse = (JavascriptExecutor) wd; + Object obj = jse.executeScript(operationValue); + if (null != obj) { + String tmp = obj.toString(); + result = (100 < tmp.length()) ? tmp.substring(0, 100) + "..." : tmp; + result = "获取到的值是【" + result + "】"; + LogUtil.APP.info("执行JS...【{}】,返回的结果为:{}",operationValue,result); + } else { + result = "执行JS...【" + operationValue + "】"; + LogUtil.APP.info("{},执行JS返回null或没有返回",result); + } + break; + case "gotodefaultcontent": + wd.switchTo().defaultContent(); + result = "gotodefaultcontent切换至默认页面位置..."; + LogUtil.APP.info(result); + break; + case "gotoparentframe": + wd.switchTo().parentFrame(); + result = "gotoparentframe切换至上一级frame位置..."; + LogUtil.APP.info(result); + break; + case "gettitle": + result = "获取到的值是【" + wd.getTitle() + "】"; + LogUtil.APP.info("获取页面Title...【{}】",wd.getTitle()); + break; + case "getwindowhandle": + result = getTargetWindowHandle(wd, operationValue); + break; + case "gotowindow": + result = switchToTargetWindow(wd, operationValue); + break; + case "closewindow": + wd.close(); + result = "关闭当前浏览器窗口..."; + break; + case "pagerefresh": + wd.navigate().refresh(); + result = "刷新当前浏览器窗口..."; + break; + case "pageforward": + wd.navigate().forward(); + result = "前进当前浏览器窗口..."; + break; + case "pageback": + wd.navigate().back(); + result = "回退当前浏览器窗口..."; + break; + case "timeout": + try { + // 设置页面加载最大时长30秒 + wd.manage().timeouts().pageLoadTimeout(Integer.parseInt(operationValue), TimeUnit.SECONDS); + // 设置元素出现最大时长30秒 + wd.manage().timeouts().implicitlyWait(Integer.parseInt(operationValue), TimeUnit.SECONDS); + result = "当前任务操作等待【" + operationValue + "】秒..."; + LogUtil.APP.info("当前任务操作等待【{}】秒...",operationValue); + break; + } catch (NumberFormatException e) { + LogUtil.APP.error("等待时间转换出现异常!",e); + result = "【等待时间转换出错,请检查参数】"; + break; + } + default: + break; + } + return result; + } + + private static List buildCookie(String operationValue) { + if (StringUtils.isBlank(operationValue)) { + LogUtil.APP.info("获取Cookie值:operationValue为空!"); + return null; + } + try { + JSONArray objects = JSON.parseArray(operationValue); + if (null == objects) { + LogUtil.APP.info("格式化Cookie字符串成JSONArray,对象为空!"); + return null; + } + List result = new ArrayList<>(objects.size()); + for (int i = 0; i < objects.size(); i++) { + JSONObject jsonObject = objects.getJSONObject(i); + if (null == jsonObject) { + continue; + } + String name = jsonObject.getString("name"); + String val = jsonObject.getString("val"); + String domain = jsonObject.getString("domain"); + String path = jsonObject.getString("path"); + // TODO 缓存多长时间,算出失效时间,单位:秒 + //String expire = jsonObject.getString("expire"); + if (!StringUtils.isBlank(name) && !StringUtils.isBlank(val)) { + Cookie cookie = new Cookie(name, val, domain, path, null); + LogUtil.APP.info("解析Cookie成功:【{}】",cookie); + result.add(cookie); + }else{ + LogUtil.APP.warn("cookie:{} 错误,name或是val为空!",jsonObject); + } + } + return result; + } catch (Exception e) { + LogUtil.APP.error("格式化Cookie对象出错,请检查您的格式是否正确!【{}】",operationValue,e); + return null; + } + } + + private static int[] getLocationFromParam(String param) { + int[] location = {0, 0}; + if (null == param || param.trim().isEmpty()) { + return location; + } else { + // 不包含分隔符 + if (! param.contains(",")) { + location[0] = Integer.parseInt(param.trim()); + } else { + String[] tmp = param.split(",", 2); + for (int i = 0; i < 2; i++) { + if (! tmp[i].trim().isEmpty()){ + location[i] = Integer.parseInt(tmp[i].trim()); + } + } + } + } + return location; + } + + /** + * operationValue为目标窗口句柄的下标, 1开始; 小于等于0即获取当前窗口的句柄值 + * 窗口句柄值都已CDwindow-开头, 可以作为预期结果的断言 + * @param driver 驱动 + * @param target 句柄字符串 + * @return 返回获取结果 + * @author Seagull + * @date 2019年8月9日 + */ + private static String getTargetWindowHandle(WebDriver driver, String target) { + String result; + if (null != driver) { + if (!ChangString.isInteger(target)) { + result = windowHandleByTitle(driver, target); + } else { + int index = Integer.parseInt(target); + result = windowHandleByIndex(driver, index); + } + } else { + result = "获取窗口句柄值失败,WebDriver为空"; + } + if (result.contains("获取窗口句柄值失败")){ + LogUtil.APP.warn(result); + } else { + LogUtil.APP.info("获取窗口句柄值成功,目标窗口句柄值为【{}】",result); + } + return result; + } + + private static String windowHandleByTitle(WebDriver driver, String title) { + String result = ""; + String original = driver.getWindowHandle(); + if (title.isEmpty()) { + result = original; + } else { + Set windowHandles = driver.getWindowHandles(); + for (String windowHandle : windowHandles) { + driver.switchTo().window(windowHandle); + if (title.equals(driver.getTitle())) { + result = windowHandle; + break; + } + } + if (0 < windowHandles.size()){ + driver.switchTo().window(original); + } + } + result = result.isEmpty() ? "获取窗口句柄值失败,需要获取窗口句柄值的标题【" + title + "】没有找到" : "获取到的值是【" + result + "】"; + return result; + } + + private static String windowHandleByIndex(WebDriver driver, int index) { + String result; + try { + List windowHandles = new ArrayList<>(driver.getWindowHandles()); + if (index > windowHandles.size()) { + result = "获取窗口句柄值失败,需要获取窗口句柄值的下标【" + index + "】大于当前窗口句柄总数【" + windowHandles.size() + "】"; + } else { + if (0 >= index){ + result = "获取到的值是【" + driver.getWindowHandle() + "】"; + } else{ + result = "获取到的值是【" + windowHandles.get(index - 1) + "】"; + } + } + } catch (IndexOutOfBoundsException e) { + LogUtil.APP.error("获取窗口句柄值出现异常,需要获取窗口句柄值的下标【{}】越界",index,e); + result = "获取窗口句柄值失败,需要获取窗口句柄值的下标【" + index + "】越界"; + } + return result; + } + + // 最长等待30秒, 每500毫秒轮询一次 + private static FluentWait wait(WebDriver driver) { + return new FluentWait<>(driver).withTimeout(Duration.ofSeconds(30)).pollingEvery(Duration.ofMillis(500)); + } + + private static ExpectedCondition windowToBeAvailableAndSwitchToIt(final String nameOrHandleOrTitle) { + return driver -> { + try { + if (null != driver){ + return driver.switchTo().window(nameOrHandleOrTitle); + } else{ + return null; + } + + } catch (NoSuchWindowException windowWithNameOrHandleNotFound) { + try { + return windowByTitle(driver, nameOrHandleOrTitle); + } catch (NoSuchWindowException windowWithTitleNotFound) { + if (ChangString.isInteger(nameOrHandleOrTitle)){ + return windowByIndex(driver, Integer.parseInt(nameOrHandleOrTitle)); + } else{ + return null; + } + } + } + }; + } + + private static WebDriver windowByTitle(WebDriver driver, String title) { + String original = driver.getWindowHandle(); + Set windowHandles = driver.getWindowHandles(); + for (String windowHandle : windowHandles) { + driver.switchTo().window(windowHandle); + if (title.equals(driver.getTitle())) { + return driver; + } + } + if (0 < windowHandles.size()){ + driver.switchTo().window(original); + } + throw new NoSuchWindowException("Window with title[" + title + "] not found"); + } + + private static WebDriver windowByIndex(WebDriver driver, int index) { + try { + List windowHandles = new ArrayList<>(driver.getWindowHandles()); + return driver.switchTo().window(windowHandles.get(index)); + } catch (IndexOutOfBoundsException windowWithIndexNotFound) { + return null; + } + } + + private static String switchToTargetWindow(WebDriver driver, String target) { + String result; + try { + if (null == wait(driver).until(windowToBeAvailableAndSwitchToIt(target))) { + result = "步骤执行失败:切换窗口句柄失败,未找到句柄值为【" + target + "】的对象"; + LogUtil.APP.warn("切换窗口句柄失败,未找到句柄值为【{}】的对象",target); + } else { + result = "切换窗口句柄成功,找到句柄值为【" + target + "】的对象"; + LogUtil.APP.info("切换窗口句柄成功,找到句柄值为【{}】的对象",target); + } + return result; + } catch (TimeoutException e) { + result = "步骤执行失败:切换窗口句柄失败,等待超时,未找到句柄值为【" + target + "】的对象"; + LogUtil.APP.error("切换窗口句柄失败,等待超时,未找到句柄值为【{}】的对象",target,e); + return result; + } + } + +} + diff --git a/src/main/java/luckyclient/execution/webdriver/TestGoogle.java b/src/main/java/luckyclient/execution/webdriver/TestGoogle.java deleted file mode 100644 index 9d0bc5f..0000000 --- a/src/main/java/luckyclient/execution/webdriver/TestGoogle.java +++ /dev/null @@ -1,21 +0,0 @@ -package luckyclient.execution.webdriver; - -import java.io.IOException; - -/** - * - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull - * ================================================================= - * @author Seagull - * @date 2019年8月8日 - */ -public class TestGoogle { - - public static void main(String[] args) throws InterruptedException, IOException { - // TODO Auto-generated method stub - - } - -} diff --git a/src/main/java/luckyclient/execution/webdriver/WebDriverInitialization.java b/src/main/java/luckyclient/execution/webdriver/WebDriverInitialization.java index 4bc6f9d..9187dd8 100644 --- a/src/main/java/luckyclient/execution/webdriver/WebDriverInitialization.java +++ b/src/main/java/luckyclient/execution/webdriver/WebDriverInitialization.java @@ -1,132 +1,134 @@ -package luckyclient.execution.webdriver; - -import java.io.File; -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebDriverException; -import org.openqa.selenium.chrome.ChromeDriver; -import org.openqa.selenium.chrome.ChromeOptions; -import org.openqa.selenium.edge.EdgeDriver; -import org.openqa.selenium.firefox.FirefoxDriver; -import org.openqa.selenium.firefox.FirefoxOptions; -import org.openqa.selenium.ie.InternetExplorerDriver; - -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * @date 2017年12月1日 上午9:29:40 - * - */ -public class WebDriverInitialization{ - private static final String OS=System.getProperty("os.name").toLowerCase(); - /** - * 初始化WebDriver - * @param drivertype - * @return - * @throws WebDriverException - * @throws IOException - */ - public static WebDriver setWebDriverForTask(int drivertype) throws WebDriverException,IOException{ - // 参数为空 - File directory = new File(""); - String drivenpath=directory.getCanonicalPath()+File.separator+"BrowserDriven"+File.separator; - WebDriver webDriver = null; - LogUtil.APP.info("准备初始化WebDriver对象...检查到当前操作系统是:{}",OS); - if(drivertype==0){ - if(OS.startsWith("win")){ - System.setProperty("webdriver.ie.driver",drivenpath+"IEDriverServer.exe"); - webDriver = new InternetExplorerDriver(); - }else{ - LogUtil.APP.warn("当前操作系统无法进行IE浏览器的Web UI测试,请选择火狐或是谷歌浏览器!"); - } - }else if(drivertype==1){ - FirefoxOptions options = new FirefoxOptions(); - if(OS.startsWith("win")){ - System.setProperty("webdriver.gecko.driver",drivenpath+"geckodriver.exe"); - }else if(OS.contains("mac")){ - options.addArguments("start-maximized"); - System.setProperty("webdriver.gecko.driver",drivenpath+"geckodriver_mac"); - }else{ - LogUtil.APP.info("检测到当前系统环境是Linux,默认使用headless方式运行Firefox浏览器的Web UI自动化..."); - //无界面参数 - options.setHeadless(true); - //禁用沙盒 - options.addArguments("no-sandbox"); - options.addArguments("start-maximized"); - System.setProperty("webdriver.gecko.driver",drivenpath+"geckodriver_linux64"); - } - webDriver = new FirefoxDriver(options); - }else if(drivertype==2){ - ChromeOptions options = new ChromeOptions(); - if(OS.startsWith("win")){ - System.setProperty("webdriver.chrome.driver",drivenpath+"chromedriver.exe"); - }else if(OS.contains("mac")){ - options.addArguments("start-maximized"); - System.setProperty("webdriver.chrome.driver",drivenpath+"chromedriver_mac"); - }else{ - LogUtil.APP.info("检测到当前系统环境是Linux,默认使用headless方式运行Chrome浏览器的Web UI自动化..."); - //无界面参数 - options.setHeadless(true); - //禁用沙盒 - options.addArguments("no-sandbox"); - options.addArguments("start-maximized"); - System.setProperty("webdriver.chrome.driver",drivenpath+"chromedriver_linux64"); - } - webDriver = new ChromeDriver(options); - }else if(drivertype==3){ - if(OS.startsWith("win")){ - System.setProperty("webdriver.edge.driver",drivenpath+"msedgedriver.exe"); - webDriver = new EdgeDriver(); - }else if(OS.contains("mac")){ - System.setProperty("webdriver.edge.driver",drivenpath+"msedgedriver_mac"); - webDriver = new EdgeDriver(); - }else{ - LogUtil.APP.warn("当前操作系统无法进行Edge浏览器的Web UI测试,请选择火狐或是谷歌浏览器!"); - } - }else{ - LogUtil.APP.warn("浏览器类型标识:{},获取到的浏览器类型标识未定义,默认IE浏览器进行执行....",drivertype); - System.setProperty("webdriver.ie.driver",drivenpath+"IEDriverServer.exe"); - webDriver = new InternetExplorerDriver(); - } - - //解决webdriver在unix环境中,最大化会出现异常的bug,unix最大化在options中单独设置 - if(OS.startsWith("win")){ - webDriver.manage().window().maximize(); - } - - //设置页面加载最大时长30秒 - webDriver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS); - //设置元素出现最大时长30秒 - webDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); - - return webDriver; - } - - /** - * 初始化WebDriver - * @return - * @throws IOException - */ - public static WebDriver setWebDriverForLocal() throws IOException{ - File directory = new File(""); - String drivenpath=directory.getCanonicalPath()+File.separator+"BrowserDriven"+File.separator; - System.setProperty("webdriver.ie.driver",drivenpath+"IEDriverServer.exe"); - WebDriver webDriver = new InternetExplorerDriver(); - webDriver.manage().window().maximize(); - //设置页面加载最大时长30秒 - webDriver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS); - //设置元素出现最大时长30秒 - webDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); - return webDriver; - } - -} +package luckyclient.execution.webdriver; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebDriverException; +import org.openqa.selenium.chrome.ChromeDriver; +import org.openqa.selenium.chrome.ChromeOptions; +import org.openqa.selenium.edge.EdgeDriver; +import org.openqa.selenium.firefox.FirefoxDriver; +import org.openqa.selenium.firefox.FirefoxOptions; +import org.openqa.selenium.ie.InternetExplorerDriver; + +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * @date 2017年12月1日 上午9:29:40 + * + */ +public class WebDriverInitialization{ + private static final String OS=System.getProperty("os.name").toLowerCase(); + /** + * 初始化WebDriver + * @param drivertype 浏览器类型 + * @return 返回初始化结果 + * @throws WebDriverException 驱动抛出异常 + * @throws IOException 读取配置文件异常 + */ + public static WebDriver setWebDriverForTask(int drivertype) throws WebDriverException,IOException{ + // 参数为空 + File directory = new File(""); + String drivenpath=directory.getCanonicalPath()+File.separator+"BrowserDriven"+File.separator; + WebDriver webDriver = null; + LogUtil.APP.info("准备初始化WebDriver对象...检查到当前操作系统是:{}",OS); + if(drivertype==0){ + if(OS.startsWith("win")){ + System.setProperty("webdriver.ie.driver",drivenpath+"IEDriverServer.exe"); + webDriver = new InternetExplorerDriver(); + }else{ + LogUtil.APP.warn("当前操作系统无法进行IE浏览器的Web UI测试,请选择火狐或是谷歌浏览器!"); + } + }else if(drivertype==1){ + FirefoxOptions options = new FirefoxOptions(); + if(OS.startsWith("win")){ + System.setProperty("webdriver.gecko.driver",drivenpath+"geckodriver.exe"); + }else if(OS.contains("mac")){ + options.addArguments("start-maximized"); + System.setProperty("webdriver.gecko.driver",drivenpath+"geckodriver_mac"); + }else{ + LogUtil.APP.info("检测到当前系统环境是Linux,默认使用headless方式运行Firefox浏览器的Web UI自动化..."); + //无界面参数 + options.setHeadless(true); + //禁用沙盒 + options.addArguments("no-sandbox"); + options.addArguments("start-maximized"); + System.setProperty("webdriver.gecko.driver",drivenpath+"geckodriver_linux64"); + } + webDriver = new FirefoxDriver(options); + }else if(drivertype==2){ + ChromeOptions options = new ChromeOptions(); + if(OS.startsWith("win")){ + System.setProperty("webdriver.chrome.driver",drivenpath+"chromedriver.exe"); + }else if(OS.contains("mac")){ + options.addArguments("start-maximized"); + System.setProperty("webdriver.chrome.driver",drivenpath+"chromedriver_mac"); + }else{ + LogUtil.APP.info("检测到当前系统环境是Linux,默认使用headless方式运行Chrome浏览器的Web UI自动化..."); + //无界面参数 + options.setHeadless(true); + //禁用沙盒 + options.addArguments("no-sandbox"); + options.addArguments("start-maximized"); + System.setProperty("webdriver.chrome.driver",drivenpath+"chromedriver_linux64"); + } + webDriver = new ChromeDriver(options); + }else if(drivertype==3){ + if(OS.startsWith("win")){ + System.setProperty("webdriver.edge.driver",drivenpath+"msedgedriver.exe"); + webDriver = new EdgeDriver(); + }else if(OS.contains("mac")){ + System.setProperty("webdriver.edge.driver",drivenpath+"msedgedriver_mac"); + webDriver = new EdgeDriver(); + }else{ + LogUtil.APP.warn("当前操作系统无法进行Edge浏览器的Web UI测试,请选择火狐或是谷歌浏览器!"); + } + }else{ + LogUtil.APP.warn("浏览器类型标识:{},获取到的浏览器类型标识未定义,默认IE浏览器进行执行....",drivertype); + System.setProperty("webdriver.ie.driver",drivenpath+"IEDriverServer.exe"); + webDriver = new InternetExplorerDriver(); + } + + //解决webdriver在unix环境中,最大化会出现异常的bug,unix最大化在options中单独设置 + if(OS.startsWith("win")){ + assert webDriver != null; + webDriver.manage().window().maximize(); + } + + //设置页面加载最大时长30秒 + assert webDriver != null; + webDriver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS); + //设置元素出现最大时长30秒 + webDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); + + return webDriver; + } + + /** + * 初始化WebDriver + * @return 返回初始化结果 + * @throws IOException 读取配置文件异常 + */ + public static WebDriver setWebDriverForLocal() throws IOException{ + File directory = new File(""); + String drivenpath=directory.getCanonicalPath()+File.separator+"BrowserDriven"+File.separator; + System.setProperty("webdriver.ie.driver",drivenpath+"IEDriverServer.exe"); + WebDriver webDriver = new InternetExplorerDriver(); + webDriver.manage().window().maximize(); + //设置页面加载最大时长30秒 + webDriver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS); + //设置元素出现最大时长30秒 + webDriver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS); + return webDriver; + } + +} diff --git a/src/main/java/luckyclient/execution/webdriver/WebTestControl.java b/src/main/java/luckyclient/execution/webdriver/WebTestControl.java index f1d1880..cd3b26a 100644 --- a/src/main/java/luckyclient/execution/webdriver/WebTestControl.java +++ b/src/main/java/luckyclient/execution/webdriver/WebTestControl.java @@ -39,7 +39,7 @@ public class WebTestControl { /** * 控制台模式调度计划执行用例 - * @param planname + * @param planname 计划名称 */ public static void manualExecutionPlan(String planname) { // 不记日志到数据库 @@ -54,7 +54,7 @@ public class WebTestControl { } serverOperation caselog = new serverOperation(); List testCases = GetServerApi.getCasesbyplanname(planname); - List pcplist = new ArrayList(); + List pcplist = new ArrayList<>(); if (testCases.size() != 0) { pcplist = GetServerApi.cgetParamsByProjectid(String.valueOf(testCases.get(0).getProjectId())); } @@ -69,14 +69,14 @@ public class WebTestControl { LogUtil.APP.info("开始执行第{}条用例:【{}】......",i,testcase.getCaseSign()); try { WebCaseExecution.caseExcution(testcase, steps, taskid, wd, caselog, pcplist); - } catch (InterruptedException e) { - // TODO Auto-generated catch block + } catch (Exception e) { LogUtil.APP.error("用户执行过程中抛出异常!", e); } LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); } LogUtil.APP.info("当前项目测试计划中的用例已经全部执行完成..."); // 关闭浏览器 + assert wd != null; wd.quit(); } @@ -90,12 +90,12 @@ public class WebTestControl { List pcplist = GetServerApi.cgetParamsByProjectid(task.getProjectId().toString()); TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(task.getTaskId()); String projectname = taskScheduling.getProject().getProjectName(); - task = GetServerApi.cgetTaskbyid(Integer.valueOf(taskid)); + task = GetServerApi.cgetTaskbyid(Integer.parseInt(taskid)); String jobname = taskScheduling.getSchedulingName(); int drivertype = serverOperation.querydrivertype(taskid); int[] tastcount = null; // 判断是否要自动重启TOMCAT - if (restartstatus.indexOf("Status:true") > -1) { + if (restartstatus.contains("Status:true")) { // 判断是否构建是否成功 if (BuildResult.SUCCESS.equals(buildResult)) { WebDriver wd = null; @@ -123,7 +123,7 @@ public class WebTestControl { // 插入开始执行的用例 caselog.insertTaskCaseExecute(taskid, taskScheduling.getProjectId(),testcase.getCaseId(),testcase.getCaseSign(), testcase.getCaseName(), 4); WebCaseExecution.caseExcution(testcase, steps, taskid, wd, caselog, pcplist); - } catch (InterruptedException e) { + } catch (Exception e) { // TODO Auto-generated catch block LogUtil.APP.error("用户执行过程中抛出异常!", e); } @@ -137,6 +137,7 @@ public class WebTestControl { HtmlMail.htmlContentFormat(tastcount, taskid, buildResult.toString(), restartstatus, testtime, jobname), taskid, taskScheduling, tastcount); // 关闭浏览器 + assert wd != null; wd.quit(); } else { LogUtil.APP.warn("项目构建失败,自动化测试自动退出!请前往JENKINS中检查项目构建情况。"); diff --git a/src/main/java/luckyclient/execution/webdriver/ex/WebBatchExecute.java b/src/main/java/luckyclient/execution/webdriver/ex/WebBatchExecute.java index 55163fc..bdf544d 100644 --- a/src/main/java/luckyclient/execution/webdriver/ex/WebBatchExecute.java +++ b/src/main/java/luckyclient/execution/webdriver/ex/WebBatchExecute.java @@ -1,82 +1,80 @@ -package luckyclient.execution.webdriver.ex; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.List; - -import org.openqa.selenium.WebDriver; - -import luckyclient.execution.httpinterface.TestControl; -import luckyclient.execution.webdriver.WebDriverInitialization; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.remote.entity.TaskExecute; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * @date 2017年12月1日 上午9:29:40 - * - */ -public class WebBatchExecute{ - - public static void batchCaseExecuteForTast(String projectname,String taskid,String batchcase) throws IOException{ - //记录日志到数据库 - serverOperation.exetype = 0; - TestControl.TASKID = taskid; - int drivertype = serverOperation.querydrivertype(taskid); - WebDriver wd = null; - try { - wd = WebDriverInitialization.setWebDriverForTask(drivertype); - } catch (MalformedURLException e1) { - // TODO Auto-generated catch block - LogUtil.APP.error("初始化WebDriver出现异常!", e1); - } - serverOperation caselog = new serverOperation(); - TaskExecute task=GetServerApi.cgetTaskbyid(Integer.valueOf(taskid)); - List pcplist=GetServerApi.cgetParamsByProjectid(task.getProjectId().toString()); - //执行全部非成功状态用例 - if(batchcase.indexOf("ALLFAIL")>-1){ - List caseIdList = caselog.getCaseListForUnSucByTaskId(taskid); - for(int i=0;i steps=GetServerApi.getStepsbycaseid(testcase.getCaseId()); - //删除旧的日志 - serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); - try { - WebCaseExecution.caseExcution(testcase, steps, taskid,wd,caselog,pcplist); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - LogUtil.APP.error("用户执行过程中抛出异常!", e); - } - } - }else{ //批量执行用例 - String[] temp=batchcase.split("\\#"); - for(int i=0;i steps=GetServerApi.getStepsbycaseid(testcase.getCaseId()); - //删除旧的日志 - serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); - try { - WebCaseExecution.caseExcution(testcase, steps,taskid,wd,caselog,pcplist); - } catch (InterruptedException e) { - // TODO Auto-generated catch block - LogUtil.APP.error("用户执行过程中抛出异常!", e); - } - } - } - serverOperation.updateTaskExecuteData(taskid, 0,2); - //关闭浏览器 - wd.quit(); - } - -} +package luckyclient.execution.webdriver.ex; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.List; + +import org.openqa.selenium.WebDriver; + +import luckyclient.execution.httpinterface.TestControl; +import luckyclient.execution.webdriver.WebDriverInitialization; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.remote.entity.TaskExecute; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * @date 2017年12月1日 上午9:29:40 + * + */ +public class WebBatchExecute{ + + public static void batchCaseExecuteForTast(String taskid, String batchcase) throws IOException{ + //记录日志到数据库 + serverOperation.exetype = 0; + TestControl.TASKID = taskid; + int drivertype = serverOperation.querydrivertype(taskid); + WebDriver wd = null; + try { + wd = WebDriverInitialization.setWebDriverForTask(drivertype); + } catch (MalformedURLException e1) { + LogUtil.APP.error("初始化WebDriver出现异常!", e1); + } + serverOperation caselog = new serverOperation(); + TaskExecute task=GetServerApi.cgetTaskbyid(Integer.parseInt(taskid)); + List pcplist=GetServerApi.cgetParamsByProjectid(task.getProjectId().toString()); + //执行全部非成功状态用例 + if(batchcase.contains("ALLFAIL")){ + List caseIdList = caselog.getCaseListForUnSucByTaskId(taskid); + for (Integer integer : caseIdList) { + ProjectCase testcase = GetServerApi.cGetCaseByCaseId(integer); + List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); + //删除旧的日志 + serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); + try { + WebCaseExecution.caseExcution(testcase, steps, taskid, wd, caselog, pcplist); + } catch (Exception e) { + LogUtil.APP.error("用户执行过程中抛出异常!", e); + } + } + }else{ //批量执行用例 + String[] temp=batchcase.split("#"); + for (String s : temp) { + ProjectCase testcase = GetServerApi.cGetCaseByCaseId(Integer.valueOf(s)); + List steps = GetServerApi.getStepsbycaseid(testcase.getCaseId()); + //删除旧的日志 + serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); + try { + WebCaseExecution.caseExcution(testcase, steps, taskid, wd, caselog, pcplist); + } catch (Exception e) { + LogUtil.APP.error("用户执行过程中抛出异常!", e); + } + } + } + serverOperation.updateTaskExecuteData(taskid, 0,2); + //关闭浏览器 + assert wd != null; + wd.quit(); + } + +} diff --git a/src/main/java/luckyclient/execution/webdriver/ex/WebCaseExecution.java b/src/main/java/luckyclient/execution/webdriver/ex/WebCaseExecution.java index 8dac2a7..aff00a0 100644 --- a/src/main/java/luckyclient/execution/webdriver/ex/WebCaseExecution.java +++ b/src/main/java/luckyclient/execution/webdriver/ex/WebCaseExecution.java @@ -1,336 +1,335 @@ -package luckyclient.execution.webdriver.ex; - -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.openqa.selenium.By; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.WebElement; - -import luckyclient.execution.dispose.ActionManageForSteps; -import luckyclient.execution.dispose.ParamsManageForSteps; -import luckyclient.execution.httpinterface.TestCaseExecution; -import luckyclient.execution.httpinterface.analyticsteps.InterfaceAnalyticCase; -import luckyclient.execution.webdriver.BaseWebDrive; -import luckyclient.execution.webdriver.EncapsulateOperation; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.Constants; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * @date 2018年3月1日 - */ -public class WebCaseExecution{ - private static Map variable = new HashMap<>(); - private static String casenote = "备注初始化"; - private static String imagname = ""; - - public static void caseExcution(ProjectCase testcase, List steps, String taskid, WebDriver wd, serverOperation caselog, List pcplist) throws InterruptedException { - caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), 3); - // 把公共参数加入到MAP中 - for (ProjectCaseParams pcp : pcplist) { - variable.put(pcp.getParamsName(), pcp.getParamsValue()); - } - // 加入全局变量 - variable.putAll(ParamsManageForSteps.GLOBAL_VARIABLE); - // 0:成功 1:失败 2:锁定 其他:锁定 - int setcaseresult = 0; - for (ProjectCaseSteps step : steps) { - Map params; - String result; - - // 根据步骤类型来分析步骤参数 - if (1 == step.getStepType()){ - params = WebDriverAnalyticCase.analyticCaseStep(testcase, step, taskid, caselog, variable); - }else{ - params = InterfaceAnalyticCase.analyticCaseStep(testcase, step, taskid, caselog, variable); - } - - // 判断分析步骤参数是否有异常 - if (null != params.get("exception") && params.get("exception").contains("解析异常")) { - setcaseresult = 2; - break; - } - - // 根据步骤类型来执行步骤 - if (1 == step.getStepType()){ - result = runWebStep(params, wd, taskid, testcase.getCaseId(), step.getStepSerialNumber(), caselog); - }else{ - TestCaseExecution testCaseExecution=new TestCaseExecution(); - result = testCaseExecution.runStep(params, taskid, testcase.getCaseSign(), step, caselog); - } - - String expectedResults = params.get("ExpectedResults"); - - // 判断结果 - int stepresult = judgeResult(testcase, step, params, wd, taskid, expectedResults, result, caselog); - // 失败,并且不在继续,直接终止 - if (0 != stepresult) { - setcaseresult = stepresult; - if (testcase.getFailcontinue() == 0) { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),step.getStepSerialNumber()); - break; - } else { - LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),step.getStepSerialNumber()); - } - } - } - - variable.clear(); - caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), setcaseresult); - if (setcaseresult == 0) { - LogUtil.APP.info("用例【{}】全部步骤执行结果成功...",testcase.getCaseSign()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例全部步骤执行结果成功", "info", "ending", ""); - } else { - LogUtil.APP.warn("用例【{}】步骤执行过程中失败或是锁定...请查看具体原因:{}",testcase.getCaseSign(),casenote); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例执行过程中失败或是锁定" + casenote, "error", "ending", ""); - } - } - - public static String runWebStep(Map params, WebDriver wd, String taskid, Integer caseId, int stepno, serverOperation caselog) { - String result = ""; - String property; - String propertyValue; - String operation; - String operationValue; - - try { - property = params.get("property"); - propertyValue = params.get("property_value"); - operation = params.get("operation"); - operationValue = params.get("operation_value"); - - LogUtil.APP.info("二次解析用例过程完成,等待进行对象操作......"); - caselog.insertTaskCaseLog(taskid, caseId, "对象操作:" + operation + "; 操作值:" + operationValue, "info", String.valueOf(stepno), ""); - } catch (Exception e) { - LogUtil.APP.error("二次解析用例过程抛出异常!",e); - return "步骤执行失败:解析用例失败!"; - } - - try { - //调用另一条用例,支持接口,web类型用例 - if (null != operation && null != operationValue && "runcase".equals(operation)) { - String[] temp = operationValue.split(",", -1); - TestCaseExecution testCaseExecution=new TestCaseExecution(); - String ex = testCaseExecution.oneCaseExecuteForUICase(temp[0], taskid, caselog, wd); - if (!ex.contains("CallCase调用出错!") && !ex.contains("解析出错啦!") && !ex.contains("失败")) { - return ex; - } else { - return "步骤执行失败:"+ex; - } - } - - // 页面元素层 - if (null != property && null != propertyValue && null != operation) { - WebElement we = isElementExist(wd, property, propertyValue); - - //判断元素是否存在关键字 - if(operation.equals("iselementexist")){ - // 判断此元素是否存在 - if (null == we) { - LogUtil.APP.warn("获取到的值是【false】"); - return "获取到的值是【false】"; - }else{ - LogUtil.APP.info("获取到的值是【true】"); - return "获取到的值是【true】"; - } - } - - // 判断此元素是否存在 - if (null == we) { - LogUtil.APP.warn("定位对象失败,isElementExist为null!"); - return "步骤执行失败:定位的元素不存在!"; - } - - //点亮即将操作的元素 - BaseWebDrive.highLightElement(wd, we); - - if (operation.contains("select")) { - result = EncapsulateOperation.selectOperation(we, operation, operationValue); - } else if (operation.contains("get")) { - result = EncapsulateOperation.getOperation(wd, we, operation, operationValue); - } else if (operation.contains("mouse")) { - result = EncapsulateOperation.actionWeOperation(wd, we, operation, operationValue, property, propertyValue); - } else { - result = EncapsulateOperation.objectOperation(wd, we, operation, operationValue, property, propertyValue); - } - // Driver层操作 - } else if (null == property && null != operation) { - // 处理弹出框事件 - if (operation.contains("alert")) { - result = EncapsulateOperation.alertOperation(wd, operation); - } else if (operation.contains("mouse")) { - result = EncapsulateOperation.actionOperation(wd, operation, operationValue); - } else { - result = EncapsulateOperation.driverOperation(wd, operation, operationValue); - } - } else { - LogUtil.APP.warn("元素操作过程失败!"); - result = "步骤执行失败:元素操作过程失败!"; - } - } catch (Exception e) { - LogUtil.APP.error("元素定位过程或是操作过程失败或异常!",e); - return "步骤执行失败:元素定位过程或是操作过程失败或异常!" + e.getMessage(); - } - - if (result.contains("步骤执行失败:")){ - caselog.insertTaskCaseLog(taskid, caseId, result, "error", String.valueOf(stepno), ""); - } else{ - caselog.insertTaskCaseLog(taskid, caseId, result, "info", String.valueOf(stepno), ""); - } - - if (result.contains("获取到的值是【") && result.contains("】")) { - result = result.substring(result.indexOf("获取到的值是【") + "获取到的值是【".length(), result.length() - 1); - } - return result; - - } - - private static WebElement isElementExist(WebDriver wd, String property, String propertyValue) { - try { - WebElement we = null; - property = property.toLowerCase(); - // 处理WebElement对象定位 - switch (property) { - case "id": - we = wd.findElement(By.id(propertyValue)); - break; - case "name": - we = wd.findElement(By.name(propertyValue)); - break; - case "xpath": - we = wd.findElement(By.xpath(propertyValue)); - break; - case "linktext": - we = wd.findElement(By.linkText(propertyValue)); - break; - case "tagname": - we = wd.findElement(By.tagName(propertyValue)); - break; - case "cssselector": - we = wd.findElement(By.cssSelector(propertyValue)); - break; - default: - break; - } - - return we; - - } catch (Exception e) { - LogUtil.APP.error("当前对象定位失败!",e); - return null; - } - - } - - public static int judgeResult(ProjectCase testcase, ProjectCaseSteps step, Map params, WebDriver driver, String taskid, String expect, String result, serverOperation caselog) throws InterruptedException { - int setresult = 0; - java.text.DateFormat timeformat = new java.text.SimpleDateFormat("MMdd-hhmmss"); - imagname = timeformat.format(new Date()); - - result = ActionManageForSteps.actionManage(step.getAction(), result); - if (null != result && !result.contains("步骤执行失败:")) { - // 有预期结果 - if (null != expect && !expect.isEmpty()) { - LogUtil.APP.info("期望结果为【{}】",expect); - // 赋值传参模式 - if (expect.length() > Constants.ASSIGNMENT_SIGN.length() && expect.startsWith(Constants.ASSIGNMENT_SIGN)) { - variable.put(expect.substring(Constants.ASSIGNMENT_SIGN.length()), result); - LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),result,expect.substring(Constants.ASSIGNMENT_SIGN.length())); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + result + "】赋值给变量【" + expect.substring(Constants.ASSIGNMENT_SIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); - } - // 赋值全局变量 - else if (expect.length() > Constants.ASSIGNMENT_GLOBALSIGN.length() && expect.startsWith(Constants.ASSIGNMENT_GLOBALSIGN)) { - variable.put(expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), result); - ParamsManageForSteps.GLOBAL_VARIABLE.put(expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), result); - LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给全局变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),result,expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length())); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + result + "】赋值给全局变量【" + expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); - } - // WebUI检查模式 - else if (1 == step.getStepType() && params.get("checkproperty") != null && params.get("checkproperty_value") != null) { - String checkproperty = params.get("checkproperty"); - String checkPropertyValue = params.get("checkproperty_value"); - - WebElement we = isElementExist(driver, checkproperty, checkPropertyValue); - if (null != we) { - LogUtil.APP.info("用例:{} 第{}步,在当前页面中找到预期结果中对象。当前步骤执行成功!",testcase.getCaseSign(),step.getStepSerialNumber()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在当前页面中找到预期结果中对象。当前步骤执行成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - casenote = "第" + step.getStepSerialNumber() + "步,没有在当前页面中找到预期结果中对象。执行失败!"; - setresult = 1; - BaseWebDrive.webScreenShot(driver, imagname); - LogUtil.APP.warn("用例:{} 第{}步,没有在当前页面中找到预期结果中对象。当前步骤执行失败!",testcase.getCaseSign(),step.getStepSerialNumber()); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在当前页面中没有找到预期结果中对象。当前步骤执行失败!" + "checkproperty【" + checkproperty + "】 checkproperty_value【" + checkPropertyValue + "】", "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - } - // 其它匹配模式 - else { - // 模糊匹配预期结果模式 - if (expect.length() > Constants.FUZZY_MATCHING_SIGN.length() && expect.startsWith(Constants.FUZZY_MATCHING_SIGN)) { - if (result.contains(expect.substring(Constants.FUZZY_MATCHING_SIGN.length()))) { - LogUtil.APP.info("用例:{} 第{}步,模糊匹配预期结果成功!执行结果:",testcase.getCaseSign(),step.getStepSerialNumber(),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果成功!执行结果:" + result, "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - casenote = "第" + step.getStepSerialNumber() + "步,模糊匹配预期结果失败!"; - setresult = 1; - BaseWebDrive.webScreenShot(driver, imagname); - LogUtil.APP.warn("用例:{} 第{}步,模糊匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expect.substring(Constants.FUZZY_MATCHING_SIGN.length()),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果失败!预期结果:" + expect.substring(Constants.FUZZY_MATCHING_SIGN.length()) + ",测试结果:" + result, "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - } - // 正则匹配预期结果模式 - else if (expect.length() > Constants.REGULAR_MATCHING_SIGN.length() && expect.startsWith(Constants.REGULAR_MATCHING_SIGN)) { - Pattern pattern = Pattern.compile(expect.substring(Constants.REGULAR_MATCHING_SIGN.length())); - Matcher matcher = pattern.matcher(result); - if (matcher.find()) { - LogUtil.APP.info("用例:{} 第{}步,正则匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - casenote = "第" + step.getStepSerialNumber() + "步,正则匹配预期结果失败!"; - setresult = 1; - BaseWebDrive.webScreenShot(driver, imagname); - LogUtil.APP.warn("用例:{} 第{}步,正则匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expect.substring(Constants.REGULAR_MATCHING_SIGN.length()),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果失败!预期结果:" + expect.substring(Constants.REGULAR_MATCHING_SIGN.length()) + ",测试结果:" + result, "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - } - // 精确匹配预期结果模式 - else { - if (expect.equals(result)) { - LogUtil.APP.info("用例:{} 第{}步,精确匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "精确匹配预期结果成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); - } else { - casenote = "第" + step.getStepSerialNumber() + "步,精确匹配预期结果失败!"; - setresult = 1; - BaseWebDrive.webScreenShot(driver, imagname); - LogUtil.APP.warn("用例:{} 第{}步,精确匹配预期结果失败!预期结果是:【{}】 执行结果:【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),expect,result); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "精确匹配预期结果失败!预期结果是:【"+expect+"】 执行结果:【"+ result+"】", "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - } - } - } - } else { - casenote = (null != result) ? result : ""; - setresult = 2; - BaseWebDrive.webScreenShot(driver, imagname); - LogUtil.APP.warn("用例:{} 第{}步,执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),casenote); - caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "当前步骤在执行过程中解析|定位元素|操作对象失败!" + casenote, "error", String.valueOf(step.getStepSerialNumber()), imagname); - } - - return setresult; - } - +package luckyclient.execution.webdriver.ex; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import luckyclient.execution.dispose.ActionManageForSteps; +import luckyclient.execution.dispose.ParamsManageForSteps; +import luckyclient.execution.httpinterface.TestCaseExecution; +import luckyclient.execution.httpinterface.analyticsteps.InterfaceAnalyticCase; +import luckyclient.execution.webdriver.BaseWebDrive; +import luckyclient.execution.webdriver.EncapsulateOperation; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.Constants; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * @date 2018年3月1日 + */ +public class WebCaseExecution{ + private static Map variable = new HashMap<>(); + private static String casenote = "备注初始化"; + + public static void caseExcution(ProjectCase testcase, List steps, String taskid, WebDriver wd, serverOperation caselog, List pcplist) { + caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), 3); + // 把公共参数加入到MAP中 + for (ProjectCaseParams pcp : pcplist) { + variable.put(pcp.getParamsName(), pcp.getParamsValue()); + } + // 加入全局变量 + variable.putAll(ParamsManageForSteps.GLOBAL_VARIABLE); + // 0:成功 1:失败 2:锁定 其他:锁定 + int setcaseresult = 0; + for (ProjectCaseSteps step : steps) { + Map params; + String result; + + // 根据步骤类型来分析步骤参数 + if (1 == step.getStepType()){ + params = WebDriverAnalyticCase.analyticCaseStep(testcase, step, taskid, caselog, variable); + }else{ + params = InterfaceAnalyticCase.analyticCaseStep(testcase, step, taskid, caselog, variable); + } + + // 判断分析步骤参数是否有异常 + if (null != params.get("exception") && params.get("exception").contains("解析异常")) { + setcaseresult = 2; + break; + } + + // 根据步骤类型来执行步骤 + if (1 == step.getStepType()){ + result = runWebStep(params, wd, taskid, testcase.getCaseId(), step.getStepSerialNumber(), caselog); + }else{ + TestCaseExecution testCaseExecution=new TestCaseExecution(); + result = testCaseExecution.runStep(params, taskid, testcase.getCaseSign(), step, caselog); + } + + String expectedResults = params.get("ExpectedResults"); + + // 判断结果 + int stepresult = judgeResult(testcase, step, params, wd, taskid, expectedResults, result, caselog); + // 失败,并且不在继续,直接终止 + if (0 != stepresult) { + setcaseresult = stepresult; + if (testcase.getFailcontinue() == 0) { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,中断本条用例后续步骤执行,进入到下一条用例执行中......",testcase.getCaseSign(),step.getStepSerialNumber()); + break; + } else { + LogUtil.APP.warn("用例【{}】第【{}】步骤执行失败,继续本条用例后续步骤执行,进入下个步骤执行中......",testcase.getCaseSign(),step.getStepSerialNumber()); + } + } + } + + variable.clear(); + caselog.updateTaskCaseExecuteStatus(taskid, testcase.getCaseId(), setcaseresult); + if (setcaseresult == 0) { + LogUtil.APP.info("用例【{}】全部步骤执行结果成功...",testcase.getCaseSign()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例全部步骤执行结果成功", "info", "ending", ""); + } else { + LogUtil.APP.warn("用例【{}】步骤执行过程中失败或是锁定...请查看具体原因:{}",testcase.getCaseSign(),casenote); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "用例执行过程中失败或是锁定" + casenote, "error", "ending", ""); + } + } + + public static String runWebStep(Map params, WebDriver wd, String taskid, Integer caseId, int stepno, serverOperation caselog) { + String result; + String property; + String propertyValue; + String operation; + String operationValue; + + try { + property = params.get("property"); + propertyValue = params.get("property_value"); + operation = params.get("operation"); + operationValue = params.get("operation_value"); + + LogUtil.APP.info("二次解析用例过程完成,等待进行对象操作......"); + caselog.insertTaskCaseLog(taskid, caseId, "对象操作:" + operation + "; 操作值:" + operationValue, "info", String.valueOf(stepno), ""); + } catch (Exception e) { + LogUtil.APP.error("二次解析用例过程抛出异常!",e); + return "步骤执行失败:解析用例失败!"; + } + + try { + //调用另一条用例,支持接口,web类型用例 + if (null != operationValue && "runcase".equals(operation)) { + String[] temp = operationValue.split(",", -1); + TestCaseExecution testCaseExecution=new TestCaseExecution(); + String ex = testCaseExecution.oneCaseExecuteForUICase(temp[0], taskid, caselog, wd); + if (!ex.contains("CallCase调用出错!") && !ex.contains("解析出错啦!") && !ex.contains("失败")) { + return ex; + } else { + return "步骤执行失败:"+ex; + } + } + + // 页面元素层 + if (null != property && null != propertyValue && null != operation) { + WebElement we = isElementExist(wd, property, propertyValue); + + //判断元素是否存在关键字 + if(operation.equals("iselementexist")){ + // 判断此元素是否存在 + if (null == we) { + LogUtil.APP.warn("获取到的值是【false】"); + return "获取到的值是【false】"; + }else{ + LogUtil.APP.info("获取到的值是【true】"); + return "获取到的值是【true】"; + } + } + + // 判断此元素是否存在 + if (null == we) { + LogUtil.APP.warn("定位对象失败,isElementExist为null!"); + return "步骤执行失败:定位的元素不存在!"; + } + + //点亮即将操作的元素 + BaseWebDrive.highLightElement(wd, we); + + if (operation.contains("select")) { + result = EncapsulateOperation.selectOperation(we, operation, operationValue); + } else if (operation.contains("get")) { + result = EncapsulateOperation.getOperation(wd, we, operation, operationValue); + } else if (operation.contains("mouse")) { + result = EncapsulateOperation.actionWeOperation(wd, we, operation, operationValue, property, propertyValue); + } else { + result = EncapsulateOperation.objectOperation(wd, we, operation, operationValue, property, propertyValue); + } + // Driver层操作 + } else if (null == property && null != operation) { + // 处理弹出框事件 + if (operation.contains("alert")) { + result = EncapsulateOperation.alertOperation(wd, operation); + } else if (operation.contains("mouse")) { + result = EncapsulateOperation.actionOperation(wd, operation, operationValue); + } else { + result = EncapsulateOperation.driverOperation(wd, operation, operationValue); + } + } else { + LogUtil.APP.warn("元素操作过程失败!"); + result = "步骤执行失败:元素操作过程失败!"; + } + } catch (Exception e) { + LogUtil.APP.error("元素定位过程或是操作过程失败或异常!",e); + return "步骤执行失败:元素定位过程或是操作过程失败或异常!" + e.getMessage(); + } + + if (result.contains("步骤执行失败:")){ + caselog.insertTaskCaseLog(taskid, caseId, result, "error", String.valueOf(stepno), ""); + } else{ + caselog.insertTaskCaseLog(taskid, caseId, result, "info", String.valueOf(stepno), ""); + } + + if (result.contains("获取到的值是【") && result.contains("】")) { + result = result.substring(result.indexOf("获取到的值是【") + "获取到的值是【".length(), result.length() - 1); + } + return result; + + } + + private static WebElement isElementExist(WebDriver wd, String property, String propertyValue) { + try { + WebElement we = null; + property = property.toLowerCase(); + // 处理WebElement对象定位 + switch (property) { + case "id": + we = wd.findElement(By.id(propertyValue)); + break; + case "name": + we = wd.findElement(By.name(propertyValue)); + break; + case "xpath": + we = wd.findElement(By.xpath(propertyValue)); + break; + case "linktext": + we = wd.findElement(By.linkText(propertyValue)); + break; + case "tagname": + we = wd.findElement(By.tagName(propertyValue)); + break; + case "cssselector": + we = wd.findElement(By.cssSelector(propertyValue)); + break; + default: + break; + } + + return we; + + } catch (Exception e) { + LogUtil.APP.error("当前对象定位失败!",e); + return null; + } + + } + + public static int judgeResult(ProjectCase testcase, ProjectCaseSteps step, Map params, WebDriver driver, String taskid, String expect, String result, serverOperation caselog) { + int setresult = 0; + java.text.DateFormat timeformat = new java.text.SimpleDateFormat("MMdd-hhmmss"); + String imagname = timeformat.format(new Date()); + + result = ActionManageForSteps.actionManage(step.getAction(), result); + if (null != result && !result.contains("步骤执行失败:")) { + // 有预期结果 + if (null != expect && !expect.isEmpty()) { + LogUtil.APP.info("期望结果为【{}】",expect); + // 赋值传参模式 + if (expect.length() > Constants.ASSIGNMENT_SIGN.length() && expect.startsWith(Constants.ASSIGNMENT_SIGN)) { + variable.put(expect.substring(Constants.ASSIGNMENT_SIGN.length()), result); + LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),result,expect.substring(Constants.ASSIGNMENT_SIGN.length())); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + result + "】赋值给变量【" + expect.substring(Constants.ASSIGNMENT_SIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); + } + // 赋值全局变量 + else if (expect.length() > Constants.ASSIGNMENT_GLOBALSIGN.length() && expect.startsWith(Constants.ASSIGNMENT_GLOBALSIGN)) { + variable.put(expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), result); + ParamsManageForSteps.GLOBAL_VARIABLE.put(expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()), result); + LogUtil.APP.info("用例:{} 第{}步,将测试结果【{}】赋值给全局变量【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),result,expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length())); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "将测试结果【" + result + "】赋值给全局变量【" + expect.substring(Constants.ASSIGNMENT_GLOBALSIGN.length()) + "】", "info", String.valueOf(step.getStepSerialNumber()), ""); + } + // WebUI检查模式 + else if (1 == step.getStepType() && params.get("checkproperty") != null && params.get("checkproperty_value") != null) { + String checkproperty = params.get("checkproperty"); + String checkPropertyValue = params.get("checkproperty_value"); + + WebElement we = isElementExist(driver, checkproperty, checkPropertyValue); + if (null != we) { + LogUtil.APP.info("用例:{} 第{}步,在当前页面中找到预期结果中对象。当前步骤执行成功!",testcase.getCaseSign(),step.getStepSerialNumber()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在当前页面中找到预期结果中对象。当前步骤执行成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + casenote = "第" + step.getStepSerialNumber() + "步,没有在当前页面中找到预期结果中对象。执行失败!"; + setresult = 1; + BaseWebDrive.webScreenShot(driver, imagname); + LogUtil.APP.warn("用例:{} 第{}步,没有在当前页面中找到预期结果中对象。当前步骤执行失败!",testcase.getCaseSign(),step.getStepSerialNumber()); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "在当前页面中没有找到预期结果中对象。当前步骤执行失败!" + "checkproperty【" + checkproperty + "】 checkproperty_value【" + checkPropertyValue + "】", "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + } + // 其它匹配模式 + else { + // 模糊匹配预期结果模式 + if (expect.length() > Constants.FUZZY_MATCHING_SIGN.length() && expect.startsWith(Constants.FUZZY_MATCHING_SIGN)) { + if (result.contains(expect.substring(Constants.FUZZY_MATCHING_SIGN.length()))) { + LogUtil.APP.info("用例:{} 第{}步,模糊匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果成功!执行结果:" + result, "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + casenote = "第" + step.getStepSerialNumber() + "步,模糊匹配预期结果失败!"; + setresult = 1; + BaseWebDrive.webScreenShot(driver, imagname); + LogUtil.APP.warn("用例:{} 第{}步,模糊匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expect.substring(Constants.FUZZY_MATCHING_SIGN.length()),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "模糊匹配预期结果失败!预期结果:" + expect.substring(Constants.FUZZY_MATCHING_SIGN.length()) + ",测试结果:" + result, "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + } + // 正则匹配预期结果模式 + else if (expect.length() > Constants.REGULAR_MATCHING_SIGN.length() && expect.startsWith(Constants.REGULAR_MATCHING_SIGN)) { + Pattern pattern = Pattern.compile(expect.substring(Constants.REGULAR_MATCHING_SIGN.length())); + Matcher matcher = pattern.matcher(result); + if (matcher.find()) { + LogUtil.APP.info("用例:{} 第{}步,正则匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + casenote = "第" + step.getStepSerialNumber() + "步,正则匹配预期结果失败!"; + setresult = 1; + BaseWebDrive.webScreenShot(driver, imagname); + LogUtil.APP.warn("用例:{} 第{}步,正则匹配预期结果失败!预期结果:{},测试结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),expect.substring(Constants.REGULAR_MATCHING_SIGN.length()),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "正则匹配预期结果失败!预期结果:" + expect.substring(Constants.REGULAR_MATCHING_SIGN.length()) + ",测试结果:" + result, "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + } + // 精确匹配预期结果模式 + else { + if (expect.equals(result)) { + LogUtil.APP.info("用例:{} 第{}步,精确匹配预期结果成功!执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "精确匹配预期结果成功!", "info", String.valueOf(step.getStepSerialNumber()), ""); + } else { + casenote = "第" + step.getStepSerialNumber() + "步,精确匹配预期结果失败!"; + setresult = 1; + BaseWebDrive.webScreenShot(driver, imagname); + LogUtil.APP.warn("用例:{} 第{}步,精确匹配预期结果失败!预期结果是:【{}】 执行结果:【{}】",testcase.getCaseSign(),step.getStepSerialNumber(),expect,result); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "精确匹配预期结果失败!预期结果是:【"+expect+"】 执行结果:【"+ result+"】", "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + } + } + } + } else { + casenote = (null != result) ? result : ""; + setresult = 2; + BaseWebDrive.webScreenShot(driver, imagname); + LogUtil.APP.warn("用例:{} 第{}步,执行结果:{}",testcase.getCaseSign(),step.getStepSerialNumber(),casenote); + caselog.insertTaskCaseLog(taskid, testcase.getCaseId(), "当前步骤在执行过程中解析|定位元素|操作对象失败!" + casenote, "error", String.valueOf(step.getStepSerialNumber()), imagname); + } + + return setresult; + } + } \ No newline at end of file diff --git a/src/main/java/luckyclient/execution/webdriver/ex/WebDriverAnalyticCase.java b/src/main/java/luckyclient/execution/webdriver/ex/WebDriverAnalyticCase.java index 9cf5ca2..781203a 100644 --- a/src/main/java/luckyclient/execution/webdriver/ex/WebDriverAnalyticCase.java +++ b/src/main/java/luckyclient/execution/webdriver/ex/WebDriverAnalyticCase.java @@ -1,193 +1,194 @@ -package luckyclient.execution.webdriver.ex; - -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.commons.lang3.StringUtils; - -import luckyclient.execution.dispose.ChangString; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @ClassName: AnalyticCase - * @Description: 解析单个用例中描述部分的脚本 @author: seagull - * @date 2016年9月18日 - * - */ -public class WebDriverAnalyticCase { - // private static String splitFlag = "\\|"; - - /** - * Web UI类型的步骤解析 - * - * @param projectcase - * @param step - * @param taskid - * @param caselog - * @return - * @author Seagull - * @date 2019年1月17日 - */ - public static Map analyticCaseStep(ProjectCase projectcase, ProjectCaseSteps step, String taskid, - serverOperation caselog, Map variable) { - Map params = new HashMap(0); - - String resultstr = null; - try { - // 处理值传递 - String path = ChangString.changparams(step.getStepPath(), variable, "包路径|定位路径"); - if (null != path && path.contains("=")) { - String property = path.substring(0, path.indexOf("=")).trim(); - String propertyValue = path.substring(path.indexOf("=") + 1, path.length()).trim(); - // set属性 - params.put("property", property.toLowerCase()); - // set属性值 - params.put("property_value", propertyValue); - LogUtil.APP.info("对象属性解析结果:property:{}; property_value:{}", property, propertyValue); - } - // set操作方法,处理值传递 - String operation = ChangString.changparams(step.getStepOperation().toLowerCase(), variable, "操作"); - params.put("operation", operation); - // set属性值,处理值传递 - String operationValue = ChangString.changparams(step.getStepParameters(), variable, "操作参数"); - if (StringUtils.isNotEmpty(operationValue)) { - params.put("operation_value", operationValue); - } - LogUtil.APP.info("对象操作解析结果:operation:{}; operation_value:{}", operation,operationValue); - // 获取预期结果字符串 - resultstr = step.getExpectedResult(); - - // set预期结果 - if (null == resultstr || "".equals(resultstr)) { - params.put("ExpectedResults", ""); - } else if (null != resultstr) { - String expectedResults = subComment(resultstr); - - // 处理check字段 - if (expectedResults.toLowerCase().startsWith("check(")) { - expectedResults = expectedResults.replace("Check(", "check("); - params.put("checkproperty", expectedResults.substring(expectedResults.indexOf("check(") + 6, - expectedResults.indexOf("="))); - params.put("checkproperty_value", expectedResults.substring(expectedResults.indexOf("=") + 1, - expectedResults.lastIndexOf(")"))); - } - //处理值传递 - expectedResults = ChangString.changparams(expectedResults, variable, "预期结果"); - params.put("ExpectedResults", expectedResults); - LogUtil.APP.info("预期结果解析:ExpectedResults:{}", expectedResults); - } - - LogUtil.APP.info("用例编号:{} 第{}步,解析自动化用例步骤脚本完成!", projectcase.getCaseSign(), step.getStepSerialNumber()); - if (null != caselog) { - caselog.insertTaskCaseLog(taskid, projectcase.getCaseId(), - "步骤编号:" + step.getStepSerialNumber() + " 解析自动化用例步骤脚本完成!", "info", - String.valueOf(step.getStepSerialNumber()), ""); - } - } catch (Exception e) { - LogUtil.APP.error("用例编号:{} 第{}步,解析自动化用例步骤脚本出现异常!", projectcase.getCaseSign(), step.getStepSerialNumber(), - e); - if (null != caselog) { - caselog.insertTaskCaseLog(taskid, projectcase.getCaseId(), - "步骤编号:" + step.getStepSerialNumber() + " 解析自动化用例步骤脚本出错!", "error", - String.valueOf(step.getStepSerialNumber()), ""); - } - params.put("exception", "用例编号:" + projectcase.getCaseSign() + "|解析异常,用例步骤为空或是用例脚本错误!"); - return params; - } - return params; - } - - private static String subComment(String htmlStr) throws InterruptedException { - // 定义script的正则表达式 - String regExScript = "]*?>[\\s\\S]*?<\\/script>"; - // 定义style的正则表达式 - String regExStyle = "]*?>[\\s\\S]*?<\\/style>"; - // 定义HTML标签的正则表达式 - String regExHtml = "<[^>]+>"; - // 定义空格回车换行符 - String regExSpace = "\t|\r|\n"; - - String scriptstr = null; - if (htmlStr != null) { - Pattern pScript = Pattern.compile(regExScript, Pattern.CASE_INSENSITIVE); - Matcher mScript = pScript.matcher(htmlStr); - // 过滤script标签 - htmlStr = mScript.replaceAll(""); - - Pattern pStyle = Pattern.compile(regExStyle, Pattern.CASE_INSENSITIVE); - Matcher mStyle = pStyle.matcher(htmlStr); - // 过滤style标签 - htmlStr = mStyle.replaceAll(""); - - Pattern pHtml = Pattern.compile(regExHtml, Pattern.CASE_INSENSITIVE); - Matcher mHtml = pHtml.matcher(htmlStr); - // 过滤html标签 - htmlStr = mHtml.replaceAll(""); - - Pattern pSpace = Pattern.compile(regExSpace, Pattern.CASE_INSENSITIVE); - Matcher mSpace = pSpace.matcher(htmlStr); - // 过滤空格回车标签 - htmlStr = mSpace.replaceAll(""); - - } - if (htmlStr.indexOf("/*") > -1 && htmlStr.indexOf("*/") > -1) { - String commentstr = htmlStr.substring(htmlStr.trim().indexOf("/*"), htmlStr.indexOf("*/") + 2); - // 去注释 - scriptstr = htmlStr.replace(commentstr, ""); - } else { - scriptstr = htmlStr; - } - // 去掉字符串前后的空格 - scriptstr = trimInnerSpaceStr(scriptstr); - // 替换空格转义 - scriptstr = scriptstr.replaceAll(" ", " "); - // 转义双引号 - scriptstr = scriptstr.replaceAll(""", "\""); - // 转义单引号 - scriptstr = scriptstr.replaceAll("'", "\'"); - // 转义链接符 - scriptstr = scriptstr.replaceAll("&", "&"); - scriptstr = scriptstr.replaceAll("<", "<"); - scriptstr = scriptstr.replaceAll(">", ">"); - - return scriptstr; - } - - /*** - * 去掉字符串前后的空格,中间的空格保留 - * - * @param str - * @return - */ - public static String trimInnerSpaceStr(String str) { - str = str.trim(); - while (str.startsWith(" ")) { - str = str.substring(1, str.length()).trim(); - } - while (str.startsWith(" ")) { - str = str.substring(6, str.length()).trim(); - } - while (str.endsWith(" ")) { - str = str.substring(0, str.length() - 1).trim(); - } - while (str.endsWith(" ")) { - str = str.substring(0, str.length() - 6).trim(); - } - return str; - } - - public static void main(String[] args) { - // TODO Auto-generated method stub - } - -} +package luckyclient.execution.webdriver.ex; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; + +import luckyclient.execution.dispose.ChangString; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @ClassName: AnalyticCase + * @Description: 解析单个用例中描述部分的脚本 @author: seagull + * @date 2016年9月18日 + * + */ +public class WebDriverAnalyticCase { + // private static String splitFlag = "\\|"; + + /** + * Web UI类型的步骤解析 + * + * @param projectcase 用例对象 + * @param step 用例步骤对象 + * @param taskid 任务ID + * @param caselog 日志对象 + * @return 返回解析结果MAP + * @author Seagull + * @date 2019年1月17日 + */ + public static Map analyticCaseStep(ProjectCase projectcase, ProjectCaseSteps step, String taskid, + serverOperation caselog, Map variable) { + Map params = new HashMap<>(0); + + String resultstr; + try { + // 处理值传递 + String path = ChangString.changparams(step.getStepPath(), variable, "包路径|定位路径"); + if (null != path && path.contains("=")) { + String property = path.substring(0, path.indexOf("=")).trim(); + String propertyValue = path.substring(path.indexOf("=") + 1).trim(); + // set属性 + params.put("property", property.toLowerCase()); + // set属性值 + params.put("property_value", propertyValue); + LogUtil.APP.info("对象属性解析结果:property:{}; property_value:{}", property, propertyValue); + } + // set操作方法,处理值传递 + String operation = ChangString.changparams(step.getStepOperation().toLowerCase(), variable, "操作"); + params.put("operation", operation); + // set属性值,处理值传递 + String operationValue = ChangString.changparams(step.getStepParameters(), variable, "操作参数"); + if (StringUtils.isNotEmpty(operationValue)) { + params.put("operation_value", operationValue); + } + LogUtil.APP.info("对象操作解析结果:operation:{}; operation_value:{}", operation,operationValue); + // 获取预期结果字符串 + resultstr = step.getExpectedResult(); + + // set预期结果 + if (null == resultstr || "".equals(resultstr)) { + params.put("ExpectedResults", ""); + } else { + String expectedResults = subComment(resultstr); + + // 处理check字段 + if (expectedResults.toLowerCase().startsWith("check(")) { + expectedResults = expectedResults.replace("Check(", "check("); + params.put("checkproperty", expectedResults.substring(expectedResults.indexOf("check(") + 6, + expectedResults.indexOf("="))); + params.put("checkproperty_value", expectedResults.substring(expectedResults.indexOf("=") + 1, + expectedResults.lastIndexOf(")"))); + } + //处理值传递 + expectedResults = ChangString.changparams(expectedResults, variable, "预期结果"); + params.put("ExpectedResults", expectedResults); + LogUtil.APP.info("预期结果解析:ExpectedResults:{}", expectedResults); + } + + LogUtil.APP.info("用例编号:{} 第{}步,解析自动化用例步骤脚本完成!", projectcase.getCaseSign(), step.getStepSerialNumber()); + if (null != caselog) { + caselog.insertTaskCaseLog(taskid, projectcase.getCaseId(), + "步骤编号:" + step.getStepSerialNumber() + " 解析自动化用例步骤脚本完成!", "info", + String.valueOf(step.getStepSerialNumber()), ""); + } + } catch (Exception e) { + LogUtil.APP.error("用例编号:{} 第{}步,解析自动化用例步骤脚本出现异常!", projectcase.getCaseSign(), step.getStepSerialNumber(), + e); + if (null != caselog) { + caselog.insertTaskCaseLog(taskid, projectcase.getCaseId(), + "步骤编号:" + step.getStepSerialNumber() + " 解析自动化用例步骤脚本出错!", "error", + String.valueOf(step.getStepSerialNumber()), ""); + } + params.put("exception", "用例编号:" + projectcase.getCaseSign() + "|解析异常,用例步骤为空或是用例脚本错误!"); + return params; + } + return params; + } + + private static String subComment(String htmlStr) { + // 定义script的正则表达式 + String regExScript = "]*?>[\\s\\S]*?"; + // 定义style的正则表达式 + String regExStyle = "]*?>[\\s\\S]*?"; + // 定义HTML标签的正则表达式 + String regExHtml = "<[^>]+>"; + // 定义空格回车换行符 + String regExSpace = "[\t\r\n]"; + + String scriptstr; + if (htmlStr != null) { + Pattern pScript = Pattern.compile(regExScript, Pattern.CASE_INSENSITIVE); + Matcher mScript = pScript.matcher(htmlStr); + // 过滤script标签 + htmlStr = mScript.replaceAll(""); + + Pattern pStyle = Pattern.compile(regExStyle, Pattern.CASE_INSENSITIVE); + Matcher mStyle = pStyle.matcher(htmlStr); + // 过滤style标签 + htmlStr = mStyle.replaceAll(""); + + Pattern pHtml = Pattern.compile(regExHtml, Pattern.CASE_INSENSITIVE); + Matcher mHtml = pHtml.matcher(htmlStr); + // 过滤html标签 + htmlStr = mHtml.replaceAll(""); + + Pattern pSpace = Pattern.compile(regExSpace, Pattern.CASE_INSENSITIVE); + Matcher mSpace = pSpace.matcher(htmlStr); + // 过滤空格回车标签 + htmlStr = mSpace.replaceAll(""); + + } + assert htmlStr != null; + if (htmlStr.contains("/*") && htmlStr.contains("*/")) { + String commentstr = htmlStr.substring(htmlStr.trim().indexOf("/*"), htmlStr.indexOf("*/") + 2); + // 去注释 + scriptstr = htmlStr.replace(commentstr, ""); + } else { + scriptstr = htmlStr; + } + // 去掉字符串前后的空格 + scriptstr = trimInnerSpaceStr(scriptstr); + // 替换空格转义 + scriptstr = scriptstr.replaceAll(" ", " "); + // 转义双引号 + scriptstr = scriptstr.replaceAll(""", "\""); + // 转义单引号 + scriptstr = scriptstr.replaceAll("'", "'"); + // 转义链接符 + scriptstr = scriptstr.replaceAll("&", "&"); + scriptstr = scriptstr.replaceAll("<", "<"); + scriptstr = scriptstr.replaceAll(">", ">"); + + return scriptstr; + } + + /*** + * 去掉字符串前后的空格,中间的空格保留 + * + * @param str 原始字符串 + * @return 返回去除结果 + */ + public static String trimInnerSpaceStr(String str) { + str = str.trim(); + while (str.startsWith(" ")) { + str = str.substring(1).trim(); + } + while (str.startsWith(" ")) { + str = str.substring(6).trim(); + } + while (str.endsWith(" ")) { + str = str.substring(0, str.length() - 1).trim(); + } + while (str.endsWith(" ")) { + str = str.substring(0, str.length() - 6).trim(); + } + return str; + } + + public static void main(String[] args) { + // TODO Auto-generated method stub + } + +} diff --git a/src/main/java/luckyclient/execution/webdriver/ex/WebOneCaseExecute.java b/src/main/java/luckyclient/execution/webdriver/ex/WebOneCaseExecute.java index 9e8ac41..904ed17 100644 --- a/src/main/java/luckyclient/execution/webdriver/ex/WebOneCaseExecute.java +++ b/src/main/java/luckyclient/execution/webdriver/ex/WebOneCaseExecute.java @@ -1,60 +1,61 @@ -package luckyclient.execution.webdriver.ex; - -import java.io.IOException; -import java.util.List; - -import org.openqa.selenium.WebDriver; - -import luckyclient.execution.httpinterface.TestControl; -import luckyclient.execution.webdriver.WebDriverInitialization; -import luckyclient.remote.api.GetServerApi; -import luckyclient.remote.api.serverOperation; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * @date 2017年12月1日 上午9:29:40 - * - */ -public class WebOneCaseExecute{ - - public static void oneCaseExecuteForTast(String projectname,Integer caseId,int version,String taskid){ - //记录日志到数据库 - serverOperation.exetype = 0; - TestControl.TASKID = taskid; - int drivertype = serverOperation.querydrivertype(taskid); - WebDriver wd = null; - try { - wd = WebDriverInitialization.setWebDriverForTask(drivertype); - } catch (IOException e1) { - LogUtil.APP.error("初始化WebDriver出错!", e1); - } - serverOperation caselog = new serverOperation(); - ProjectCase testcase = GetServerApi.cGetCaseByCaseId(caseId); - //删除旧的日志 - serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); - - List pcplist=GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); - LogUtil.APP.info("开始执行用例:【{}】......",testcase.getCaseSign()); - try { - List steps=GetServerApi.getStepsbycaseid(testcase.getCaseId()); - WebCaseExecution.caseExcution(testcase, steps, taskid,wd,caselog,pcplist); - LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); - } catch (InterruptedException e) { - LogUtil.APP.error("用户执行过程中抛出异常!", e); - } - serverOperation.updateTaskExecuteData(taskid, 0,2); - //关闭浏览器 - wd.quit(); - } - -} +package luckyclient.execution.webdriver.ex; + +import java.io.IOException; +import java.util.List; + +import org.openqa.selenium.WebDriver; + +import luckyclient.execution.httpinterface.TestControl; +import luckyclient.execution.webdriver.WebDriverInitialization; +import luckyclient.remote.api.GetServerApi; +import luckyclient.remote.api.serverOperation; +import luckyclient.remote.entity.ProjectCase; +import luckyclient.remote.entity.ProjectCaseParams; +import luckyclient.remote.entity.ProjectCaseSteps; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * @date 2017年12月1日 上午9:29:40 + * + */ +public class WebOneCaseExecute{ + + public static void oneCaseExecuteForTast(Integer caseId, String taskid){ + //记录日志到数据库 + serverOperation.exetype = 0; + TestControl.TASKID = taskid; + int drivertype = serverOperation.querydrivertype(taskid); + WebDriver wd = null; + try { + wd = WebDriverInitialization.setWebDriverForTask(drivertype); + } catch (IOException e1) { + LogUtil.APP.error("初始化WebDriver出错!", e1); + } + serverOperation caselog = new serverOperation(); + ProjectCase testcase = GetServerApi.cGetCaseByCaseId(caseId); + //删除旧的日志 + serverOperation.deleteTaskCaseLog(testcase.getCaseId(), taskid); + + List pcplist=GetServerApi.cgetParamsByProjectid(String.valueOf(testcase.getProjectId())); + LogUtil.APP.info("开始执行用例:【{}】......",testcase.getCaseSign()); + try { + List steps=GetServerApi.getStepsbycaseid(testcase.getCaseId()); + WebCaseExecution.caseExcution(testcase, steps, taskid,wd,caselog,pcplist); + LogUtil.APP.info("当前用例:【{}】执行完成......进入下一条",testcase.getCaseSign()); + } catch (Exception e) { + LogUtil.APP.error("用户执行过程中抛出异常!", e); + } + serverOperation.updateTaskExecuteData(taskid, 0,2); + //关闭浏览器 + assert wd != null; + wd.quit(); + } + +} diff --git a/src/main/java/luckyclient/execution/webdriver/ocr/Ocr.java b/src/main/java/luckyclient/execution/webdriver/ocr/Ocr.java index 4a61e8d..739e7b6 100644 --- a/src/main/java/luckyclient/execution/webdriver/ocr/Ocr.java +++ b/src/main/java/luckyclient/execution/webdriver/ocr/Ocr.java @@ -41,18 +41,14 @@ public class Ocr { /** * 批处理文件路径 */ - private static String cmdpath = System.getProperty("user.dir"); - /** - * 默认把截图放在C盘根目录 - */ - private static String cmdname = "handlingCAPTCHA.bat"; + private static String cmdpath = System.getProperty("user.dir"); /** * 读取生成的TXT文件中的验证码 - * @return + * @return 返回结果 */ private static String readTextFile() { - String lineTxt = ""; + String lineTxt; try { String encoding = "GBK"; File file = new File(readtextpath); @@ -77,8 +73,8 @@ public class Ocr { /** * 截取验证码位置的图片 - * - * @param + * @param driver webDriver驱动 + * @param element 对象定位 */ private static void screenShotForElement(WebDriver driver, WebElement element){ driver = new Augmenter().augment(driver); @@ -106,10 +102,12 @@ public class Ocr { public static String getCAPTCHA(WebDriver driver, WebElement element) { - String code = ""; + String code; screenShotForElement(driver, element); Runtime run = Runtime.getRuntime(); try { + //默认把截图放在C盘根目录 + String cmdname = "handlingCAPTCHA.bat"; run.exec("cmd.exe /k start " + cmdname, null, new File(cmdpath)); Thread.sleep(1000); } catch (IOException | InterruptedException e) { @@ -125,9 +123,5 @@ public class Ocr { }*/ return code; } - - - public static void main(String[] args) throws IOException, InterruptedException { - } } \ No newline at end of file diff --git a/src/main/java/luckyclient/netty/ClientHandler.java b/src/main/java/luckyclient/netty/ClientHandler.java index 95fcadb..7ab6fde 100644 --- a/src/main/java/luckyclient/netty/ClientHandler.java +++ b/src/main/java/luckyclient/netty/ClientHandler.java @@ -51,8 +51,6 @@ public class ClientHandler extends ChannelHandlerAdapter { private static final String SERVER_PORT = SysConfig.getConfiguration().getProperty("server.web.port"); - private int byteRead; - private volatile int lastLength = 0; @@ -61,15 +59,15 @@ public class ClientHandler extends ChannelHandlerAdapter { private static ChannelHandlerContext ctx; - public ClientHandler() throws IOException { + public ClientHandler() { } @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException, InterruptedException { + public void channelRead(ChannelHandlerContext ctx, Object msg) throws UnsupportedEncodingException { //统一转编码 String jsonStr = URLDecoder.decode(msg.toString(), "GBK"); //服务端消息处理,如果接收到测试任务方法,则直接产生一个http请求并发送请求到本地 - JSONObject json = new JSONObject(); + JSONObject json; try { json = JSON.parseObject(jsonStr); @@ -80,41 +78,37 @@ public class ClientHandler extends ChannelHandlerAdapter { log.info("收到服务端消息:" + json.toString()); //解析消息 if ("run".equals(json.get("method"))) { - try { - //返回请求 - JSONObject re = new JSONObject(); - re.put("method", "return"); - Result result = new Result(1, "同步等待消息返回", json.get("uuid").toString(), null); - //如果是调度请求,则发起一个HTTP请求 - //获取是get方法还是post方法 - String getOrPost = json.get("getOrPost").toString(); - String urlParam = "http://127.0.0.1:" + port + "/" + json.get("url").toString(); - Integer socketTimeout = Integer.valueOf(json.get("socketTimeout").toString()); - String tmpResult = ""; - if ("get".equals(getOrPost)) { - @SuppressWarnings("unchecked") - Map jsonparams = (Map) json.get("data"); - //get方法 - try { - tmpResult = HttpRequest.httpClientGet(urlParam, jsonparams, socketTimeout); - } catch (Exception e) { - log.error("转发服务端GET请求出错"); - } - } else { - String jsonparams = json.get("data").toString(); - //post方法 - try { - tmpResult = HttpRequest.httpClientPost(urlParam, jsonparams, socketTimeout); - } catch (Exception e) { - log.error("转发服务端POST请求出错"); - } + //返回请求 + JSONObject re = new JSONObject(); + re.put("method", "return"); + Result result = new Result(1, "同步等待消息返回", json.get("uuid").toString(), null); + //如果是调度请求,则发起一个HTTP请求 + //获取是get方法还是post方法 + String getOrPost = json.get("getOrPost").toString(); + String urlParam = "http://127.0.0.1:" + port + "/" + json.get("url").toString(); + Integer socketTimeout = Integer.valueOf(json.get("socketTimeout").toString()); + String tmpResult = ""; + if ("get".equals(getOrPost)) { + @SuppressWarnings("unchecked") + Map jsonparams = (Map) json.get("data"); + //get方法 + try { + tmpResult = HttpRequest.httpClientGet(urlParam, jsonparams, socketTimeout); + } catch (Exception e) { + log.error("转发服务端GET请求出错"); + } + } else { + String jsonparams = json.get("data").toString(); + //post方法 + try { + tmpResult = HttpRequest.httpClientPost(urlParam, jsonparams, socketTimeout); + } catch (Exception e) { + log.error("转发服务端POST请求出错"); } - result.setMessage(tmpResult); - re.put("data", result); - sendMessage(re.toString()); - } catch (InterruptedException e) { - e.printStackTrace(); } + result.setMessage(tmpResult); + re.put("data", result); + sendMessage(re.toString()); } else if ("download".equals(json.get("method"))) { String loadpath = json.get("path").toString(); String path = System.getProperty("user.dir") + loadpath; @@ -147,7 +141,7 @@ public class ClientHandler extends ChannelHandlerAdapter { String fileName = jsonparams.get("imgName").toString(); String ctxPath = System.getProperty("user.dir") + File.separator + "log" + File.separator + "ScreenShot" + File.separator + fileName; File file = new File(ctxPath); - int start = Integer.valueOf(json.get("start").toString()); + int start = Integer.parseInt(json.get("start").toString()); FileUploadFile fileUploadFile = new FileUploadFile(); fileUploadFile.setFile(file); if (start != -1) { @@ -164,6 +158,7 @@ public class ClientHandler extends ChannelHandlerAdapter { log.info("文件长度:" + (randomAccessFile.length()) + ",start:" + start + ",a:" + a + ",b:" + b + ",lastLength:" + lastLength); byte[] bytes = new byte[lastLength]; log.info("bytes的长度是=" + bytes.length); + int byteRead; if ((byteRead = randomAccessFile.read(bytes)) != -1 && (randomAccessFile.length() - start) > 0) { log.info("byteRead = " + byteRead); fileUploadFile.setEndPos(byteRead); @@ -209,7 +204,7 @@ public class ClientHandler extends ChannelHandlerAdapter { } @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { + public void channelActive(ChannelHandlerContext ctx) { //发送客户端登录消息 JSONObject json = new JSONObject(); json.put("hostName", NETTY_HOST); @@ -226,14 +221,11 @@ public class ClientHandler extends ChannelHandlerAdapter { log.info("连接已断开,正在尝试重连..."); //使用过程中断线重连 final EventLoop eventLoop = ctx.channel().eventLoop(); - eventLoop.schedule(new Runnable() { - @Override - public void run() { - try { - NettyClient.start(); - } catch (InterruptedException e) { - e.printStackTrace(); - } + eventLoop.schedule(() -> { + try { + NettyClient.start(); + } catch (Exception e) { + log.error("链接出现异常,正在尝试重连...",e); } }, 1, TimeUnit.SECONDS); @@ -252,7 +244,7 @@ public class ClientHandler extends ChannelHandlerAdapter { if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent) evt; if (event.state().equals(IdleState.READER_IDLE)) { - /**发送心跳,保持长连接*/ + //发送心跳,保持长连接 JSONObject json = new JSONObject(); json.put("method", "ping"); json.put("hostName", NETTY_HOST); @@ -264,7 +256,7 @@ public class ClientHandler extends ChannelHandlerAdapter { super.userEventTriggered(ctx, evt); } - public static void sendMessage(String json) throws InterruptedException { + public static void sendMessage(String json) { ctx.channel().writeAndFlush(Unpooled.copiedBuffer((json + "$_").getBytes())); } diff --git a/src/main/java/luckyclient/netty/HttpRequest.java b/src/main/java/luckyclient/netty/HttpRequest.java index 1061f87..67de0c5 100644 --- a/src/main/java/luckyclient/netty/HttpRequest.java +++ b/src/main/java/luckyclient/netty/HttpRequest.java @@ -1,12 +1,10 @@ package luckyclient.netty; import org.apache.http.HttpEntity; -import org.apache.http.NoHttpResponseException; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; -import org.apache.http.conn.HttpHostConnectException; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.impl.client.CloseableHttpClient; @@ -19,9 +17,7 @@ import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; -import java.nio.charset.Charset; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; +import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.Map.Entry; @@ -29,19 +25,15 @@ public class HttpRequest { private static final Logger log = LoggerFactory.getLogger(HttpRequest.class); /** * 使用HttpClient以JSON格式发送post请求 - * @param urlParam - * @param jsonparams - * @param socketTimeout - * @return - * @throws NoSuchAlgorithmException - * @throws KeyManagementException - * @throws UnsupportedEncodingException - * @throws IOException + * @param urlParam 请求地址 + * @param jsonparams 请求参数 + * @param socketTimeout 超时时间 + * @return 返回请求结果 * @author Seagull * @date 2019年5月14日 */ - public static String httpClientPost(String urlParam,String jsonparams,Integer socketTimeout) throws NoSuchAlgorithmException, KeyManagementException, UnsupportedEncodingException, IOException{ - StringBuffer resultBuffer = null; + public static String httpClientPost(String urlParam,String jsonparams,Integer socketTimeout) throws IOException{ + StringBuffer resultBuffer; CloseableHttpClient httpclient= HttpClients.createDefault(); HttpPost httpPost = new HttpPost(urlParam); RequestConfig requestConfig = RequestConfig.custom() @@ -62,7 +54,7 @@ public class HttpRequest { // 读取服务器响应数据 resultBuffer = new StringBuffer(); if(null!=response.getEntity()){ - br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "utf-8")); + br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); String temp; while ((temp = br.readLine()) != null) { resultBuffer.append(temp); @@ -79,8 +71,7 @@ public class HttpRequest { try { br.close(); } catch (IOException e) { - br = null; - throw new RuntimeException(e); + log.error("关闭流出现异常...",e); } } } @@ -89,22 +80,19 @@ public class HttpRequest { /** * 使用HttpClient以JSON格式发送get请求 - * @param urlParam - * @param params - * @param socketTimeout - * @return - * @throws NoSuchAlgorithmException - * @throws KeyManagementException - * @throws NoHttpResponseException + * @param urlParam 请求地址 + * @param params 请求参数 + * @param socketTimeout 超时时间 + * @return 返回请求结果 * @author Seagull * @date 2019年5月14日 */ - public static String httpClientGet(String urlParam, Map params,Integer socketTimeout) throws NoSuchAlgorithmException, KeyManagementException, NoHttpResponseException { - StringBuffer resultBuffer = null; + public static String httpClientGet(String urlParam, Map params,Integer socketTimeout) { + StringBuffer resultBuffer; CloseableHttpClient httpclient= HttpClients.createDefault(); BufferedReader br = null; // 构建请求参数 - StringBuffer sbParams = new StringBuffer(); + StringBuilder sbParams = new StringBuilder(); if (params != null && params.size() > 0) { for (Entry entry : params.entrySet()) { sbParams.append(entry.getKey()); @@ -117,7 +105,7 @@ public class HttpRequest { sbParams.append("&"); } } - if (sbParams != null && sbParams.length() > 0) { + if (sbParams.length() > 0) { urlParam = urlParam + "?" + sbParams.substring(0, sbParams.length() - 1); } HttpGet httpGet = new HttpGet(urlParam); @@ -129,7 +117,7 @@ public class HttpRequest { CloseableHttpResponse response = httpclient.execute(httpGet); // 读取服务器响应数据 - br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "utf-8")); + br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); String temp; resultBuffer = new StringBuffer(); while ((temp = br.readLine()) != null) { @@ -142,8 +130,7 @@ public class HttpRequest { try { br.close(); } catch (IOException e) { - br = null; - throw new RuntimeException(e); + log.error("关闭流出现异常...",e); } } } @@ -153,18 +140,15 @@ public class HttpRequest { /** * 上传文件 - * @param urlParam - * @param loadpath - * @param file - * @return - * @throws NoSuchAlgorithmException - * @throws KeyManagementException - * @throws HttpHostConnectException + * @param urlParam 请求地址 + * @param loadpath 文件加载路径 + * @param file 文件对象 + * @return 返回上传结果 * @author Seagull * @date 2019年3月15日 */ - public static String httpClientUploadFile(String urlParam, String loadpath, File file) throws NoSuchAlgorithmException, KeyManagementException, HttpHostConnectException { - StringBuffer resultBuffer = null; + public static String httpClientUploadFile(String urlParam, String loadpath, File file) { + StringBuffer resultBuffer; CloseableHttpClient httpclient= HttpClients.createDefault(); HttpPost httpPost = new HttpPost(urlParam); // 构建请求参数 @@ -172,7 +156,7 @@ public class HttpRequest { try { MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create(); //设置请求的编码格式 - entityBuilder.setCharset(Charset.forName("utf-8")); + entityBuilder.setCharset(StandardCharsets.UTF_8); entityBuilder.addBinaryBody("jarfile", file); entityBuilder.addTextBody("loadpath", loadpath); HttpEntity reqEntity =entityBuilder.build(); @@ -184,13 +168,13 @@ public class HttpRequest { // 读取服务器响应数据 resultBuffer = new StringBuffer(); - br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "utf-8")); + br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); String temp; while ((temp = br.readLine()) != null) { resultBuffer.append(temp); } if(resultBuffer.length()==0){ - resultBuffer.append("上传文件异常,响应码:"+responsecode); + resultBuffer.append("上传文件异常,响应码:").append(responsecode); } } catch (Exception e) { throw new RuntimeException(e); @@ -199,8 +183,7 @@ public class HttpRequest { try { br.close(); } catch (IOException e) { - br = null; - throw new RuntimeException(e); + log.error("关闭流出现异常...",e); } } } @@ -209,17 +192,15 @@ public class HttpRequest { /** * 获取文件流 - * @param urlParam - * @param params - * @return - * @throws IOException - * @throws HttpHostConnectException + * @param urlParam 请求地址 + * @param params 请求参数 + * @return 返回获取到的文件流 * @author Seagull * @date 2019年3月15日 */ - public static byte[] getFile(String urlParam, Map params) throws IOException, HttpHostConnectException { + public static byte[] getFile(String urlParam, Map params) throws IOException { // 构建请求参数 - StringBuffer sbParams = new StringBuffer(); + StringBuilder sbParams = new StringBuilder(); if (params != null && params.size() > 0) { for (Entry entry : params.entrySet()) { sbParams.append(entry.getKey()); @@ -232,7 +213,7 @@ public class HttpRequest { sbParams.append("&"); } } - if (sbParams != null && sbParams.length() > 0) { + if (sbParams.length() > 0) { urlParam = urlParam + "?" + sbParams.substring(0, sbParams.length() - 1); } URL urlConet = new URL(urlParam); @@ -242,23 +223,21 @@ public class HttpRequest { InputStream inStream = con .getInputStream(); //通过输入流获取图片数据 ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] buffer = new byte[2048]; - int len = 0; + int len; while( (len=inStream.read(buffer)) != -1 ){ outStream.write(buffer, 0, len); } inStream.close(); - byte[] data = outStream.toByteArray(); - return data; + return outStream.toByteArray(); } /** * 从网络Url中下载文件 - * @param urlStr - * @param fileName - * @param savePath - * @throws IOException + * @param urlStr 请求地址 + * @param fileName 文件名 + * @param savePath 保存路径 */ - public static boolean downLoadFromUrl(String urlStr,String fileName,String savePath) throws IOException{ + public static void downLoadFromUrl(String urlStr, String fileName, String savePath) { try { URL url = new URL(urlStr); @@ -281,28 +260,21 @@ public class HttpRequest { File file = new File(saveDir+File.separator+fileName); FileOutputStream fos = new FileOutputStream(file); fos.write(getData); - if(fos!=null){ - fos.close(); - } - if(inputStream!=null){ - inputStream.close(); - } - return true; + fos.close(); + inputStream.close(); }catch (Exception e){ e.printStackTrace(); - return false; } } /** * 从输入流中获取字节数组 - * @param inputStream - * @return - * @throws IOException + * @param inputStream 字节流 + * @return 返回字节 */ public static byte[] readInputStream(InputStream inputStream) throws IOException { byte[] buffer = new byte[1024]; - int len = 0; + int len; ByteArrayOutputStream bos = new ByteArrayOutputStream(); while((len = inputStream.read(buffer)) != -1) { bos.write(buffer, 0, len); diff --git a/src/main/java/luckyclient/netty/NettyClient.java b/src/main/java/luckyclient/netty/NettyClient.java index bccce85..d6cac27 100644 --- a/src/main/java/luckyclient/netty/NettyClient.java +++ b/src/main/java/luckyclient/netty/NettyClient.java @@ -1,23 +1,9 @@ package luckyclient.netty; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.concurrent.TimeUnit; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.EventLoop; -import io.netty.channel.EventLoopGroup; +import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; @@ -26,6 +12,12 @@ import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.timeout.IdleStateHandler; import luckyclient.utils.config.SysConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.concurrent.TimeUnit; public class NettyClient { private static final String NETTY_SERVER_IP= SysConfig.getConfiguration().getProperty("server.web.ip"); @@ -34,61 +26,46 @@ public class NettyClient { protected static Channel channel; - private static ChannelFuture connect; - private static final Logger log = LoggerFactory.getLogger(NettyClient.class); private static ClientHandler clientHandler; - public static void start() throws InterruptedException{ + public static void start() { EventLoopGroup group = new NioEventLoopGroup(); - try { - Bootstrap b = new Bootstrap(); - clientHandler=new ClientHandler(); - b.group(group) - .channel(NioSocketChannel.class) - .option(ChannelOption.SO_KEEPALIVE,true) - .handler(new ChannelInitializer() { - @Override - public void initChannel(SocketChannel ch) throws Exception { - ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes()); - ChannelPipeline p = ch.pipeline(); - p.addLast(new DelimiterBasedFrameDecoder(1024, delimiter)); - p.addLast("decoder", new StringDecoder(Charset.forName("UTF-8"))); - p.addLast("encoder", new StringEncoder(Charset.forName("GBK"))); - p.addLast(new IdleStateHandler(1,0,0,TimeUnit.SECONDS)); - p.addLast(clientHandler); - } - }); - //连接服务端 - connect = b.connect(NETTY_SERVER_IP, NETTY_SERVER_PORT); - //断线重连 - connect.addListener(new ChannelFutureListener() { - @Override - public void operationComplete(ChannelFuture channelFuture) throws Exception { - if (!channelFuture.isSuccess()) { - final EventLoop loop = channelFuture.channel().eventLoop(); - loop.schedule(new Runnable() { - @Override - public void run() { - try { - log.error("服务端链接不上,开始重连操作..."); - start(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - }, 1L, TimeUnit.SECONDS); - } else { - channel = channelFuture.channel(); - log.info("服务端链接成功..."); + Bootstrap b = new Bootstrap(); + clientHandler=new ClientHandler(); + b.group(group) + .channel(NioSocketChannel.class) + .option(ChannelOption.SO_KEEPALIVE,true) + .handler(new ChannelInitializer() { + @Override + public void initChannel(SocketChannel ch) { + ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes()); + ChannelPipeline p = ch.pipeline(); + p.addLast(new DelimiterBasedFrameDecoder(1024, delimiter)); + p.addLast("decoder", new StringDecoder(StandardCharsets.UTF_8)); + p.addLast("encoder", new StringEncoder(Charset.forName("GBK"))); + p.addLast(new IdleStateHandler(1,0,0,TimeUnit.SECONDS)); + p.addLast(clientHandler); } - } - }); - } catch (IOException e) { - e.printStackTrace(); - } finally { - //不关闭通道 - //group.shutdownGracefully(); - } + }); + //连接服务端 + ChannelFuture connect = b.connect(NETTY_SERVER_IP, NETTY_SERVER_PORT); + //断线重连 + connect.addListener((ChannelFutureListener) channelFuture -> { + if (!channelFuture.isSuccess()) { + final EventLoop loop = channelFuture.channel().eventLoop(); + loop.schedule(() -> { + try { + log.error("服务端链接不上,开始重连操作..."); + start(); + } catch (Exception ignored) { + + } + }, 1L, TimeUnit.SECONDS); + } else { + channel = channelFuture.channel(); + log.info("服务端链接成功..."); + } + }); } } diff --git a/src/main/java/luckyclient/remote/api/GetServerApi.java b/src/main/java/luckyclient/remote/api/GetServerApi.java index bc7590e..d63f4ba 100644 --- a/src/main/java/luckyclient/remote/api/GetServerApi.java +++ b/src/main/java/luckyclient/remote/api/GetServerApi.java @@ -1,20 +1,12 @@ package luckyclient.remote.api; -import java.io.UnsupportedEncodingException; -import java.util.List; - import com.alibaba.fastjson.JSONObject; - import luckyclient.execution.dispose.ParamsManageForSteps; -import luckyclient.remote.entity.ProjectCase; -import luckyclient.remote.entity.ProjectCaseParams; -import luckyclient.remote.entity.ProjectCaseSteps; -import luckyclient.remote.entity.ProjectProtocolTemplate; -import luckyclient.remote.entity.ProjectTemplateParams; -import luckyclient.remote.entity.TaskExecute; -import luckyclient.remote.entity.TaskScheduling; +import luckyclient.remote.entity.*; import luckyclient.utils.httputils.HttpRequest; +import java.util.List; + /** * ================================================================= @@ -33,85 +25,78 @@ public class GetServerApi { /** * 通过计划ID获取测试用例对象集 - * @param planId - * @return + * @param planId 测试计划ID + * @return 返回用例List */ public static List getCasesbyplanId(int planId) { - String result = HttpRequest.loadJSON(PREFIX+"/clientGetCaseListByPlanId.do?planId=" + planId); - List caseList = JSONObject.parseArray(result, ProjectCase.class); - return caseList; + String result = HttpRequest.loadJSON(PREFIX+"/clientGetCaseListByPlanId.do?planId=" + planId); + return JSONObject.parseArray(result, ProjectCase.class); } /** * 通过计划名称获取测试用例对象集 - * @param name - * @return + * @param name 测试计划名称 + * @return 返回用例List */ public static List getCasesbyplanname(String name) { String result = HttpRequest.loadJSON(PREFIX+"/clientGetCaseListByPlanName.do?planName=" + name); - List caseList = JSONObject.parseArray(result, ProjectCase.class); - return caseList; + return JSONObject.parseArray(result, ProjectCase.class); } /** * 通过用例ID获取下面的步骤对象 - * @param caseid - * @return + * @param caseid 用例ID + * @return 返回用例步骤List */ public static List getStepsbycaseid(Integer caseid) { String result = HttpRequest.loadJSON(PREFIX+"/clientGetStepListByCaseId.do?caseId=" + caseid); - List stepsList = JSONObject.parseArray(result, ProjectCaseSteps.class); - return stepsList; + return JSONObject.parseArray(result, ProjectCaseSteps.class); } /** * 通过taskid获取对象 - * @param taskid - * @return + * @param taskid 测试任务ID + * @return 返回测试任务对象 */ public static TaskExecute cgetTaskbyid(int taskid) { String result = HttpRequest.loadJSON(PREFIX+"/clientGetTaskByTaskId.do?taskId=" + taskid); - TaskExecute task = JSONObject.parseObject(result, TaskExecute.class); - return task; + return JSONObject.parseObject(result, TaskExecute.class); } /** * 通过taskid获取调度对象 - * @param taskid - * @return + * @param taskid 测试任务ID + * @return 返回调度对象 */ public static TaskScheduling cGetTaskSchedulingByTaskId(int taskid) { String result = HttpRequest.loadJSON(PREFIX+"/clientGetTaskSchedulingByTaskId.do?taskId=" + taskid); - TaskScheduling taskScheduling = JSONObject.parseObject(result, TaskScheduling.class); - return taskScheduling; + return JSONObject.parseObject(result, TaskScheduling.class); } /** * 通过用例编号获取对象 - * @param sign - * @return + * @param sign 用例编号 + * @return 用例对象 */ public static ProjectCase cgetCaseBysign(String sign) { String result = HttpRequest.loadJSON(PREFIX+"/clientGetCaseByCaseSign.do?caseSign=" + sign); - ProjectCase projectCase = JSONObject.parseObject(result, ProjectCase.class); - return projectCase; + return JSONObject.parseObject(result, ProjectCase.class); } /** * 通过用例ID获取对象 - * @param caseId - * @return + * @param caseId 用例ID + * @return 用例对象 */ public static ProjectCase cGetCaseByCaseId(Integer caseId) { String result = HttpRequest.loadJSON(PREFIX+"/clientGetCaseByCaseId.do?caseId=" + caseId); - ProjectCase projectCase = JSONObject.parseObject(result, ProjectCase.class); - return projectCase; + return JSONObject.parseObject(result, ProjectCase.class); } /** * 获取项目下的所有公共参数 - * @param projectid - * @return + * @param projectid 项目ID + * @return 公共参数集合 */ public static List cgetParamsByProjectid(String projectid) { String result = HttpRequest.loadJSON(PREFIX+"/clientGetParamsByProjectId.do?projectId="+projectid); @@ -125,43 +110,36 @@ public class GetServerApi { /** * 通过计划ID获取测试用例对象集 - * @param taskId - * @return + * @param taskId 测试任务ID + * @return 测试用例ID集合 */ public static List clientGetCaseListForUnSucByTaskId(Integer taskId) { - String result = HttpRequest.loadJSON(PREFIX+"/clientGetCaseListForUnSucByTaskId.do?taskId=" + taskId); - List caseIdList = JSONObject.parseArray(result, Integer.class); - return caseIdList; + String result = HttpRequest.loadJSON(PREFIX+"/clientGetCaseListForUnSucByTaskId.do?taskId=" + taskId); + return JSONObject.parseArray(result, Integer.class); } /** * 通过templateId获取实体 - * @param templateId - * @return + * @param templateId 模板ID + * @return 协议模板对象 * @author Seagull * @date 2019年4月24日 */ public static ProjectProtocolTemplate clientGetProjectProtocolTemplateByTemplateId(Integer templateId) { String result = HttpRequest.loadJSON(PREFIX+"/clientGetProjectProtocolTemplateByTemplateId.do?templateId=" + templateId); - ProjectProtocolTemplate projectProtocolTemplate = JSONObject.parseObject(result, ProjectProtocolTemplate.class); - return projectProtocolTemplate; + return JSONObject.parseObject(result, ProjectProtocolTemplate.class); } /** * 通过模板ID获取参数列表 - * @param templateId - * @return + * @param templateId 模板ID + * @return 参数集合 * @author Seagull * @date 2019年4月24日 */ public static List clientGetProjectTemplateParamsListByTemplateId(Integer templateId) { String result = HttpRequest.loadJSON(PREFIX+"/clientGetProjectTemplateParamsListByTemplateId.do?templateId=" + templateId); - List projectTemplateParamsList = JSONObject.parseArray(result, ProjectTemplateParams.class); - return projectTemplateParamsList; - } - - public static void main(String[] args) throws UnsupportedEncodingException { - + return JSONObject.parseArray(result, ProjectTemplateParams.class); } } diff --git a/src/main/java/luckyclient/remote/api/PostServerApi.java b/src/main/java/luckyclient/remote/api/PostServerApi.java index 2b373c5..780bd0b 100644 --- a/src/main/java/luckyclient/remote/api/PostServerApi.java +++ b/src/main/java/luckyclient/remote/api/PostServerApi.java @@ -24,11 +24,11 @@ public class PostServerApi { /** * put web界面的数据到服务端 - * @param userId - * @param caseId - * @param logLevel - * @param logDetail - * @param debugIsend + * @param userId 用户ID + * @param caseId 用例ID + * @param logLevel 日志级别 + * @param logDetail 日志明细 + * @param debugIsend 结束标志 */ public static void cPostDebugLog(Integer userId, Integer caseId, String logLevel, String logDetail,Integer debugIsend){ ProjectCaseDebug projectCaseDebug = new ProjectCaseDebug(); @@ -43,12 +43,12 @@ public class PostServerApi { /** * 插入用例执行明细到数据库 - * @param taskId - * @param projectId - * @param caseId - * @param caseSign - * @param caseName - * @param caseStatus + * @param taskId 任务ID + * @param projectId 项目ID + * @param caseId 用例ID + * @param caseSign 用例编号 + * @param caseName 用例名称 + * @param caseStatus 用例状态 * @author Seagull * @date 2019年4月22日 */ @@ -66,9 +66,9 @@ public class PostServerApi { /** * 修改用例执行状态 - * @param taskId - * @param caseId - * @param caseStatus + * @param taskId 任务ID + * @param caseId 用例ID + * @param caseStatus 用例状态 * @author Seagull * @date 2019年4月22日 */ @@ -83,12 +83,12 @@ public class PostServerApi { /** * 插入用例执行明细到数据库 - * @param taskId - * @param caseId - * @param logDetail - * @param logGrade - * @param logStep - * @param imgname + * @param taskId 任务ID + * @param caseId 用例ID + * @param logDetail 日志明细 + * @param logGrade 日志等级 + * @param logStep 日志对应步骤 + * @param imgname 截图名称 * @author Seagull * @date 2019年4月22日 */ @@ -107,10 +107,10 @@ public class PostServerApi { /** * 更新任务执行数据 - * @param taskId - * @param caseCount - * @param taskStatus - * @return + * @param taskId 任务ID + * @param caseCount 用例总数 + * @param taskStatus 任务状态 + * @return 更新结果 */ public static String clientUpdateTaskExecuteData(Integer taskId, Integer caseCount, Integer taskStatus){ String str = "{\"taskId\":"+taskId+",\"caseCount\":"+caseCount+",\"taskStatus\":"+taskStatus+"}"; @@ -119,22 +119,21 @@ public class PostServerApi { } /** - * 更新任务执行数据 - * @param taskId - * @param caseId - * @return + * 删除用例执行日志 + * @param taskId 任务ID + * @param caseId 用例ID */ - public static String clientDeleteTaskCaseLog(Integer taskId, Integer caseId){ + public static void clientDeleteTaskCaseLog(Integer taskId, Integer caseId){ String str = "{\"taskId\":"+taskId+",\"caseId\":"+caseId+"}"; JSONObject jsonObject = JSON.parseObject(str); - return HttpRequest.httpClientPostJson(PREFIX+"/clientDeleteTaskCaseLog", jsonObject.toJSONString()); + HttpRequest.httpClientPostJson(PREFIX + "/clientDeleteTaskCaseLog", jsonObject.toJSONString()); } /** * 提取测试用例的详细日志以及结果 - * @param taskName - * @param caseSign - * @return + * @param taskName 任务名称 + * @param caseSign 用例编号 + * @return 提取结果 */ public static String getLogDetailResult(String taskName, String caseSign){ String str = "{\"taskName\":\""+taskName+"\",\"caseSign\":\""+caseSign+"\"}"; diff --git a/src/main/java/luckyclient/remote/api/serverOperation.java b/src/main/java/luckyclient/remote/api/serverOperation.java index 9382f95..96e6b52 100644 --- a/src/main/java/luckyclient/remote/api/serverOperation.java +++ b/src/main/java/luckyclient/remote/api/serverOperation.java @@ -1,262 +1,262 @@ -package luckyclient.remote.api; - -import java.util.Date; -import java.util.List; - -import com.alibaba.fastjson.JSONObject; - -import cn.hutool.core.util.StrUtil; -import luckyclient.remote.entity.TaskExecute; -import luckyclient.remote.entity.TaskScheduling; -import luckyclient.utils.LogUtil; - -/** - * - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull - * ================================================================= - * @author Seagull - * @date 2019年4月23日 - */ -public class serverOperation { - /** - * 任务执行类型: 0 任务调度模式 1 控制台模式 - */ - public static int exetype; - - /** - * 插入用例执行状态 0通过 1失败 2锁定 3执行中 4未执行 - */ - public void insertTaskCaseExecute(String taskIdStr, Integer projectId,Integer caseId, String caseSign,String caseName, Integer caseStatus) { - if (0 == exetype) { - Integer taskId=Integer.valueOf(taskIdStr); - PostServerApi.clientPostInsertTaskCaseExecute(taskId, projectId, caseId, caseSign, caseName, caseStatus); - } - } - - /** - * 更新用例执行状态 0通过 1失败 2锁定 3执行中 4未执行 - */ - public void updateTaskCaseExecuteStatus(String taskIdStr, Integer caseId, Integer caseStatus) { - if (0 == exetype) { - Integer taskId=Integer.valueOf(taskIdStr); - PostServerApi.clientUpdateTaskCaseExecuteStatus(taskId, caseId, caseStatus); - } - } - - /** - * 插入用例执行日志 - */ - public void insertTaskCaseLog(String taskIdStr, Integer caseId, String logDetail, String logGrade, String logStep, - String imgname) { - if (0 == exetype) { - if (logDetail.length()>5000) { - LogUtil.APP.info("第{}步,日志级别{},日志明细【{}】...日志明细超过5000字符,无法进入数据库存储,进行日志明细打印...",logStep,logGrade,logDetail); - logDetail="日志明细超过5000字符无法存入数据库,已在LOG4J日志中打印,请前往查看..."; - } - - Integer taskId=Integer.valueOf(taskIdStr); - PostServerApi.clientPostInsertTaskCaseLog(taskId, caseId, logDetail, logGrade, logStep, imgname); - } - } - - /** - * 更新本次任务的执行统计情况 - * 状态 0未执行 1执行中 2执行完成 3执行失败 4唤起客户端失败 - */ - public static int[] updateTaskExecuteData(String taskIdStr, int caseCount, int taskStatus) { - int[] taskcount = null; - if (0 == exetype) { - Integer taskId = Integer.parseInt(taskIdStr); - String str = PostServerApi.clientUpdateTaskExecuteData(taskId, caseCount,taskStatus); - JSONObject jsonObject = JSONObject.parseObject(str); - - // 返回本次任务执行情况 - taskcount = new int[5]; - taskcount[0] = jsonObject.getInteger("caseCount"); - taskcount[1] = jsonObject.getInteger("caseSuc"); - taskcount[2] = jsonObject.getInteger("caseFail"); - taskcount[3] = jsonObject.getInteger("caseLock"); - taskcount[4] = jsonObject.getInteger("caseNoExec"); - - } - return taskcount; - } - - /** - * 更新本次任务的执行状态 - * 状态 0未执行 1执行中 2执行完成 3执行失败 4唤起客户端失败 - */ - public static void updateTaskExecuteStatusIng(String taskIdStr, int caseCount) { - if (0 == exetype) { - Integer taskId = Integer.parseInt(taskIdStr); - PostServerApi.clientUpdateTaskExecuteData(taskId, caseCount,1); - } - } - - /** - * 删除单次任务指定的用例日志明细 - */ - public static void deleteTaskCaseLog(Integer caseId, String taskIdStr) { - Integer taskId = Integer.parseInt(taskIdStr); - PostServerApi.clientDeleteTaskCaseLog(taskId, caseId); - } - - /** - * 取出指定任务ID中的不属于成功状态的用例ID - */ - public List getCaseListForUnSucByTaskId(String taskIdStr) { - int taskId = Integer.parseInt(taskIdStr); - return GetServerApi.clientGetCaseListForUnSucByTaskId(taskId); - } - - /** - * 取出指定任务ID中所属的调度是否要发送邮件状态及收件人地址 发送邮件通知时的具体逻辑, -1-不通知 0-全部,1-成功,2-失败 - * 发送 eMailer varchar(100) ; --收件人 - */ - - public static String[] getEmailAddress(String taskIdStr) { - Integer taskId = Integer.parseInt(taskIdStr); - String[] address = null; - try { - TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(taskId); - if (!taskScheduling.getEmailSendCondition().equals(-1)) { - String temp = taskScheduling.getEmailAddress(); - // 清除最后一个; - if (temp.indexOf(";") > -1 && temp.substring(temp.length() - 1, temp.length()).indexOf(";") > -1) { - temp = temp.substring(0, temp.length() - 1); - } - // 多个地址 - if (temp.indexOf("null") <= -1 && temp.indexOf(";") > -1) { - address = temp.split(";", -1); - // 一个地址 - } else if (temp.indexOf("null") <= -1 && temp.indexOf(";") <= -1) { - address = new String[1]; - address[0] = temp; - } - } - } catch (Exception e) { - // TODO Auto-generated catch block - LogUtil.APP.error("获取邮件收件人地址出现异常,请检查!",e); - return address; - } - return address; - } - - /** - * 取出指定任务ID中所属的调度是否要自动构建以及构建的项目名称 为空时不构建 - */ - public static String[] getBuildName(String taskIdStr) { - Integer taskId = Integer.parseInt(taskIdStr); - String[] buildname = null; - try { - TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(taskId); - if (StrUtil.isEmpty(taskScheduling.getBuildingLink())) { - return buildname; - }else{ - String jobName = taskScheduling.getBuildingLink(); - // 清除最后一个; - if (jobName.indexOf(";") > -1 && jobName.substring(jobName.length() - 1, jobName.length()).indexOf(";") > -1) { - jobName = jobName.substring(0, jobName.length() - 1); - } - // 多个名称 - if (jobName.indexOf("null") <= -1 && jobName.indexOf(";") > -1) { - buildname = jobName.split(";", -1); - // 一个名称 - } else if (jobName.indexOf("null") <= -1 && jobName.indexOf(";") <= -1) { - buildname = new String[1]; - buildname[0] = jobName; - } - } - } catch (Exception e) { - // TODO Auto-generated catch block - LogUtil.APP.error("获取构建地址出现异常,请检查!",e); - return buildname; - } - return buildname; - } - - /** - * 取出指定任务ID中所属的调度是否要自动重启TOMCAT - * 自动重启 restartcomm varchar(200) ; -- 格式:服务器IP;服务器用户名;服务器密码;ssh端口;Shell命令; - * 例:192.168.222.22;pospsettle;pospsettle;22;cd - * /home/pospsettle/tomcat-7.0-7080/bin&&./restart.sh; - */ - - public static String[] getRestartComm(String taskIdStr) { - Integer taskId = Integer.parseInt(taskIdStr); - String[] command = null; - try { - TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(taskId); - if (null == taskScheduling.getRemoteShell() || "".equals(taskScheduling.getRemoteShell())) { - return command; - }else{ - String temp = taskScheduling.getRemoteShell(); - // 清除最后一个; - if (temp.indexOf(";") > -1 && temp.substring(temp.length() - 1, temp.length()).indexOf(";") > -1) { - temp = temp.substring(0, temp.length() - 1); - } - // 多个名称 - if (temp.indexOf("null") <= -1 && temp.indexOf(";") > -1) { - command = temp.split(";", -1); - // 一个名称 - } else if (temp.indexOf("null") <= -1 && temp.indexOf(";") <= -1) { - command = new String[1]; - command[0] = temp; - } - } - } catch (Exception e) { - // TODO Auto-generated catch block - LogUtil.APP.error("获取远程shell地址出现异常,请检查!",e); - return command; - } - return command; - - } - - /** - * 获取任务测试时长 - */ - public static String getTestTime(String taskIdStr) { - Integer taskId = Integer.parseInt(taskIdStr); - String desTime = "计算测试时长出错!"; - try { - TaskExecute taskExecute = GetServerApi.cgetTaskbyid(taskId); - Date start = taskExecute.getCreateTime(); - if (null!= taskExecute.getFinishTime()) { - Date finish = taskExecute.getFinishTime(); - long l = finish.getTime() - start.getTime(); - long day = l / (24 * 60 * 60 * 1000); - long hour = (l / (60 * 60 * 1000) - day * 24); - long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60); - long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60); - desTime = "" + hour + "小时" + min - + "" + s + "秒"; - } - } catch (Exception e) { - // TODO Auto-generated catch block - LogUtil.APP.error("获取任务测试时长出现异常,请检查!",e); - return desTime; - } - return desTime; - } - - /** - * 查询web执行,浏览器类型 UI自动化浏览器类型 0 IE 1 火狐 2 谷歌 3 Edge - */ - public static int querydrivertype(String taskIdStr) { - Integer taskId = Integer.parseInt(taskIdStr); - int driverType = 0; - try { - TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(taskId); - driverType = taskScheduling.getBrowserType(); - } catch (Exception e) { - // TODO Auto-generated catch block - LogUtil.APP.error("获取浏览器类型出现异常,请检查!",e); - return driverType; - } - return driverType; - } - -} +package luckyclient.remote.api; + +import java.util.Date; +import java.util.List; + +import com.alibaba.fastjson.JSONObject; + +import cn.hutool.core.util.StrUtil; +import luckyclient.remote.entity.TaskExecute; +import luckyclient.remote.entity.TaskScheduling; +import luckyclient.utils.LogUtil; + +/** + * + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull + * ================================================================= + * @author Seagull + * @date 2019年4月23日 + */ +public class serverOperation { + /** + * 任务执行类型: 0 任务调度模式 1 控制台模式 + */ + public static int exetype; + + /** + * 插入用例执行状态 0通过 1失败 2锁定 3执行中 4未执行 + */ + public void insertTaskCaseExecute(String taskIdStr, Integer projectId,Integer caseId, String caseSign,String caseName, Integer caseStatus) { + if (0 == exetype) { + Integer taskId=Integer.valueOf(taskIdStr); + PostServerApi.clientPostInsertTaskCaseExecute(taskId, projectId, caseId, caseSign, caseName, caseStatus); + } + } + + /** + * 更新用例执行状态 0通过 1失败 2锁定 3执行中 4未执行 + */ + public void updateTaskCaseExecuteStatus(String taskIdStr, Integer caseId, Integer caseStatus) { + if (0 == exetype) { + Integer taskId=Integer.valueOf(taskIdStr); + PostServerApi.clientUpdateTaskCaseExecuteStatus(taskId, caseId, caseStatus); + } + } + + /** + * 插入用例执行日志 + */ + public void insertTaskCaseLog(String taskIdStr, Integer caseId, String logDetail, String logGrade, String logStep, + String imgname) { + if (0 == exetype) { + if (logDetail.length()>5000) { + LogUtil.APP.info("第{}步,日志级别{},日志明细【{}】...日志明细超过5000字符,无法进入数据库存储,进行日志明细打印...",logStep,logGrade,logDetail); + logDetail="日志明细超过5000字符无法存入数据库,已在LOG4J日志中打印,请前往查看..."; + } + + Integer taskId=Integer.valueOf(taskIdStr); + PostServerApi.clientPostInsertTaskCaseLog(taskId, caseId, logDetail, logGrade, logStep, imgname); + } + } + + /** + * 更新本次任务的执行统计情况 + * 状态 0未执行 1执行中 2执行完成 3执行失败 4唤起客户端失败 + */ + public static int[] updateTaskExecuteData(String taskIdStr, int caseCount, int taskStatus) { + int[] taskcount = null; + if (0 == exetype) { + Integer taskId = Integer.parseInt(taskIdStr); + String str = PostServerApi.clientUpdateTaskExecuteData(taskId, caseCount,taskStatus); + JSONObject jsonObject = JSONObject.parseObject(str); + + // 返回本次任务执行情况 + taskcount = new int[5]; + taskcount[0] = jsonObject.getInteger("caseCount"); + taskcount[1] = jsonObject.getInteger("caseSuc"); + taskcount[2] = jsonObject.getInteger("caseFail"); + taskcount[3] = jsonObject.getInteger("caseLock"); + taskcount[4] = jsonObject.getInteger("caseNoExec"); + + } + return taskcount; + } + + /** + * 更新本次任务的执行状态 + * 状态 0未执行 1执行中 2执行完成 3执行失败 4唤起客户端失败 + */ + public static void updateTaskExecuteStatusIng(String taskIdStr, int caseCount) { + if (0 == exetype) { + Integer taskId = Integer.parseInt(taskIdStr); + PostServerApi.clientUpdateTaskExecuteData(taskId, caseCount,1); + } + } + + /** + * 删除单次任务指定的用例日志明细 + */ + public static void deleteTaskCaseLog(Integer caseId, String taskIdStr) { + Integer taskId = Integer.parseInt(taskIdStr); + PostServerApi.clientDeleteTaskCaseLog(taskId, caseId); + } + + /** + * 取出指定任务ID中的不属于成功状态的用例ID + */ + public List getCaseListForUnSucByTaskId(String taskIdStr) { + int taskId = Integer.parseInt(taskIdStr); + return GetServerApi.clientGetCaseListForUnSucByTaskId(taskId); + } + + /** + * 取出指定任务ID中所属的调度是否要发送邮件状态及收件人地址 发送邮件通知时的具体逻辑, -1-不通知 0-全部,1-成功,2-失败 + * 发送 eMailer varchar(100) ; --收件人 + */ + + public static String[] getEmailAddress(String taskIdStr) { + int taskId = Integer.parseInt(taskIdStr); + String[] address = null; + try { + TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(taskId); + if (!taskScheduling.getEmailSendCondition().equals(-1)) { + String temp = taskScheduling.getEmailAddress(); + // 清除最后一个; + if (temp.contains(";") && temp.substring(temp.length() - 1).contains(";")) { + temp = temp.substring(0, temp.length() - 1); + } + // 多个地址 + if (!temp.contains("null") && temp.contains(";")) { + address = temp.split(";", -1); + // 一个地址 + } else if (!temp.contains("null") && !temp.contains(";")) { + address = new String[1]; + address[0] = temp; + } + } + } catch (Exception e) { + // TODO Auto-generated catch block + LogUtil.APP.error("获取邮件收件人地址出现异常,请检查!",e); + return address; + } + return address; + } + + /** + * 取出指定任务ID中所属的调度是否要自动构建以及构建的项目名称 为空时不构建 + */ + public static String[] getBuildName(String taskIdStr) { + int taskId = Integer.parseInt(taskIdStr); + String[] buildname = null; + try { + TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(taskId); + if (StrUtil.isEmpty(taskScheduling.getBuildingLink())) { + return buildname; + }else{ + String jobName = taskScheduling.getBuildingLink(); + // 清除最后一个; + if (jobName.contains(";") && jobName.substring(jobName.length() - 1).contains(";")) { + jobName = jobName.substring(0, jobName.length() - 1); + } + // 多个名称 + if (!jobName.contains("null") && jobName.contains(";")) { + buildname = jobName.split(";", -1); + // 一个名称 + } else if (!jobName.contains("null") && !jobName.contains(";")) { + buildname = new String[1]; + buildname[0] = jobName; + } + } + } catch (Exception e) { + // TODO Auto-generated catch block + LogUtil.APP.error("获取构建地址出现异常,请检查!",e); + return buildname; + } + return buildname; + } + + /** + * 取出指定任务ID中所属的调度是否要自动重启TOMCAT + * 自动重启 restartcomm varchar(200) ; -- 格式:服务器IP;服务器用户名;服务器密码;ssh端口;Shell命令; + * 例:192.168.222.22;pospsettle;pospsettle;22;cd + * /home/pospsettle/tomcat-7.0-7080/bin&&./restart.sh; + */ + + public static String[] getRestartComm(String taskIdStr) { + int taskId = Integer.parseInt(taskIdStr); + String[] command = null; + try { + TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(taskId); + if (null == taskScheduling.getRemoteShell() || "".equals(taskScheduling.getRemoteShell())) { + return command; + }else{ + String temp = taskScheduling.getRemoteShell(); + // 清除最后一个; + if (temp.contains(";") && temp.substring(temp.length() - 1).contains(";")) { + temp = temp.substring(0, temp.length() - 1); + } + // 多个名称 + if (!temp.contains("null") && temp.contains(";")) { + command = temp.split(";", -1); + // 一个名称 + } else if (!temp.contains("null") && !temp.contains(";")) { + command = new String[1]; + command[0] = temp; + } + } + } catch (Exception e) { + // TODO Auto-generated catch block + LogUtil.APP.error("获取远程shell地址出现异常,请检查!",e); + return command; + } + return command; + + } + + /** + * 获取任务测试时长 + */ + public static String getTestTime(String taskIdStr) { + int taskId = Integer.parseInt(taskIdStr); + String desTime = "计算测试时长出错!"; + try { + TaskExecute taskExecute = GetServerApi.cgetTaskbyid(taskId); + Date start = taskExecute.getCreateTime(); + if (null!= taskExecute.getFinishTime()) { + Date finish = taskExecute.getFinishTime(); + long l = finish.getTime() - start.getTime(); + long day = l / (24 * 60 * 60 * 1000); + long hour = (l / (60 * 60 * 1000) - day * 24); + long min = ((l / (60 * 1000)) - day * 24 * 60 - hour * 60); + long s = (l / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60); + desTime = "" + hour + "小时" + min + + "" + s + "秒"; + } + } catch (Exception e) { + // TODO Auto-generated catch block + LogUtil.APP.error("获取任务测试时长出现异常,请检查!",e); + return desTime; + } + return desTime; + } + + /** + * 查询web执行,浏览器类型 UI自动化浏览器类型 0 IE 1 火狐 2 谷歌 3 Edge + */ + public static int querydrivertype(String taskIdStr) { + int taskId = Integer.parseInt(taskIdStr); + int driverType = 0; + try { + TaskScheduling taskScheduling = GetServerApi.cGetTaskSchedulingByTaskId(taskId); + driverType = taskScheduling.getBrowserType(); + } catch (Exception e) { + // TODO Auto-generated catch block + LogUtil.APP.error("获取浏览器类型出现异常,请检查!",e); + return driverType; + } + return driverType; + } + +} diff --git a/src/main/java/luckyclient/remote/entity/monitor/IpUtils.java b/src/main/java/luckyclient/remote/entity/monitor/IpUtils.java index e617979..8fcadcb 100644 --- a/src/main/java/luckyclient/remote/entity/monitor/IpUtils.java +++ b/src/main/java/luckyclient/remote/entity/monitor/IpUtils.java @@ -1,202 +1,197 @@ -package luckyclient.remote.entity.monitor; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import javax.servlet.http.HttpServletRequest; - -/** - * 获取IP方法 - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull - * ================================================================= - * @author Seagull - * @date 2019年5月5日 - */ -public class IpUtils -{ - public static String getIpAddr(HttpServletRequest request) - { - if (request == null) - { - return "unknown"; - } - String ip = request.getHeader("x-forwarded-for"); - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getHeader("Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getHeader("X-Forwarded-For"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getHeader("WL-Proxy-Client-IP"); - } - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getHeader("X-Real-IP"); - } - - if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) - { - ip = request.getRemoteAddr(); - } - - return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip; - } - - public static boolean internalIp(String ip) - { - byte[] addr = textToNumericFormatV4(ip); - return internalIp(addr) || "127.0.0.1".equals(ip); - } - - private static boolean internalIp(byte[] addr) - { - final byte b0 = addr[0]; - final byte b1 = addr[1]; - // 10.x.x.x/8 - final byte section1 = 0x0A; - // 172.16.x.x/12 - final byte section2 = (byte) 0xAC; - final byte section3 = (byte) 0x10; - final byte section4 = (byte) 0x1F; - // 192.168.x.x/16 - final byte section5 = (byte) 0xC0; - final byte section6 = (byte) 0xA8; - switch (b0) - { - case section1: - return true; - case section2: - if (b1 >= section3 && b1 <= section4) - { - return true; - } - case section5: - switch (b1) - { - case section6: - return true; - default: - return false; - } - default: - return false; - } - } - - /** - * 将IPv4地址转换成字节 - * - * @param text IPv4地址 - * @return byte 字节 - */ - public static byte[] textToNumericFormatV4(String text) - { - if (text.length() == 0) - { - return null; - } - - byte[] bytes = new byte[4]; - String[] elements = text.split("\\.", -1); - try - { - long l; - int i; - switch (elements.length) - { - case 1: - l = Long.parseLong(elements[0]); - if ((l < 0L) || (l > 4294967295L)){ - return null; - } - - bytes[0] = (byte) (int) (l >> 24 & 0xFF); - bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); - bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); - bytes[3] = (byte) (int) (l & 0xFF); - break; - case 2: - l = Integer.parseInt(elements[0]); - if ((l < 0L) || (l > 255L)){ - return null; - } - - bytes[0] = (byte) (int) (l & 0xFF); - l = Integer.parseInt(elements[1]); - if ((l < 0L) || (l > 16777215L)){ - return null; - } - - bytes[1] = (byte) (int) (l >> 16 & 0xFF); - bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); - bytes[3] = (byte) (int) (l & 0xFF); - break; - case 3: - for (i = 0; i < 2; ++i) - { - l = Integer.parseInt(elements[i]); - if ((l < 0L) || (l > 255L)){ - return null; - } - - bytes[i] = (byte) (int) (l & 0xFF); - } - l = Integer.parseInt(elements[2]); - if ((l < 0L) || (l > 65535L)){ - return null; - } - - bytes[2] = (byte) (int) (l >> 8 & 0xFF); - bytes[3] = (byte) (int) (l & 0xFF); - break; - case 4: - for (i = 0; i < 4; ++i) - { - l = Integer.parseInt(elements[i]); - if ((l < 0L) || (l > 255L)){ - return null; - } - - bytes[i] = (byte) (int) (l & 0xFF); - } - break; - default: - return null; - } - } - catch (NumberFormatException e) - { - return null; - } - return bytes; - } - - public static String getHostIp() - { - try - { - return InetAddress.getLocalHost().getHostAddress(); - } - catch (UnknownHostException e) - { - } - return "127.0.0.1"; - } - - public static String getHostName() - { - try - { - return InetAddress.getLocalHost().getHostName(); - } - catch (UnknownHostException e) - { - } - return "未知"; - } +package luckyclient.remote.entity.monitor; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import javax.servlet.http.HttpServletRequest; + +/** + * 获取IP方法 + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull + * ================================================================= + * @author Seagull + * @date 2019年5月5日 + */ +public class IpUtils +{ + public static String getIpAddr(HttpServletRequest request) + { + if (request == null) + { + return "unknown"; + } + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("X-Forwarded-For"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getHeader("X-Real-IP"); + } + + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) + { + ip = request.getRemoteAddr(); + } + + return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip; + } + + public static boolean internalIp(String ip) + { + byte[] addr = textToNumericFormatV4(ip); + assert addr != null; + return internalIp(addr) || "127.0.0.1".equals(ip); + } + + private static boolean internalIp(byte[] addr) + { + final byte b0 = addr[0]; + final byte b1 = addr[1]; + // 10.x.x.x/8 + final byte section1 = 0x0A; + // 172.16.x.x/12 + final byte section2 = (byte) 0xAC; + final byte section3 = (byte) 0x10; + final byte section4 = (byte) 0x1F; + // 192.168.x.x/16 + final byte section5 = (byte) 0xC0; + final byte section6 = (byte) 0xA8; + switch (b0) + { + case section1: + return true; + case section2: + if (b1 >= section3 && b1 <= section4) + { + return true; + } + case section5: + return b1 == section6; + default: + return false; + } + } + + /** + * 将IPv4地址转换成字节 + * + * @param text IPv4地址 + * @return byte 字节 + */ + public static byte[] textToNumericFormatV4(String text) + { + if (text.length() == 0) + { + return null; + } + + byte[] bytes = new byte[4]; + String[] elements = text.split("\\.", -1); + try + { + long l; + int i; + switch (elements.length) + { + case 1: + l = Long.parseLong(elements[0]); + if ((l < 0L) || (l > 4294967295L)){ + return null; + } + + bytes[0] = (byte) (int) (l >> 24 & 0xFF); + bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 2: + l = Integer.parseInt(elements[0]); + if ((l < 0L) || (l > 255L)){ + return null; + } + + bytes[0] = (byte) (int) (l & 0xFF); + l = Integer.parseInt(elements[1]); + if ((l < 0L) || (l > 16777215L)){ + return null; + } + + bytes[1] = (byte) (int) (l >> 16 & 0xFF); + bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 3: + for (i = 0; i < 2; ++i) + { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)){ + return null; + } + + bytes[i] = (byte) (int) (l & 0xFF); + } + l = Integer.parseInt(elements[2]); + if ((l < 0L) || (l > 65535L)){ + return null; + } + + bytes[2] = (byte) (int) (l >> 8 & 0xFF); + bytes[3] = (byte) (int) (l & 0xFF); + break; + case 4: + for (i = 0; i < 4; ++i) + { + l = Integer.parseInt(elements[i]); + if ((l < 0L) || (l > 255L)){ + return null; + } + + bytes[i] = (byte) (int) (l & 0xFF); + } + break; + default: + return null; + } + } + catch (NumberFormatException e) + { + return null; + } + return bytes; + } + + public static String getHostIp() + { + try + { + return InetAddress.getLocalHost().getHostAddress(); + } + catch (UnknownHostException ignored) + { + } + return "127.0.0.1"; + } + + public static String getHostName() + { + try + { + return InetAddress.getLocalHost().getHostName(); + } + catch (UnknownHostException ignored) + { + } + return "未知"; + } } \ No newline at end of file diff --git a/src/main/java/luckyclient/remote/entity/monitor/Server.java b/src/main/java/luckyclient/remote/entity/monitor/Server.java index 2542a22..52659c5 100644 --- a/src/main/java/luckyclient/remote/entity/monitor/Server.java +++ b/src/main/java/luckyclient/remote/entity/monitor/Server.java @@ -1,238 +1,236 @@ -package luckyclient.remote.entity.monitor; - -import java.net.UnknownHostException; -import java.util.LinkedList; -import java.util.List; -import java.util.Properties; - -import oshi.SystemInfo; -import oshi.hardware.CentralProcessor; -import oshi.hardware.CentralProcessor.TickType; -import oshi.hardware.GlobalMemory; -import oshi.hardware.HardwareAbstractionLayer; -import oshi.software.os.FileSystem; -import oshi.software.os.OSFileStore; -import oshi.software.os.OperatingSystem; -import oshi.util.Util; - -/** - * 服务器相关信息 - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull - * ================================================================= - * @author Seagull - * @date 2019年5月5日 - */ -public class Server -{ - private static final int OSHI_WAIT_SECOND = 1000; - - /** - * CPU相关信息 - */ - private Cpu cpu = new Cpu(); - - /** - * 內存相关信息 - */ - private Mem mem = new Mem(); - - /** - * JVM相关信息 - */ - private Jvm jvm = new Jvm(); - - /** - * 服务器相关信息 - */ - private Sys sys = new Sys(); - - /** - * 磁盘相关信息 - */ - private List sysFiles = new LinkedList(); - - public Cpu getCpu() - { - return cpu; - } - - public void setCpu(Cpu cpu) - { - this.cpu = cpu; - } - - public Mem getMem() - { - return mem; - } - - public void setMem(Mem mem) - { - this.mem = mem; - } - - public Jvm getJvm() - { - return jvm; - } - - public void setJvm(Jvm jvm) - { - this.jvm = jvm; - } - - public Sys getSys() - { - return sys; - } - - public void setSys(Sys sys) - { - this.sys = sys; - } - - public List getSysFiles() - { - return sysFiles; - } - - public void setSysFiles(List sysFiles) - { - this.sysFiles = sysFiles; - } - - public void copyTo() throws Exception - { - SystemInfo si = new SystemInfo(); - HardwareAbstractionLayer hal = si.getHardware(); - - setCpuInfo(hal.getProcessor()); - - setMemInfo(hal.getMemory()); - - setSysInfo(); - - setJvmInfo(); - - setSysFiles(si.getOperatingSystem()); - } - - /** - * 设置CPU信息 - */ - private void setCpuInfo(CentralProcessor processor) - { - // CPU信息 - long[] prevTicks = processor.getSystemCpuLoadTicks(); - Util.sleep(OSHI_WAIT_SECOND); - long[] ticks = processor.getSystemCpuLoadTicks(); - long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()]; - long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()]; - long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()]; - long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()]; - long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()]; - long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()]; - long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()]; - long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()]; - long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal; - cpu.setCpuNum(processor.getLogicalProcessorCount()); - cpu.setTotal(totalCpu); - cpu.setSys(cSys); - cpu.setUsed(user); - cpu.setWait(iowait); - cpu.setFree(idle); - } - - /** - * 设置内存信息 - */ - private void setMemInfo(GlobalMemory memory) - { - mem.setTotal(memory.getTotal()); - mem.setUsed(memory.getTotal() - memory.getAvailable()); - mem.setFree(memory.getAvailable()); - } - - /** - * 设置服务器信息 - */ - private void setSysInfo() - { - Properties props = System.getProperties(); - sys.setComputerName(IpUtils.getHostName()); - sys.setComputerIp(IpUtils.getHostIp()); - sys.setOsName(props.getProperty("os.name")); - sys.setOsArch(props.getProperty("os.arch")); - sys.setUserDir(props.getProperty("user.dir")); - } - - /** - * 设置Java虚拟机 - */ - private void setJvmInfo() throws UnknownHostException - { - Properties props = System.getProperties(); - jvm.setTotal(Runtime.getRuntime().totalMemory()); - jvm.setMax(Runtime.getRuntime().maxMemory()); - jvm.setFree(Runtime.getRuntime().freeMemory()); - jvm.setVersion(props.getProperty("java.version")); - jvm.setHome(props.getProperty("java.home")); - } - - /** - * 设置磁盘信息 - */ - private void setSysFiles(OperatingSystem os) - { - FileSystem fileSystem = os.getFileSystem(); - OSFileStore[] fsArray = fileSystem.getFileStores(); - for (OSFileStore fs : fsArray) - { - long free = fs.getUsableSpace(); - long total = fs.getTotalSpace(); - long used = total - free; - SysFile sysFile = new SysFile(); - sysFile.setDirName(fs.getMount()); - sysFile.setSysTypeName(fs.getType()); - sysFile.setTypeName(fs.getName()); - sysFile.setTotal(convertFileSize(total)); - sysFile.setFree(convertFileSize(free)); - sysFile.setUsed(convertFileSize(used)); - sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100)); - sysFiles.add(sysFile); - } - } - - /** - * 字节转换 - * - * @param size 字节大小 - * @return 转换后值 - */ - public String convertFileSize(long size) - { - long kb = 1024; - long mb = kb * 1024; - long gb = mb * 1024; - if (size >= gb) - { - return String.format("%.1f GB", (float) size / gb); - } - else if (size >= mb) - { - float f = (float) size / mb; - return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f); - } - else if (size >= kb) - { - float f = (float) size / kb; - return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f); - } - else - { - return String.format("%d B", size); - } - } -} +package luckyclient.remote.entity.monitor; + +import java.net.UnknownHostException; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; + +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.CentralProcessor.TickType; +import oshi.hardware.GlobalMemory; +import oshi.hardware.HardwareAbstractionLayer; +import oshi.software.os.FileSystem; +import oshi.software.os.OSFileStore; +import oshi.software.os.OperatingSystem; +import oshi.util.Util; + +/** + * 服务器相关信息 + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull + * ================================================================= + * @author Seagull + * @date 2019年5月5日 + */ +public class Server +{ + private static final int OSHI_WAIT_SECOND = 1000; + + /** + * CPU相关信息 + */ + private Cpu cpu = new Cpu(); + + /** + * 內存相关信息 + */ + private Mem mem = new Mem(); + + /** + * JVM相关信息 + */ + private Jvm jvm = new Jvm(); + + /** + * 服务器相关信息 + */ + private Sys sys = new Sys(); + + /** + * 磁盘相关信息 + */ + private List sysFiles = new LinkedList<>(); + + public Cpu getCpu() + { + return cpu; + } + + public void setCpu(Cpu cpu) + { + this.cpu = cpu; + } + + public Mem getMem() + { + return mem; + } + + public void setMem(Mem mem) + { + this.mem = mem; + } + + public Jvm getJvm() + { + return jvm; + } + + public void setJvm(Jvm jvm) + { + this.jvm = jvm; + } + + public Sys getSys() + { + return sys; + } + + public void setSys(Sys sys) + { + this.sys = sys; + } + + public List getSysFiles() + { + return sysFiles; + } + + public void setSysFiles(List sysFiles) + { + this.sysFiles = sysFiles; + } + + public void copyTo() { + SystemInfo si = new SystemInfo(); + HardwareAbstractionLayer hal = si.getHardware(); + + setCpuInfo(hal.getProcessor()); + + setMemInfo(hal.getMemory()); + + setSysInfo(); + + setJvmInfo(); + + setSysFiles(si.getOperatingSystem()); + } + + /** + * 设置CPU信息 + */ + private void setCpuInfo(CentralProcessor processor) + { + // CPU信息 + long[] prevTicks = processor.getSystemCpuLoadTicks(); + Util.sleep(OSHI_WAIT_SECOND); + long[] ticks = processor.getSystemCpuLoadTicks(); + long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()]; + long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()]; + long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()]; + long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()]; + long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()]; + long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()]; + long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()]; + long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()]; + long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal; + cpu.setCpuNum(processor.getLogicalProcessorCount()); + cpu.setTotal(totalCpu); + cpu.setSys(cSys); + cpu.setUsed(user); + cpu.setWait(iowait); + cpu.setFree(idle); + } + + /** + * 设置内存信息 + */ + private void setMemInfo(GlobalMemory memory) + { + mem.setTotal(memory.getTotal()); + mem.setUsed(memory.getTotal() - memory.getAvailable()); + mem.setFree(memory.getAvailable()); + } + + /** + * 设置服务器信息 + */ + private void setSysInfo() + { + Properties props = System.getProperties(); + sys.setComputerName(IpUtils.getHostName()); + sys.setComputerIp(IpUtils.getHostIp()); + sys.setOsName(props.getProperty("os.name")); + sys.setOsArch(props.getProperty("os.arch")); + sys.setUserDir(props.getProperty("user.dir")); + } + + /** + * 设置Java虚拟机 + */ + private void setJvmInfo() { + Properties props = System.getProperties(); + jvm.setTotal(Runtime.getRuntime().totalMemory()); + jvm.setMax(Runtime.getRuntime().maxMemory()); + jvm.setFree(Runtime.getRuntime().freeMemory()); + jvm.setVersion(props.getProperty("java.version")); + jvm.setHome(props.getProperty("java.home")); + } + + /** + * 设置磁盘信息 + */ + private void setSysFiles(OperatingSystem os) + { + FileSystem fileSystem = os.getFileSystem(); + OSFileStore[] fsArray = fileSystem.getFileStores(); + for (OSFileStore fs : fsArray) + { + long free = fs.getUsableSpace(); + long total = fs.getTotalSpace(); + long used = total - free; + SysFile sysFile = new SysFile(); + sysFile.setDirName(fs.getMount()); + sysFile.setSysTypeName(fs.getType()); + sysFile.setTypeName(fs.getName()); + sysFile.setTotal(convertFileSize(total)); + sysFile.setFree(convertFileSize(free)); + sysFile.setUsed(convertFileSize(used)); + sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100)); + sysFiles.add(sysFile); + } + } + + /** + * 字节转换 + * + * @param size 字节大小 + * @return 转换后值 + */ + public String convertFileSize(long size) + { + long kb = 1024; + long mb = kb * 1024; + long gb = mb * 1024; + if (size >= gb) + { + return String.format("%.1f GB", (float) size / gb); + } + else if (size >= mb) + { + float f = (float) size / mb; + return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f); + } + else if (size >= kb) + { + float f = (float) size / kb; + return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f); + } + else + { + return String.format("%d B", size); + } + } +} diff --git a/src/main/java/luckyclient/tool/jenkins/BuildingInitialization.java b/src/main/java/luckyclient/tool/jenkins/BuildingInitialization.java index 8eccf74..cf8ed19 100644 --- a/src/main/java/luckyclient/tool/jenkins/BuildingInitialization.java +++ b/src/main/java/luckyclient/tool/jenkins/BuildingInitialization.java @@ -1,73 +1,73 @@ -package luckyclient.tool.jenkins; - -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import com.offbytwo.jenkins.model.BuildResult; - -import luckyclient.remote.api.serverOperation; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * - * @date 2017年12月1日 上午9:29:40 - * - */ -public class BuildingInitialization { - - protected static int THREAD_COUNT = 0; - protected static int THREAD_SUCCOUNT = 0; - - public static BuildResult buildingRun(String tastid) throws InterruptedException { - try { - String[] jobName = serverOperation.getBuildName(tastid); - - if (jobName != null) { - ThreadPoolExecutor threadExecute = new ThreadPoolExecutor(jobName.length, 10, 3, TimeUnit.SECONDS, - new ArrayBlockingQueue(1000), - new ThreadPoolExecutor.CallerRunsPolicy()); - - LogUtil.APP.info("准备将配置的测试项目进行构建!请稍等。。。。"); - for (int i = 0; i < jobName.length; i++) { - BuildingInitialization.THREAD_COUNT++; //多线程计数++,用于检测线程是否全部执行完 - threadExecute.execute(new ThreadForBuildJob(jobName[i])); - } - - //多线程计数,用于检测线程是否全部执行完 - int k=0; - while(BuildingInitialization.THREAD_COUNT!=0){ - k++; - //最长等待构建时间45分钟 - if(k>2700){ - break; - } - Thread.sleep(1000); - } - threadExecute.shutdown(); - - if(jobName.length!=THREAD_SUCCOUNT){ - LogUtil.APP.info("待构建项目{}个,构建成功的项目{}个,有构建任务异常或失败状态,详情请查看构建日志...",jobName.length,THREAD_SUCCOUNT); - return BuildResult.FAILURE; - }else{ - LogUtil.APP.info("总共构建成功的项目{}个,全部构建成功,详情请查看构建日志...",THREAD_SUCCOUNT); - } - - } else { - LogUtil.APP.info("当前任务没有找到需要构建的项目!"); - } - } catch (Exception e) { - LogUtil.APP.error("项目构建过程中出现异常", e); - return BuildResult.UNSTABLE; - } - return BuildResult.SUCCESS; - - } - -} +package luckyclient.tool.jenkins; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import com.offbytwo.jenkins.model.BuildResult; + +import luckyclient.remote.api.serverOperation; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * + * @date 2017年12月1日 上午9:29:40 + * + */ +public class BuildingInitialization { + + protected static int THREAD_COUNT = 0; + protected static int THREAD_SUCCOUNT = 0; + + public static BuildResult buildingRun(String tastid) { + try { + String[] jobName = serverOperation.getBuildName(tastid); + + if (jobName != null) { + ThreadPoolExecutor threadExecute = new ThreadPoolExecutor(jobName.length, 10, 3, TimeUnit.SECONDS, + new ArrayBlockingQueue<>(1000), + new ThreadPoolExecutor.CallerRunsPolicy()); + + LogUtil.APP.info("准备将配置的测试项目进行构建!请稍等。。。。"); + for (String s : jobName) { + BuildingInitialization.THREAD_COUNT++; //多线程计数++,用于检测线程是否全部执行完 + threadExecute.execute(new ThreadForBuildJob(s)); + } + + //多线程计数,用于检测线程是否全部执行完 + int k=0; + while(BuildingInitialization.THREAD_COUNT!=0){ + k++; + //最长等待构建时间45分钟 + if(k>2700){ + break; + } + Thread.sleep(1000); + } + threadExecute.shutdown(); + + if(jobName.length!=THREAD_SUCCOUNT){ + LogUtil.APP.info("待构建项目{}个,构建成功的项目{}个,有构建任务异常或失败状态,详情请查看构建日志...",jobName.length,THREAD_SUCCOUNT); + return BuildResult.FAILURE; + }else{ + LogUtil.APP.info("总共构建成功的项目{}个,全部构建成功,详情请查看构建日志...",THREAD_SUCCOUNT); + } + + } else { + LogUtil.APP.info("当前任务没有找到需要构建的项目!"); + } + } catch (Exception e) { + LogUtil.APP.error("项目构建过程中出现异常", e); + return BuildResult.UNSTABLE; + } + return BuildResult.SUCCESS; + + } + +} diff --git a/src/main/java/luckyclient/tool/jenkins/JenkinsConnect.java b/src/main/java/luckyclient/tool/jenkins/JenkinsConnect.java index 9f0ebdd..e0f6544 100644 --- a/src/main/java/luckyclient/tool/jenkins/JenkinsConnect.java +++ b/src/main/java/luckyclient/tool/jenkins/JenkinsConnect.java @@ -1,70 +1,68 @@ -package luckyclient.tool.jenkins; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Properties; - -import com.offbytwo.jenkins.JenkinsServer; -import com.offbytwo.jenkins.client.JenkinsHttpClient; - -import luckyclient.utils.LogUtil; -import luckyclient.utils.config.SysConfig; - -/** - * Jenkins链接 - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull - * ================================================================= - * @author Seagull - * @date 2019年10月29日 - */ -public class JenkinsConnect { - - private String JENKINS_URL; - private String JENKINS_USERNAME; - private String JENKINS_PASSWORD; - - JenkinsConnect() { - Properties properties = SysConfig.getConfiguration(); - this.JENKINS_URL=properties.getProperty("jenkins.url"); - this.JENKINS_USERNAME=properties.getProperty("jenkins.username"); - this.JENKINS_PASSWORD=properties.getProperty("jenkins.password"); - } - - /** - * 如果有些 API 该Jar工具包未提供,可以用此Http客户端操作远程接口,执行命令 - * @return - * @author Seagull - * @date 2019年10月29日 - */ - public JenkinsHttpClient getClient() { - JenkinsHttpClient jenkinsHttpClient = null; - try { - jenkinsHttpClient = new JenkinsHttpClient(new URI(JENKINS_URL), JENKINS_USERNAME, JENKINS_PASSWORD); - } catch (URISyntaxException e) { - e.printStackTrace(); - } - return jenkinsHttpClient; - } - - /** - * Jenkins API链接 - * @return - * @author Seagull - * @date 2019年10月29日 - */ - public JenkinsServer connection() { - JenkinsServer jenkinsServer = null; - try { - LogUtil.APP.info("准备连接Jenkins...URL:{} 用户名:{} 密码:{}",JENKINS_URL,JENKINS_USERNAME,JENKINS_PASSWORD); - jenkinsServer = new JenkinsServer(new URI(JENKINS_URL), JENKINS_USERNAME, JENKINS_PASSWORD); - LogUtil.APP.info("连接Jenkins成功!"); - LogUtil.APP.info("Jenkins版本:{}",jenkinsServer.getVersion()); - } catch (URISyntaxException e) { - LogUtil.APP.error("连接Jenkins出现异常",e); - } - return jenkinsServer; - } - +package luckyclient.tool.jenkins; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Properties; + +import com.offbytwo.jenkins.JenkinsServer; +import com.offbytwo.jenkins.client.JenkinsHttpClient; + +import luckyclient.utils.LogUtil; +import luckyclient.utils.config.SysConfig; + +/** + * Jenkins链接 + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull + * ================================================================= + * @author Seagull + * @date 2019年10月29日 + */ +public class JenkinsConnect { + + private String JENKINS_URL; + private String JENKINS_USERNAME; + private String JENKINS_PASSWORD; + + JenkinsConnect() { + Properties properties = SysConfig.getConfiguration(); + this.JENKINS_URL=properties.getProperty("jenkins.url"); + this.JENKINS_USERNAME=properties.getProperty("jenkins.username"); + this.JENKINS_PASSWORD=properties.getProperty("jenkins.password"); + } + + /** + * 如果有些 API 该Jar工具包未提供,可以用此Http客户端操作远程接口,执行命令 + * @return 返回jenkins客户端对象 + */ + public JenkinsHttpClient getClient() { + JenkinsHttpClient jenkinsHttpClient = null; + try { + jenkinsHttpClient = new JenkinsHttpClient(new URI(JENKINS_URL), JENKINS_USERNAME, JENKINS_PASSWORD); + } catch (URISyntaxException e) { + e.printStackTrace(); + } + return jenkinsHttpClient; + } + + /** + * Jenkins API链接 + * @return 返回jenkins服务对象 + * @author Seagull + * @date 2019年10月29日 + */ + public JenkinsServer connection() { + JenkinsServer jenkinsServer = null; + try { + LogUtil.APP.info("准备连接Jenkins...URL:{} 用户名:{} 密码:{}",JENKINS_URL,JENKINS_USERNAME,JENKINS_PASSWORD); + jenkinsServer = new JenkinsServer(new URI(JENKINS_URL), JENKINS_USERNAME, JENKINS_PASSWORD); + LogUtil.APP.info("连接Jenkins成功!"); + LogUtil.APP.info("Jenkins版本:{}",jenkinsServer.getVersion()); + } catch (URISyntaxException e) { + LogUtil.APP.error("连接Jenkins出现异常",e); + } + return jenkinsServer; + } + } \ No newline at end of file diff --git a/src/main/java/luckyclient/tool/jenkins/JobBuildApi.java b/src/main/java/luckyclient/tool/jenkins/JobBuildApi.java index 32b292e..99ae38d 100644 --- a/src/main/java/luckyclient/tool/jenkins/JobBuildApi.java +++ b/src/main/java/luckyclient/tool/jenkins/JobBuildApi.java @@ -1,94 +1,94 @@ -package luckyclient.tool.jenkins; - -import java.io.IOException; - -import com.offbytwo.jenkins.JenkinsServer; -import com.offbytwo.jenkins.model.BuildResult; -import com.offbytwo.jenkins.model.BuildWithDetails; -import com.offbytwo.jenkins.model.ConsoleLog; -import com.offbytwo.jenkins.model.JobWithDetails; - -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.StrUtil; -import luckyclient.utils.LogUtil; - -/** - * * Job Build(任务构建) 相关操作 例如对任务 Build 相关的信息进行获取操作、例如获取构建日志 - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull - * ================================================================= - * - * @author Seagull - * @date 2019年10月30日 - */ -public class JobBuildApi { - - // Jenkins 对象 - private JenkinsServer jenkinsServer; - // http 客户端对象 - //private JenkinsHttpClient jenkinsHttpClient; - - /** - * 构造方法中调用连接 Jenkins 方法 - * - * 2019年10月30日 - */ - JobBuildApi() { - JenkinsConnect jenkinsConnect = new JenkinsConnect(); - // 连接 Jenkins - jenkinsServer = jenkinsConnect.connection(); - // 设置客户端连接 Jenkins - //jenkinsHttpClient = jenkinsConnect.getClient(); - } - - /** - * 通过job名称触发构建并获取构建结果 - * @param jobName - * @return - * @author Seagull - * @date 2019年11月29日 - */ - public BuildResult buildAndGetResultForJobName(String jobName) { - BuildResult buildResult = null; - try { - //触发构建 - jenkinsServer.getJob(jobName).build(false); - // 获取 Job 信息 - JobWithDetails job = jenkinsServer.getJob(jobName); - // 这里用最后一次编译来示例 - BuildWithDetails build = job.getLastBuild().details(); - // 获取构建的显示名称 - LogUtil.APP.info("构建项目:{}, 构建名称:{}", jobName,build.getDisplayName()); - // 获取构建的参数信息 - LogUtil.APP.info("构建项目:{}, 构建参数:{}", jobName,build.getParameters()); - // 获取构建编号 - LogUtil.APP.info("构建项目:{}, 构建编号:{}", jobName,build.getNumber()); - // 获取执行构建的活动信息 - LogUtil.APP.info("构建项目:{}, 构建活动信息:{}", jobName,build.getActions()); - // 获取构建开始时间戳 - LogUtil.APP.info("构建项目:{}, 构建时间:{}", jobName,DateUtil.format(DateUtil.date(build.getTimestamp()), "yyyy-MM-dd HH:mm:ss")); - // 当前日志 - ConsoleLog currentLog = build.getConsoleOutputText(0); - // 输出当前获取日志信息 - //LogUtil.APP.info(currentLog.getConsoleLog()); - // 检测是否还有更多日志,如果是则继续循环获取 - while (currentLog.getHasMoreData()) { - // 获取最新日志信息 - ConsoleLog newLog = build.getConsoleOutputText(currentLog.getCurrentBufferSize()); - // 输出最新日志 - if(!StrUtil.isBlank(newLog.getConsoleLog())){ - LogUtil.APP.info("构建项目:{}, 构建日志:{}",jobName,newLog.getConsoleLog()); - } - currentLog = newLog; - - } - buildResult = job.getBuildByNumber(build.getNumber()).details().getResult(); - LogUtil.APP.info("构建项目:{}, 构建结果:>>>>>>>>>{}",jobName,buildResult.toString()); - } catch (IOException e) { - LogUtil.APP.error("获取执行任务状态出现异常", e); - } - return buildResult; - } - -} +package luckyclient.tool.jenkins; + +import java.io.IOException; + +import com.offbytwo.jenkins.JenkinsServer; +import com.offbytwo.jenkins.model.BuildResult; +import com.offbytwo.jenkins.model.BuildWithDetails; +import com.offbytwo.jenkins.model.ConsoleLog; +import com.offbytwo.jenkins.model.JobWithDetails; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import luckyclient.utils.LogUtil; + +/** + * * Job Build(任务构建) 相关操作 例如对任务 Build 相关的信息进行获取操作、例如获取构建日志 + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull + * ================================================================= + * + * @author Seagull + * @date 2019年10月30日 + */ +public class JobBuildApi { + + // Jenkins 对象 + private JenkinsServer jenkinsServer; + // http 客户端对象 + //private JenkinsHttpClient jenkinsHttpClient; + + /** + * 构造方法中调用连接 Jenkins 方法 + * + * 2019年10月30日 + */ + JobBuildApi() { + JenkinsConnect jenkinsConnect = new JenkinsConnect(); + // 连接 Jenkins + jenkinsServer = jenkinsConnect.connection(); + // 设置客户端连接 Jenkins + //jenkinsHttpClient = jenkinsConnect.getClient(); + } + + /** + * 通过job名称触发构建并获取构建结果 + * @param jobName 任务名称 + * @return 返回构建结果 + * @author Seagull + * @date 2019年11月29日 + */ + public BuildResult buildAndGetResultForJobName(String jobName) { + BuildResult buildResult = null; + try { + //触发构建 + jenkinsServer.getJob(jobName).build(false); + // 获取 Job 信息 + JobWithDetails job = jenkinsServer.getJob(jobName); + // 这里用最后一次编译来示例 + BuildWithDetails build = job.getLastBuild().details(); + // 获取构建的显示名称 + LogUtil.APP.info("构建项目:{}, 构建名称:{}", jobName,build.getDisplayName()); + // 获取构建的参数信息 + LogUtil.APP.info("构建项目:{}, 构建参数:{}", jobName,build.getParameters()); + // 获取构建编号 + LogUtil.APP.info("构建项目:{}, 构建编号:{}", jobName,build.getNumber()); + // 获取执行构建的活动信息 + LogUtil.APP.info("构建项目:{}, 构建活动信息:{}", jobName,build.getActions()); + // 获取构建开始时间戳 + LogUtil.APP.info("构建项目:{}, 构建时间:{}", jobName,DateUtil.format(DateUtil.date(build.getTimestamp()), "yyyy-MM-dd HH:mm:ss")); + // 当前日志 + ConsoleLog currentLog = build.getConsoleOutputText(0); + // 输出当前获取日志信息 + //LogUtil.APP.info(currentLog.getConsoleLog()); + // 检测是否还有更多日志,如果是则继续循环获取 + while (currentLog.getHasMoreData()) { + // 获取最新日志信息 + ConsoleLog newLog = build.getConsoleOutputText(currentLog.getCurrentBufferSize()); + // 输出最新日志 + if(!StrUtil.isBlank(newLog.getConsoleLog())){ + LogUtil.APP.info("构建项目:{}, 构建日志:{}",jobName,newLog.getConsoleLog()); + } + currentLog = newLog; + + } + buildResult = job.getBuildByNumber(build.getNumber()).details().getResult(); + LogUtil.APP.info("构建项目:{}, 构建结果:>>>>>>>>>{}",jobName,buildResult.toString()); + } catch (IOException e) { + LogUtil.APP.error("获取执行任务状态出现异常", e); + } + return buildResult; + } + +} diff --git a/src/main/java/luckyclient/tool/shell/RestartServerInitialization.java b/src/main/java/luckyclient/tool/shell/RestartServerInitialization.java index 17ddfa8..ca99899 100644 --- a/src/main/java/luckyclient/tool/shell/RestartServerInitialization.java +++ b/src/main/java/luckyclient/tool/shell/RestartServerInitialization.java @@ -1,45 +1,45 @@ -package luckyclient.tool.shell; - -import luckyclient.remote.api.serverOperation; -import luckyclient.utils.LogUtil; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * @date 2017年12月1日 上午9:29:40 - * - */ -public class RestartServerInitialization { - - public static String restartServerRun(String tastid){ - String result = "Status:true"+" 重启命令执行成功!"; - try{ - String[] command = serverOperation.getRestartComm(tastid); - if(command!=null){ - LogUtil.APP.info("准备重启指定的TOMCAT!请稍等。。。参数个数:{}",command.length); - if(command.length==5){ - LogUtil.APP.info("开始调用重启TOMCAT方法。。。参数0:{} 参数1:{} 参数2:{} 参数3:{} 参数4:{}",command[0],command[1],command[2],command[3],command[4]); - result = RmtShellExecutor.sshShell(command[0], command[1], command[2], Integer.valueOf(command[3]), command[4]); - }else{ - LogUtil.APP.warn("重启TOMCAT命令行参数出现异常,请检查配置信息!"); - result = "重启TOMCAT命令行参数出现异常,请检查配置信息!"; - } - }else{ - result = "Status:true"+" 当前任务没有找到需要重启的TOMCAT命令!"; - LogUtil.APP.info("当前任务没有指定需要重启TOMCAT!"); - } - }catch(Throwable e){ - LogUtil.APP.error("重启TOMCAT过程中出现异常",e); - result = "重启TOMCAT过程中出现异常"; - return result; - } - return result; - - } - -} +package luckyclient.tool.shell; + +import luckyclient.remote.api.serverOperation; +import luckyclient.utils.LogUtil; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * @date 2017年12月1日 上午9:29:40 + * + */ +public class RestartServerInitialization { + + public static String restartServerRun(String tastid){ + String result; + try{ + String[] command = serverOperation.getRestartComm(tastid); + if(command!=null){ + LogUtil.APP.info("准备重启指定的TOMCAT!请稍等。。。参数个数:{}",command.length); + if(command.length==5){ + LogUtil.APP.info("开始调用重启TOMCAT方法。。。参数0:{} 参数1:{} 参数2:{} 参数3:{} 参数4:{}",command[0],command[1],command[2],command[3],command[4]); + result = RmtShellExecutor.sshShell(command[0], command[1], command[2], Integer.parseInt(command[3]), command[4]); + }else{ + LogUtil.APP.warn("重启TOMCAT命令行参数出现异常,请检查配置信息!"); + result = "重启TOMCAT命令行参数出现异常,请检查配置信息!"; + } + }else{ + result = "Status:true"+" 当前任务没有找到需要重启的TOMCAT命令!"; + LogUtil.APP.info("当前任务没有指定需要重启TOMCAT!"); + } + }catch(Throwable e){ + LogUtil.APP.error("重启TOMCAT过程中出现异常",e); + result = "重启TOMCAT过程中出现异常"; + return result; + } + return result; + + } + +} diff --git a/src/main/java/luckyclient/tool/shell/RmtShellExecutor.java b/src/main/java/luckyclient/tool/shell/RmtShellExecutor.java index 2433c9f..58d9b80 100644 --- a/src/main/java/luckyclient/tool/shell/RmtShellExecutor.java +++ b/src/main/java/luckyclient/tool/shell/RmtShellExecutor.java @@ -1,4 +1,5 @@ package luckyclient.tool.shell; + import java.io.InputStream; import java.io.OutputStream; @@ -10,110 +11,95 @@ import luckyclient.utils.LogUtil; /** * 远程执行shell脚本类 + * * @author l */ public class RmtShellExecutor { - /** - * 利用JSch包实现远程主机SHELL命令执行 - * @param ip 主机IP - * @param user 主机登陆用户名 - * @param psw 主机登陆密码 - * @param port 主机ssh2登陆端口,如果取默认值,传-1 - * @param command Shell命令 cd /home/pospsettle/tomcat-7.0-7080/bin&&./restart.sh - */ - public static String sshShell(String ip, String user, String psw - ,int port,String command) throws Exception{ - - Session session = null; - Channel channel = null; - String privateKey = ""; - String passphrase = ""; - String result = "Status:true"+" 重启命令执行成功!"; - try { - JSch jsch = new JSch(); - LogUtil.APP.info("进入到重启TOMCAT方法..."); - //设置密钥和密码 - if (privateKey != null && !"".equals(privateKey)) { - if (passphrase != null && "".equals(passphrase)) { - //设置带口令的密钥 - jsch.addIdentity(privateKey, passphrase); - } else { - //设置不带口令的密钥 - jsch.addIdentity(privateKey); - } - } - - if(port <=0){ - //连接服务器,采用默认端口 - LogUtil.APP.info("设置重启TOMCAT服务器IP及默认端口..."); - session = jsch.getSession(user, ip); - }else{ - //采用指定的端口连接服务器 - LogUtil.APP.info("设置重启TOMCAT服务器IP及端口..."); - session = jsch.getSession(user, ip ,port); - LogUtil.APP.info("设置重启TOMCAT服务器IP及端口完成!"); - } - - //如果服务器连接不上,则抛出异常 - if (session == null) { - LogUtil.APP.warn("重启TOMCAT过程中,链接服务器session is null"); - result = "重启TOMCAT过程中,链接服务器session is null"; - throw new Exception("session is null"); - } - //设置登陆主机的密码 - session.setPassword(psw); - //设置第一次登陆的时候提示,可选值:(ask | yes | no) - session.setConfig("StrictHostKeyChecking", "no"); - //设置登陆超时时间 - session.connect(30000); - - //创建sftp通信通道 - channel = (Channel) session.openChannel("shell"); - channel.connect(1000); - - //获取输入流和输出流 - InputStream instream = channel.getInputStream(); - OutputStream outstream = channel.getOutputStream(); - - //发送需要执行的SHELL命令,需要用\n结尾,表示回车 - LogUtil.APP.info("准备往重启TOMCAT服务器发送命令!"); - String shellCommand = command+" \n"; - outstream.write(shellCommand.getBytes()); - outstream.flush(); + /** + * 利用JSch包实现远程主机SHELL命令执行 + * + * @param ip 主机IP + * @param user 主机登陆用户名 + * @param psw 主机登陆密码 + * @param port 主机ssh2登陆端口,如果取默认值,传-1 + * @param command Shell命令 cd /home/pospsettle/tomcat-7.0-7080/bin&&./restart.sh + */ + public static String sshShell(String ip, String user, String psw + , int port, String command) { - Thread.sleep(10000); - //获取命令执行的结果 - if (instream.available() > 0) { - byte[] data = new byte[instream.available()]; - int nLen = instream.read(data); - if (nLen < 0) { - LogUtil.APP.warn("重启TOMCAT过程中,获取命令执行结果出现异常!"); - result = "重启TOMCAT过程中,获取命令执行结果出现异常!"; - throw new Exception("network error."); - } - - //转换输出结果并打印出来 - String temp = new String(data, 0, nLen,"iso8859-1"); - LogUtil.APP.info("开始打印重启TOMCAT命令执行结果...",temp); - } - outstream.close(); - instream.close(); - } catch (Exception e) { - result = "重启TOMCAT过程中,出现异常!"; - LogUtil.APP.error("重启TOMCAT过程中,出现异常!", e); - return result; - } finally { - if(null!=session){ - session.disconnect(); - } - if(null!=channel){ - channel.disconnect(); - } + Session session = null; + Channel channel = null; + String result = "Status:true" + " 重启命令执行成功!"; + try { + JSch jsch = new JSch(); + LogUtil.APP.info("进入到重启TOMCAT方法..."); - } - return result; - } + if (port <= 0) { + //连接服务器,采用默认端口 + LogUtil.APP.info("设置重启TOMCAT服务器IP及默认端口..."); + session = jsch.getSession(user, ip); + } else { + //采用指定的端口连接服务器 + LogUtil.APP.info("设置重启TOMCAT服务器IP及端口..."); + session = jsch.getSession(user, ip, port); + LogUtil.APP.info("设置重启TOMCAT服务器IP及端口完成!"); + } - public static void main(String args[]) throws Exception { + //如果服务器连接不上,则抛出异常 + if (session == null) { + LogUtil.APP.warn("重启TOMCAT过程中,链接服务器session is null"); + throw new Exception("session is null"); + } + //设置登陆主机的密码 + session.setPassword(psw); + //设置第一次登陆的时候提示,可选值:(ask | yes | no) + session.setConfig("StrictHostKeyChecking", "no"); + //设置登陆超时时间 + session.connect(30000); + + //创建sftp通信通道 + channel = session.openChannel("shell"); + channel.connect(1000); + + //获取输入流和输出流 + InputStream instream = channel.getInputStream(); + OutputStream outstream = channel.getOutputStream(); + + //发送需要执行的SHELL命令,需要用\n结尾,表示回车 + LogUtil.APP.info("准备往重启TOMCAT服务器发送命令!"); + String shellCommand = command + " \n"; + outstream.write(shellCommand.getBytes()); + outstream.flush(); + + Thread.sleep(10000); + //获取命令执行的结果 + if (instream.available() > 0) { + byte[] data = new byte[instream.available()]; + int nLen = instream.read(data); + if (nLen < 0) { + LogUtil.APP.warn("重启TOMCAT过程中,获取命令执行结果出现异常!"); + } + + //转换输出结果并打印出来 + String temp = new String(data, 0, nLen, "iso8859-1"); + LogUtil.APP.info("开始打印重启TOMCAT命令执行结果...{}", temp); + } + outstream.close(); + instream.close(); + } catch (Exception e) { + result = "重启TOMCAT过程中,出现异常!"; + LogUtil.APP.error("重启TOMCAT过程中,出现异常!", e); + return result; + } finally { + if (null != session) { + session.disconnect(); + } + if (null != channel) { + channel.disconnect(); + } + + } + return result; } + } \ No newline at end of file diff --git a/src/main/java/luckyclient/utils/DateUtils.java b/src/main/java/luckyclient/utils/DateUtils.java index 107c50c..8866a69 100644 --- a/src/main/java/luckyclient/utils/DateUtils.java +++ b/src/main/java/luckyclient/utils/DateUtils.java @@ -1,163 +1,160 @@ -package luckyclient.utils; - -import java.lang.management.ManagementFactory; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import org.apache.commons.lang3.time.DateFormatUtils; - -/** - * 时间工具类 - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull - * ================================================================= - * @author Seagull - * @date 2019年5月5日 - */ -public class DateUtils extends org.apache.commons.lang3.time.DateUtils -{ - public static String YYYY = "yyyy"; - - public static String YYYY_MM = "yyyy-MM"; - - public static String YYYY_MM_DD = "yyyy-MM-dd"; - - public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; - - public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; - - private static String[] parsePatterns = { - "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", - "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", - "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; - - /** - * 获取当前Date型日期 - * - * @return Date() 当前日期 - */ - public static Date getNowDate() - { - return new Date(); - } - - /** - * 获取当前日期, 默认格式为yyyy-MM-dd - * - * @return String - */ - public static String getDate() - { - return dateTimeNow(YYYY_MM_DD); - } - - public static final String getTime() - { - return dateTimeNow(YYYY_MM_DD_HH_MM_SS); - } - - public static final String dateTimeNow() - { - return dateTimeNow(YYYYMMDDHHMMSS); - } - - public static final String dateTimeNow(final String format) - { - return parseDateToStr(format, new Date()); - } - - public static final String dateTime(final Date date) - { - return parseDateToStr(YYYY_MM_DD, date); - } - - public static final String parseDateToStr(final String format, final Date date) - { - return new SimpleDateFormat(format).format(date); - } - - public static final Date dateTime(final String format, final String ts) - { - try - { - return new SimpleDateFormat(format).parse(ts); - } - catch (ParseException e) - { - throw new RuntimeException(e); - } - } - - /** - * 日期路径 即年/月/日 如2018/08/08 - */ - public static final String datePath() - { - Date now = new Date(); - return DateFormatUtils.format(now, "yyyy/MM/dd"); - } - - /** - * 日期路径 即年/月/日 如20180808 - */ - public static final String dateTime() - { - Date now = new Date(); - return DateFormatUtils.format(now, "yyyyMMdd"); - } - - /** - * 日期型字符串转化为日期 格式 - */ - public static Date parseDate(Object str) - { - if (str == null) - { - return null; - } - try - { - return parseDate(str.toString(), parsePatterns); - } - catch (ParseException e) - { - return null; - } - } - - /** - * 获取服务器启动时间 - */ - public static Date getServerStartDate() - { - long time = ManagementFactory.getRuntimeMXBean().getStartTime(); - return new Date(time); - } - - /** - * 计算两个时间差 - */ - public static String getDatePoor(Date endDate, Date nowDate) - { - if(null==nowDate){ - return 0 + "天" + 0 + "小时" + 0 + "分钟"; - } - - long nd = 1000 * 24 * 60 * 60; - long nh = 1000 * 60 * 60; - long nm = 1000 * 60; - // long ns = 1000; - // 获得两个时间的毫秒时间差异 - long diff = endDate.getTime() - nowDate.getTime(); - // 计算差多少天 - long day = diff / nd; - // 计算差多少小时 - long hour = diff % nd / nh; - // 计算差多少分钟 - long min = diff % nd % nh / nm; - // 计算差多少秒//输出结果 - // long sec = diff % nd % nh % nm / ns; - return day + "天" + hour + "小时" + min + "分钟"; - } -} +package luckyclient.utils; + +import java.lang.management.ManagementFactory; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import org.apache.commons.lang3.time.DateFormatUtils; + +/** + * 时间工具类 + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull + * ================================================================= + * @author Seagull + * @date 2019年5月5日 + */ +public class DateUtils extends org.apache.commons.lang3.time.DateUtils +{ + + public static String YYYY_MM_DD = "yyyy-MM-dd"; + + public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; + + public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + + private static String[] parsePatterns = { + "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", + "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", + "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; + + /** + * 获取当前Date型日期 + * + * @return Date() 当前日期 + */ + public static Date getNowDate() + { + return new Date(); + } + + /** + * 获取当前日期, 默认格式为yyyy-MM-dd + * + * @return String + */ + public static String getDate() + { + return dateTimeNow(YYYY_MM_DD); + } + + public static String getTime() + { + return dateTimeNow(YYYY_MM_DD_HH_MM_SS); + } + + public static String dateTimeNow() + { + return dateTimeNow(YYYYMMDDHHMMSS); + } + + public static String dateTimeNow(final String format) + { + return parseDateToStr(format, new Date()); + } + + public static String dateTime(final Date date) + { + return parseDateToStr(YYYY_MM_DD, date); + } + + public static String parseDateToStr(final String format, final Date date) + { + return new SimpleDateFormat(format).format(date); + } + + public static Date dateTime(final String format, final String ts) + { + try + { + return new SimpleDateFormat(format).parse(ts); + } + catch (ParseException e) + { + throw new RuntimeException(e); + } + } + + /** + * 日期路径 即年/月/日 如2018/08/08 + */ + public static String datePath() + { + Date now = new Date(); + return DateFormatUtils.format(now, "yyyy/MM/dd"); + } + + /** + * 日期路径 即年/月/日 如20180808 + */ + public static String dateTime() + { + Date now = new Date(); + return DateFormatUtils.format(now, "yyyyMMdd"); + } + + /** + * 日期型字符串转化为日期 格式 + */ + public static Date parseDate(Object str) + { + if (str == null) + { + return null; + } + try + { + return parseDate(str.toString(), parsePatterns); + } + catch (ParseException e) + { + return null; + } + } + + /** + * 获取服务器启动时间 + */ + public static Date getServerStartDate() + { + long time = ManagementFactory.getRuntimeMXBean().getStartTime(); + return new Date(time); + } + + /** + * 计算两个时间差 + */ + public static String getDatePoor(Date endDate, Date nowDate) + { + if(null==nowDate){ + return 0 + "天" + 0 + "小时" + 0 + "分钟"; + } + + long nd = 1000 * 24 * 60 * 60; + long nh = 1000 * 60 * 60; + long nm = 1000 * 60; + // long ns = 1000; + // 获得两个时间的毫秒时间差异 + long diff = endDate.getTime() - nowDate.getTime(); + // 计算差多少天 + long day = diff / nd; + // 计算差多少小时 + long hour = diff % nd / nh; + // 计算差多少分钟 + long min = diff % nd % nh / nm; + // 计算差多少秒//输出结果 + // long sec = diff % nd % nh % nm / ns; + return day + "天" + hour + "小时" + min + "分钟"; + } +} diff --git a/src/main/java/luckyclient/utils/DbOperation.java b/src/main/java/luckyclient/utils/DbOperation.java index 381e339..02cbb42 100644 --- a/src/main/java/luckyclient/utils/DbOperation.java +++ b/src/main/java/luckyclient/utils/DbOperation.java @@ -4,148 +4,140 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; + /** * ================================================================= * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 * ================================================================= - * @ClassName: DBOperation + * + * @ClassName: DBOperation * @Description: 封装自动化过程中,对数据库的部分操作 * @author: seagull - * @date 2014年8月24日 上午9:29:40 - * + * @date 2014年8月24日 上午9:29:40 */ public class DbOperation { - - DbToolkit dbt =null; - /** - * 创建链接池,注意此方法不能new多次,会导致多次创建链接池,最好放在任务启动方法中 - */ - public DbOperation(String urlBase,String usernameBase,String passwordBase) { - dbt = new DbToolkit(urlBase,usernameBase,passwordBase); - } - - - /** - * 执行SQL - * @param sql - * @throws Exception - */ - public String executeSql(String sql) throws Exception{ - Connection conn = null; - String result; - try{ - conn = dbt.getBaseConnection(); - int resultnum = DbToolkit.executeSQL(conn, sql); - if(resultnum>0){ - result= "成功执行SQL,更新数据"+resultnum+"行!"; - }else{ - result= "成功执行SQL,没有更新到数据!"; - } - return result; - }catch(Exception e){ - return e.toString(); - }finally{ - DbToolkit.closeConnection(conn); - } - } - - /** - * 执行SQL流水查询 - * @param sql - * @throws SQLException - */ - public String executeQuery(String sql) throws Exception{ - Connection conn = null; - ResultSet rs=null; - try{ - conn = dbt.getBaseConnection(); - StringBuffer sb = new StringBuffer(); - rs = DbToolkit.executeQuery(conn, sql); - ResultSetMetaData metaData = rs.getMetaData(); - int colum = metaData.getColumnCount(); - int count=0; - //行数 - while(rs.next()){ - count++; - if (count > 1){ - sb.append("#"); - } - //列数 - for (int i = 1; i <= colum; i++){ - if(rs.getObject(metaData.getColumnName(i))== null){ - sb.append("null").append("%"); - continue; - } - sb.append(rs.getObject(metaData.getColumnName(i)).toString()).append("%"); - } + + DbToolkit dbt; + + /** + * 创建链接池,注意此方法不能new多次,会导致多次创建链接池,最好放在任务启动方法中 + */ + public DbOperation(String urlBase, String usernameBase, String passwordBase) { + dbt = new DbToolkit(urlBase, usernameBase, passwordBase); + } + + + /** + * 执行SQL + * + * @param sql 执行SQL语句 + */ + public String executeSql(String sql) { + Connection conn = null; + String result; + try { + conn = dbt.getBaseConnection(); + int resultnum = DbToolkit.executeSQL(conn, sql); + if (resultnum > 0) { + result = "成功执行SQL,更新数据" + resultnum + "行!"; + } else { + result = "成功执行SQL,没有更新到数据!"; + } + return result; + } catch (Exception e) { + return e.toString(); + } finally { + DbToolkit.closeConnection(conn); + } + } + + /** + * 执行SQL流水查询 + * + * @param sql 查询SQL语句 + */ + public String executeQuery(String sql) throws Exception { + Connection conn = null; + ResultSet rs = null; + try { + conn = dbt.getBaseConnection(); + StringBuilder sb = new StringBuilder(); + rs = DbToolkit.executeQuery(conn, sql); + ResultSetMetaData metaData = rs.getMetaData(); + int colum = metaData.getColumnCount(); + int count = 0; + //行数 + while (rs.next()) { + count++; + if (count > 1) { + sb.append("#"); + } + //列数 + for (int i = 1; i <= colum; i++) { + if (rs.getObject(metaData.getColumnName(i)) == null) { + sb.append("null").append("%"); + continue; + } + sb.append(rs.getObject(metaData.getColumnName(i)).toString()).append("%"); + } /* if(DbOperation.sumString(sb.toString(), "%")>500){ sb.delete(0,sb.length()); sb.append("查询出来的数据太多啦(超过100项)!我显示不过来哦。。。。"); break; }*/ - } - return sb.toString(); - }catch(Exception e){ - throw e; - }finally{ - if(rs!=null){ - rs.close(); - } - DbToolkit.closeConnection(conn); - } - } - - + } + return sb.toString(); + } finally { + if (rs != null) { + rs.close(); + } + DbToolkit.closeConnection(conn); + } + } + + /** - * - * @Title: subString + * 截取字符串 + * + * @return String * @Description: 截取字符串 - * @return String - * @throws */ - public String subString(String str,String begin,String end){ - try{ - return str.substring(str.indexOf(begin)+begin.length(), str.lastIndexOf(end)); - } - catch (Exception e) { + public String subString(String str, String begin, String end) { + try { + return str.substring(str.indexOf(begin) + begin.length(), str.lastIndexOf(end)); + } catch (Exception e) { return null; } - } - - - /** - * - * @Title: sumString - * @Description: 统计字符在字符串中出现的次数 - * @return int - * @throws - */ - public static int sumString(String str,String a){ - char chs[]=a.toCharArray(); - int num = 0; - char[] chars = str.toCharArray(); - for(int i = 0; i < chars.length; i++){ - if(chs[0] == chars[i]) - { - num++; - } - } - return num; - } + } - /** - * @throws InterruptedException - * - * @Title: Wait - * @Description: 等待时间 + + /** + * 统计字符在字符串中出现的次数 + * * @return int - * @throws */ - public static void stepWait(String s) throws InterruptedException{ - int second = Integer.parseInt(s); - Thread.sleep(second*1000); - } - + public static int sumString(String str, String a) { + char[] chs = a.toCharArray(); + int num = 0; + char[] chars = str.toCharArray(); + for (char aChar : chars) { + if (chs[0] == aChar) { + num++; + } + } + return num; + } + + /** + * Wait等待时间 + * + * @return int + */ + public static void stepWait(String s) throws InterruptedException { + int second = Integer.parseInt(s); + Thread.sleep(second * 1000); + } + } diff --git a/src/main/java/luckyclient/utils/DbToolkit.java b/src/main/java/luckyclient/utils/DbToolkit.java index 9b5898e..3be45a1 100644 --- a/src/main/java/luckyclient/utils/DbToolkit.java +++ b/src/main/java/luckyclient/utils/DbToolkit.java @@ -26,7 +26,7 @@ public class DbToolkit { /** * 建立数据库链接池 */ - public ComboPooledDataSource cpds=null; + public ComboPooledDataSource cpds; private static final String DRIVERCLASS = DrivenConfig.getConfiguration().getProperty("db.ComboPooledDataSource.DriverClass"); public DbToolkit(String urlBase,String usernameBase,String passwordBase){ @@ -57,8 +57,7 @@ public class DbToolkit { public Connection getBaseConnection() throws SQLException{ // TODO Auto-generated method stub - Connection conn = cpds.getConnection(); - return conn; + return cpds.getConnection(); } /** @@ -66,25 +65,22 @@ public class DbToolkit { * * @param conn 数据库连接 * @param staticSql 静态SQL语句字符串 - * @return 返回查询结果集ResultSet对象 - * @throws SQLException + * @return 返回查询结果集ResultSet对象 */ public static ResultSet executeQuery(Connection conn, String staticSql) throws SQLException { //创建执行SQL的对象 Statement stmt = conn.createStatement(); //执行SQL,并获取返回结果 - ResultSet rs = stmt.executeQuery(staticSql); - // stmt.close(); - return rs; + // stmt.close(); + return stmt.executeQuery(staticSql); } /** * 在一个数据库连接上执行一个静态SQL语句 * * @param conn 数据库连接 - * @param staticSql 静态SQL语句字符串 - * @throws SQLException + * @param staticSql 静态SQL语句字符串 */ public static int executeSQL(Connection conn, String staticSql) throws SQLException { //创建执行SQL的对象 diff --git a/src/main/java/luckyclient/utils/JarClassFind.java b/src/main/java/luckyclient/utils/JarClassFind.java index 6f11868..d4532e8 100644 --- a/src/main/java/luckyclient/utils/JarClassFind.java +++ b/src/main/java/luckyclient/utils/JarClassFind.java @@ -1,79 +1,80 @@ -package luckyclient.utils; - -import java.io.File; -import java.util.Enumeration; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -/** - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 - * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 - * ================================================================= - * - * @author: seagull - * @date 2017年12月1日 上午9:29:40 - * - */ -public class JarClassFind { - - private static void findClassInLocalSystem(String path,String classname) { - int count = 0; - //String path = "D:\\web_task\\TestFrame\\lib\\"; //指定查找路径 - classname = classname.replace('.', '/') + ".class"; - - //JavaBaseTest.LogUtil.APP.info("即将去服务器路径【" + path + "】下查找类【" + classname + "】 !"); - System.out.println("即将去服务器路径【" + path + "】下查找类【" + classname + "】 !"); - if (path.charAt(path.length() - 1) != '\\') { - path += '\\'; - } - File file = new File(path); - if (!file.exists()) { - //JavaBaseTest.LogUtil.ERROR.error("找不到本地指定包查找路径!"); - System.out.println("找不到本地指定包查找路径!"); - return; - } - - String[] filelist = file.list(); - for (int i = 0; i < filelist.length; i++) { - File temp = new File(path + filelist[i]); - if ((temp.isDirectory() && !temp.isHidden() && temp.exists())&&filelist[i].equals(classname)) { - count++; - System.out.println("【"+path + filelist[i]+"】查找到第"+count+"个JAR包存在指定类!"); - } else { - if (filelist[i].endsWith("jar")) { - try { - JarFile jarfile = new java.util.jar.JarFile(path + filelist[i]); - for (Enumeration e = jarfile.entries(); e.hasMoreElements();) { - String name = e.nextElement().toString(); - if (name.equals(classname) || name.indexOf(classname) > -1) { - count++; - //JavaBaseTest.LogUtil.APP.info("【"+path + filelist[i]+"】查找到第"+count+"个JAR包存在指定类!"); - System.out.println("【"+path + filelist[i]+"】查找到第"+count+"个JAR包存在指定类!"); - } - } - jarfile.close(); - } catch (Exception e) { - - } - } - } - } - - if(count==0){ - //JavaBaseTest.LogUtil.APP.info("没有在当前路径下找到指定类"); - System.out.println("没有在当前路径下找到指定类"); - }else if(count==1){ - //JavaBaseTest.LogUtil.APP.info("在当前路径下只找到一个存在的指定类,不存在类冲突情况!"); - System.out.println("在当前路径下只找到一个存在的指定类,不存在类冲突情况!"); - } - } - - static public void main(String[] args) { - String path = args[0]; - String classname = args[1]; - findClassInLocalSystem(path,classname); - } - -} +package luckyclient.utils; + +import java.io.File; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +/** + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 + * 有任何疑问欢迎联系作者讨论。 QQ:1573584944 seagull1985 + * ================================================================= + * + * @author: seagull + * @date 2017年12月1日 上午9:29:40 + * + */ +public class JarClassFind { + + private static void findClassInLocalSystem(String path,String classname) { + int count = 0; + //String path = "D:\\web_task\\TestFrame\\lib\\"; //指定查找路径 + classname = classname.replace('.', '/') + ".class"; + + //JavaBaseTest.LogUtil.APP.info("即将去服务器路径【" + path + "】下查找类【" + classname + "】 !"); + System.out.println("即将去服务器路径【" + path + "】下查找类【" + classname + "】 !"); + if (path.charAt(path.length() - 1) != '\\') { + path += '\\'; + } + File file = new File(path); + if (!file.exists()) { + //JavaBaseTest.LogUtil.ERROR.error("找不到本地指定包查找路径!"); + System.out.println("找不到本地指定包查找路径!"); + return; + } + + String[] filelist = file.list(); + assert filelist != null; + for (String s : filelist) { + File temp = new File(path + s); + if ((temp.isDirectory() && !temp.isHidden() && temp.exists()) && s.equals(classname)) { + count++; + System.out.println("【" + path + s + "】查找到第" + count + "个JAR包存在指定类!"); + } else { + if (s.endsWith("jar")) { + try { + JarFile jarfile = new JarFile(path + s); + for (Enumeration e = jarfile.entries(); e.hasMoreElements(); ) { + String name = e.nextElement().toString(); + if (name.equals(classname) || name.contains(classname)) { + count++; + //JavaBaseTest.LogUtil.APP.info("【"+path + filelist[i]+"】查找到第"+count+"个JAR包存在指定类!"); + System.out.println("【" + path + s + "】查找到第" + count + "个JAR包存在指定类!"); + } + } + jarfile.close(); + } catch (Exception ignored) { + + } + } + } + } + + if(count==0){ + //JavaBaseTest.LogUtil.APP.info("没有在当前路径下找到指定类"); + System.out.println("没有在当前路径下找到指定类"); + }else if(count==1){ + //JavaBaseTest.LogUtil.APP.info("在当前路径下只找到一个存在的指定类,不存在类冲突情况!"); + System.out.println("在当前路径下只找到一个存在的指定类,不存在类冲突情况!"); + } + } + + static public void main(String[] args) { + String path = args[0]; + String classname = args[1]; + findClassInLocalSystem(path,classname); + } + +} diff --git a/src/main/java/luckyclient/utils/LogUtil.java b/src/main/java/luckyclient/utils/LogUtil.java index 9b9d802..9c3befa 100644 --- a/src/main/java/luckyclient/utils/LogUtil.java +++ b/src/main/java/luckyclient/utils/LogUtil.java @@ -1,57 +1,54 @@ -package luckyclient.utils; - -import java.lang.reflect.Field; -import java.util.List; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * 系统日志记录 - * @author Seagull - * - */ -public class LogUtil { - - /** - * 主要使用三种日志级别,info,warn,error - * info 记录客户端系统日志,监控客户端运行情况 - * warn 记录客户端业务上的告警日志 - * error 记录客户端在执行过程中抛出的异常以及严重错误 - */ - public static final Logger APP = LoggerFactory.getLogger("info"); - - public static StringBuffer getFieldValue(Object bean){ - StringBuffer sb = new StringBuffer(); - - try{ - if(bean==null){ - return null; - } - Field[] fieldArray = bean.getClass().getDeclaredFields(); - if(fieldArray != null){ - int indexId = 0; - Object obj = null; - for(Field field:fieldArray){ - field.setAccessible(true); - obj = field.get(bean); - if(!(obj instanceof List) && !"serialVersionUID".equals(field.getName())){ - if(indexId>0){ - sb.append(","); - } - if(obj != null){ - sb.append(field.getName()).append("=").append( obj.toString()); - }else{ - sb.append(field.getName()).append("="); - } - indexId += 1; - } - } - } - } - catch(Exception ex){ - LogUtil.APP.error("日志异常",ex); - } - return sb; - } -} +package luckyclient.utils; + +import java.lang.reflect.Field; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 系统日志记录 + * + * @author Seagull + */ +public class LogUtil { + + /** + * 主要使用三种日志级别,info,warn,error + * info 记录客户端系统日志,监控客户端运行情况 + * warn 记录客户端业务上的告警日志 + * error 记录客户端在执行过程中抛出的异常以及严重错误 + */ + public static final Logger APP = LoggerFactory.getLogger("info"); + + public static StringBuffer getFieldValue(Object bean) { + StringBuffer sb = new StringBuffer(); + + try { + if (bean == null) { + return null; + } + Field[] fieldArray = bean.getClass().getDeclaredFields(); + int indexId = 0; + Object obj; + for (Field field : fieldArray) { + field.setAccessible(true); + obj = field.get(bean); + if (!(obj instanceof List) && !"serialVersionUID".equals(field.getName())) { + if (indexId > 0) { + sb.append(","); + } + if (obj != null) { + sb.append(field.getName()).append("=").append(obj.toString()); + } else { + sb.append(field.getName()).append("="); + } + indexId += 1; + } + } + } catch (Exception ex) { + LogUtil.APP.error("日志异常", ex); + } + return sb; + } +} diff --git a/src/main/java/luckyclient/utils/config/AppiumConfig.java b/src/main/java/luckyclient/utils/config/AppiumConfig.java index a5b3bf7..aa62a85 100644 --- a/src/main/java/luckyclient/utils/config/AppiumConfig.java +++ b/src/main/java/luckyclient/utils/config/AppiumConfig.java @@ -1,31 +1,32 @@ -package luckyclient.utils.config; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.Properties; - -import luckyclient.utils.LogUtil; - -/** - * 初始化Appium配置参数 - * @author seagull - * - */ -public class AppiumConfig { - private static final Properties SYS_CONFIG = new Properties(); - private static final String SYS_CONFIG_FILE = "/appium_config.properties"; - static{ - try { - InputStream in = new BufferedInputStream(AppiumConfig.class.getResourceAsStream(SYS_CONFIG_FILE)); - SYS_CONFIG.load(new InputStreamReader(in, "UTF-8")); - } catch (IOException e) { - LogUtil.APP.error("读取移动端appium_config.properties配置文件出现异常,请检查!", e); - } - } - private AppiumConfig(){} - public static Properties getConfiguration(){ - return SYS_CONFIG; - } -} +package luckyclient.utils.config; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Properties; + +import luckyclient.utils.LogUtil; + +/** + * 初始化Appium配置参数 + * @author seagull + * + */ +public class AppiumConfig { + private static final Properties SYS_CONFIG = new Properties(); + private static final String SYS_CONFIG_FILE = "/appium_config.properties"; + static{ + try { + InputStream in = new BufferedInputStream(AppiumConfig.class.getResourceAsStream(SYS_CONFIG_FILE)); + SYS_CONFIG.load(new InputStreamReader(in, StandardCharsets.UTF_8)); + } catch (IOException e) { + LogUtil.APP.error("读取移动端appium_config.properties配置文件出现异常,请检查!", e); + } + } + private AppiumConfig(){} + public static Properties getConfiguration(){ + return SYS_CONFIG; + } +} diff --git a/src/main/java/luckyclient/utils/config/DrivenConfig.java b/src/main/java/luckyclient/utils/config/DrivenConfig.java index fd93499..9882553 100644 --- a/src/main/java/luckyclient/utils/config/DrivenConfig.java +++ b/src/main/java/luckyclient/utils/config/DrivenConfig.java @@ -1,35 +1,36 @@ -package luckyclient.utils.config; - -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.Properties; - -import luckyclient.utils.LogUtil; - -/** - * 初始化数据库驱动配置 - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull - * ================================================================= - * @author Seagull - * @date 2020年2月17日 - */ -public class DrivenConfig { - private static final Properties SYS_CONFIG = new Properties(); - private static final String SYS_CONFIG_FILE = "/TestDriven/driven_config.properties"; - static{ - try { - InputStream in = new BufferedInputStream(DrivenConfig.class.getResourceAsStream(SYS_CONFIG_FILE)); - SYS_CONFIG.load(new InputStreamReader(in, "UTF-8")); - } catch (IOException e) { - LogUtil.APP.error("读取测试驱动driven_config.properties配置文件出现异常,请检查!", e); - } - } - private DrivenConfig(){} - public static Properties getConfiguration(){ - return SYS_CONFIG; - } -} +package luckyclient.utils.config; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.Properties; + +import luckyclient.utils.LogUtil; + +/** + * 初始化数据库驱动配置 + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull + * ================================================================= + * @author Seagull + * @date 2020年2月17日 + */ +public class DrivenConfig { + private static final Properties SYS_CONFIG = new Properties(); + private static final String SYS_CONFIG_FILE = "/TestDriven/driven_config.properties"; + static{ + try { + InputStream in = new BufferedInputStream(DrivenConfig.class.getResourceAsStream(SYS_CONFIG_FILE)); + SYS_CONFIG.load(new InputStreamReader(in, StandardCharsets.UTF_8)); + } catch (IOException e) { + LogUtil.APP.error("读取测试驱动driven_config.properties配置文件出现异常,请检查!", e); + } + } + private DrivenConfig(){} + public static Properties getConfiguration(){ + return SYS_CONFIG; + } +} diff --git a/src/main/java/luckyclient/utils/httputils/HttpRequest.java b/src/main/java/luckyclient/utils/httputils/HttpRequest.java index 6ea78d3..1312ee6 100644 --- a/src/main/java/luckyclient/utils/httputils/HttpRequest.java +++ b/src/main/java/luckyclient/utils/httputils/HttpRequest.java @@ -1,16 +1,7 @@ package luckyclient.utils.httputils; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.net.URL; -import java.net.URLConnection; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.util.Properties; - +import luckyclient.utils.LogUtil; +import luckyclient.utils.config.SysConfig; import org.apache.http.HttpResponse; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; @@ -20,8 +11,11 @@ import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; -import luckyclient.utils.LogUtil; -import luckyclient.utils.config.SysConfig; +import java.io.*; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.StandardCharsets; +import java.util.Properties; /** * ================================================================= @@ -41,12 +35,12 @@ public class HttpRequest { /** * 字符串参数 - * @param repath - * @return + * @param repath 请求路径 + * @return 返回请求结果 */ public static String loadJSON(String repath) { String charset="GBK"; - StringBuffer resultBuffer = null; + StringBuffer resultBuffer; CloseableHttpClient httpclient = HttpClients.createDefault(); BufferedReader br = null; // 构建请求参数 @@ -69,8 +63,6 @@ public class HttpRequest { br.close(); } catch (IOException e) { LogUtil.APP.error("loadJSON发送请求后关闭br流出现异常,请检查!", e); - br = null; - throw new RuntimeException(e); } } } @@ -86,7 +78,7 @@ public class HttpRequest { public static String sendPost(String repath, String param) { PrintWriter out = null; BufferedReader in = null; - String result = ""; + StringBuilder result = new StringBuilder(); try { URL realUrl = new URL(WEB_URL+repath); // 打开和URL之间的连接 @@ -109,7 +101,7 @@ public class HttpRequest { in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "GBK")); String line; while ((line = in.readLine()) != null) { - result += line; + result.append(line); } } catch (Exception e) { LogUtil.APP.error("向指定URL发送POST方法的请求出现异常,请检查!", e); @@ -128,17 +120,17 @@ public class HttpRequest { LogUtil.APP.error("向指定URL发送POST方法的请求后关闭流出现异常,请检查!", ex); } } - return result; + return result.toString(); } /** * 使用HttpClient以JSON格式发送post请求 - * @param urlParam - * @param params - * @return + * @param urlParam 请求路径 + * @param params 请求参数 + * @return 返回请求结果 */ public static String httpClientPostJson(String urlParam, String params){ - StringBuffer resultBuffer = null; + StringBuffer resultBuffer; CloseableHttpClient httpclient=HttpClients.createDefault(); HttpPost httpPost = new HttpPost(WEB_URL+urlParam); httpPost.setHeader("Content-Type", "application/json"); @@ -159,7 +151,7 @@ public class HttpRequest { // 读取服务器响应数据 resultBuffer = new StringBuffer(); if(null!=response.getEntity()){ - br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "utf-8")); + br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); String temp; while ((temp = br.readLine()) != null) { resultBuffer.append(temp); @@ -173,9 +165,7 @@ public class HttpRequest { try { br.close(); } catch (IOException e) { - br = null; LogUtil.APP.error("使用HttpClient以JSON格式发送post请求后关闭br流出现异常,请检查!", e); - throw new RuntimeException(e); } } } diff --git a/src/main/java/luckyclient/utils/httputils/MyX509TrustManager.java b/src/main/java/luckyclient/utils/httputils/MyX509TrustManager.java index 6261bdd..8cfd5c0 100644 --- a/src/main/java/luckyclient/utils/httputils/MyX509TrustManager.java +++ b/src/main/java/luckyclient/utils/httputils/MyX509TrustManager.java @@ -1,36 +1,34 @@ -package luckyclient.utils.httputils; - -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; - -import javax.net.ssl.X509TrustManager; - -/** - * - * ================================================================= - * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 - * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull - * ================================================================= - * @author Seagull - * @date 2019年8月8日 - */ -public class MyX509TrustManager implements X509TrustManager -{ - @Override - public void checkClientTrusted(X509Certificate ax509certificate[], String s) throws CertificateException - { - //TODO nothing - } - - @Override - public void checkServerTrusted(X509Certificate ax509certificate[], String s) throws CertificateException - { - //TODO nothing - } - - @Override - public X509Certificate[] getAcceptedIssuers() - { - return new X509Certificate[]{}; - } -} +package luckyclient.utils.httputils; + +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.X509TrustManager; + +/** + * + * ================================================================= + * 这是一个受限制的自由软件!您不能在任何未经允许的前提下对程序代码进行修改和用于商业用途;也不允许对程序代码修改后以任何形式任何目的的再发布。 + * 为了尊重作者的劳动成果,LuckyFrame关键版权信息严禁篡改 有任何疑问欢迎联系作者讨论。 QQ:1573584944 Seagull + * ================================================================= + * @author Seagull + * @date 2019年8月8日 + */ +public class MyX509TrustManager implements X509TrustManager +{ + @Override + public void checkClientTrusted(X509Certificate[] ax509certificate, String s) { + //TODO nothing + } + + @Override + public void checkServerTrusted(X509Certificate[] ax509certificate, String s) { + //TODO nothing + } + + @Override + public X509Certificate[] getAcceptedIssuers() + { + return new X509Certificate[]{}; + } +} diff --git a/src/main/java/springboot/HttpImpl.java b/src/main/java/springboot/HttpImpl.java index b615210..52adb8e 100644 --- a/src/main/java/springboot/HttpImpl.java +++ b/src/main/java/springboot/HttpImpl.java @@ -9,14 +9,11 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; -import java.rmi.RemoteException; +import java.nio.charset.StandardCharsets; +import java.util.Objects; import java.util.Properties; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,14 +48,14 @@ public class HttpImpl { private static final String OS=System.getProperty("os.name").toLowerCase(); /** * 运行自动化任务 - * @param req - * @return - * @throws RemoteException + * @param req HTTP请求 + * @return 返回运行任务结果 */ @PostMapping("/runTask") - private String runTask(HttpServletRequest req) throws RemoteException { + private String runTask(HttpServletRequest req) { StringBuilder sb = new StringBuilder(); - try (BufferedReader reader = req.getReader();) { + try { + BufferedReader reader = req.getReader(); char[] buff = new char[1024]; int len; while ((len = reader.read(buff)) != -1) { @@ -81,7 +78,7 @@ public class HttpImpl { } log.info("初始化Runtime..."); Runtime run = Runtime.getRuntime(); - StringBuffer sbf=new StringBuffer(); + StringBuilder sbf=new StringBuilder(); sbf.append(runTaskEntity.getTaskId()).append(" "); sbf.append(runTaskEntity.getLoadPath()); log.info("启动任务模式测试程序...调度名称:【{}】 任务ID:【{}】",runTaskEntity.getSchedulingName(),runTaskEntity.getTaskId()); @@ -104,14 +101,14 @@ public class HttpImpl { /** * 批量运行用例 - * @param req - * @return - * @throws RemoteException + * @param req HTTP请求 + * @return 返回批量运行用例结果 */ @PostMapping("/runBatchCase") - private String runBatchCase(HttpServletRequest req) throws RemoteException { + private String runBatchCase(HttpServletRequest req) { StringBuilder sbd = new StringBuilder(); - try (BufferedReader reader = req.getReader();) { + try { + BufferedReader reader = req.getReader(); char[] buff = new char[1024]; int len; while ((len = reader.read(buff)) != -1) { @@ -139,7 +136,7 @@ public class HttpImpl { } log.info("初始化Runtime..."); Runtime run = Runtime.getRuntime(); - StringBuffer sb=new StringBuffer(); + StringBuilder sb=new StringBuilder(); sb.append(taskId).append(" "); sb.append(batchCase).append(" "); sb.append(loadPath); @@ -164,14 +161,14 @@ public class HttpImpl { /** * web界面调度接口 - * @param req - * @return - * @throws RemoteException + * @param req HTTP请求 + * @return 返回调试用例运行结果 */ @PostMapping("/webDebugCase") - private String webDebugCase(HttpServletRequest req) throws RemoteException { + private String webDebugCase(HttpServletRequest req) { StringBuilder sbd = new StringBuilder(); - try (BufferedReader reader = req.getReader();) { + try { + BufferedReader reader = req.getReader(); char[] buff = new char[1024]; int len; while ((len = reader.read(buff)) != -1) { @@ -190,7 +187,7 @@ public class HttpImpl { return "客户端测试驱动桩路径不存在,请检查【"+file.getPath()+"】"; } Runtime run = Runtime.getRuntime(); - StringBuffer sb=new StringBuffer(); + StringBuilder sb=new StringBuilder(); sb.append(webDebugCaseEntity.getCaseId()).append(" "); sb.append(webDebugCaseEntity.getUserId()).append(" "); sb.append(webDebugCaseEntity.getLoadpath()); @@ -210,23 +207,19 @@ public class HttpImpl { /** * 获取客户端本地日志 - * @param req - * @return - * @throws RemoteException + * @param req HTTP请求 + * @return 返回日志全部信息 */ @GetMapping("/getLogdDetail") - private String getLogdDetail(HttpServletRequest req) throws RemoteException{ + private String getLogdDetail(HttpServletRequest req) { String fileName=req.getParameter("filename"); String ctxPath = System.getProperty("user.dir")+File.separator+"log"; String downLoadPath = ctxPath +File.separator+ fileName; - String str = ""; - InputStreamReader isr=null; + String str; + InputStreamReader isr; try { - isr = new InputStreamReader(new FileInputStream(downLoadPath), "UTF-8"); - } catch (UnsupportedEncodingException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + isr = new InputStreamReader(new FileInputStream(downLoadPath), StandardCharsets.UTF_8); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -234,7 +227,7 @@ public class HttpImpl { return "读取日志路径错误,请检查客户端日志路径是否存在!downLoadPath: "+downLoadPath; } BufferedReader bos = new BufferedReader(isr); - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); try { while ((str = bos.readLine()) != null) { @@ -253,12 +246,11 @@ public class HttpImpl { /** * 获取错误截图 - * @param req - * @return - * @throws RemoteException + * @param req HTTP请求 + * @return 返回图片字节 */ @GetMapping("/getLogImg") - private byte[] getLogImg(HttpServletRequest req,HttpServletResponse res) throws RemoteException{ + private byte[] getLogImg(HttpServletRequest req) { String imgName=req.getParameter("imgName"); String ctxPath = System.getProperty("user.dir")+File.separator+"log"+File.separator+"ScreenShot"; String downLoadPath = ctxPath+File.separator+imgName; @@ -267,7 +259,7 @@ public class HttpImpl { File file = new File(downLoadPath); b = new byte[(int) file.length()]; BufferedInputStream is = new BufferedInputStream(new FileInputStream(file)); - is.read(b); + //is.read(b); is.close(); log.info("服务端获取本地图片:{}",downLoadPath); } catch (FileNotFoundException e) { @@ -285,9 +277,9 @@ public class HttpImpl { * 上传驱动文件到客户端 */ @PostMapping("/uploadJar") - private String uploadJar(HttpServletRequest req,HttpServletResponse res, HttpSession session,@RequestParam("jarfile") MultipartFile jarfile) throws IOException, ServletException{ + private String uploadJar(HttpServletRequest req, @RequestParam("jarfile") MultipartFile jarfile) { if (!jarfile.isEmpty()){ - if (!jarfile.getOriginalFilename().endsWith(".jar")&&!jarfile.getOriginalFilename().endsWith(".py")) { + if (!Objects.requireNonNull(jarfile.getOriginalFilename()).endsWith(".jar")&&!jarfile.getOriginalFilename().endsWith(".py")) { log.warn("文件格式后缀不是.jar或.py,上传失败"); return "文件格式后缀不是.jar或.py,上传失败"; } @@ -311,14 +303,19 @@ public class HttpImpl { if (file.exists()){ file.deleteOnExit(); } - file.createNewFile(); - BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file)); - byte[] jarfileByte = jarfile.getBytes(); - os.write(jarfileByte); - os.flush(); - os.close(); - log.info("上传驱动包【{}】到客户端驱动目录【{}】成功!",name,file.getAbsolutePath()); - return "上传驱动包【"+name+"】到客户端驱动目录【"+file.getAbsolutePath()+"】成功!"; + boolean newFile = file.createNewFile(); + if(newFile){ + BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file)); + byte[] jarfileByte = jarfile.getBytes(); + os.write(jarfileByte); + os.flush(); + os.close(); + log.info("上传驱动包【{}】到客户端驱动目录【{}】成功!",name,file.getAbsolutePath()); + return "上传驱动包【"+name+"】到客户端驱动目录【"+file.getAbsolutePath()+"】成功!"; + }else{ + log.error("上传驱动包【{}】到客户端驱动目录【{}】失败!",name,file.getAbsolutePath()); + return "上传驱动包【"+name+"】到客户端驱动目录【"+file.getAbsolutePath()+"】失败!"; + } } catch (FileNotFoundException e) { // TODO Auto-generated catch block log.error("客户端未找到正确路径或文件,上传失败!文件路径名称:{}",pathName,e); @@ -332,12 +329,10 @@ public class HttpImpl { /** * 检查客户端心跳 - * @param req - * @return - * @throws RemoteException + * @return 返回心跳结果 */ @GetMapping("/getClientStatus") - private String getClientStatus(HttpServletRequest req) throws RemoteException{ + private String getClientStatus() { Properties properties = SysConfig.getConfiguration(); String verison=properties.getProperty("client.verison"); return "{\"status\":\"success\",\"version\":\""+verison+"\"}"; @@ -345,14 +340,12 @@ public class HttpImpl { /** * 获取客户端资源监控情况 - * @param req - * @return + * @return 返回客户端资源情况 * @author Seagull - * @throws Exception * @date 2019年5月5日 */ @GetMapping("/getClientMonitorData") - private String getClientMonitorData(HttpServletRequest req) throws Exception{ + private String getClientMonitorData() { Server server = new Server(); server.copyTo(); return JSON.toJSONString(server); @@ -360,11 +353,10 @@ public class HttpImpl { /** * 检查客户端中的配置 - * @return * @author Seagull * @date 2019年5月6日 */ - public static boolean checkHostNet() { + public static void checkHostNet() { log.info("检查客户端配置中,请稍后......"); Properties properties = SysConfig.getConfiguration(); String version="Version "+properties.getProperty("client.verison"); @@ -384,9 +376,7 @@ public class HttpImpl { } catch (Exception e) { log.error("客户端配置检测异常,请确认您项目根目录下的客户端配置文件(sys_config.properties)是否已经正确配置。",e); - return false; - } - return true; - } + } + } }