diff --git a/test-common/src/main/java/com/test/common/utils/SeleniumUtils.java b/test-common/src/main/java/com/test/common/utils/SeleniumUtils.java index d29ef3f..c310f2b 100644 --- a/test-common/src/main/java/com/test/common/utils/SeleniumUtils.java +++ b/test-common/src/main/java/com/test/common/utils/SeleniumUtils.java @@ -855,4 +855,16 @@ public class SeleniumUtils { } } + /** + * 在新标签页打开URL + * @param url 要打开的网址 + */ + public void openUrlInNewTab(String url) { + // 打开新标签页 + driver.switchTo().newWindow(WindowType.TAB); + + // 导航到目标URL + driver.get(url); + } + } diff --git a/test-test/src/main/java/com/test/test/controller/UiAutomationController.java b/test-test/src/main/java/com/test/test/controller/UiAutomationController.java index 601b580..e744b4d 100644 --- a/test-test/src/main/java/com/test/test/controller/UiAutomationController.java +++ b/test-test/src/main/java/com/test/test/controller/UiAutomationController.java @@ -107,7 +107,7 @@ public class UiAutomationController extends BaseController */ // @PreAuthorize("@ss.hasPermi('system:automation:remove')") @GetMapping("/executeStep") - public AjaxResult remove(@RequestParam Long id) + public AjaxResult executeStep(@RequestParam Long id) { try{ log.info("执行完成!"); diff --git a/test-test/src/main/java/com/test/test/service/impl/UiAutomationServiceImpl.java b/test-test/src/main/java/com/test/test/service/impl/UiAutomationServiceImpl.java index 11a5cc5..213d05c 100644 --- a/test-test/src/main/java/com/test/test/service/impl/UiAutomationServiceImpl.java +++ b/test-test/src/main/java/com/test/test/service/impl/UiAutomationServiceImpl.java @@ -187,7 +187,7 @@ public class UiAutomationServiceImpl implements IUiAutomationService { uiAutomation.setUpdateTime(DateUtils.getNowDate()); uiAutomation.setCreateBy(SecurityUtils.getUsername()); uiAutomation.setUpdateBy(SecurityUtils.getUsername()); - uiAutomation.setStatus("1"); //未开始 +// uiAutomation.setStatus("1"); //未开始 uiAutomation.setDutyBy(SecurityUtils.getUsername()); uiAutomation.setDelFlag(0); uiAutomation.setCrontabStatus(0); //未开启 diff --git a/test-test/src/main/java/com/test/test/service/impl/UiSceneStepsServiceImpl.java b/test-test/src/main/java/com/test/test/service/impl/UiSceneStepsServiceImpl.java index 4aa1dbc..eca6a85 100644 --- a/test-test/src/main/java/com/test/test/service/impl/UiSceneStepsServiceImpl.java +++ b/test-test/src/main/java/com/test/test/service/impl/UiSceneStepsServiceImpl.java @@ -24,6 +24,7 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.chrome.ChromeDriver; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -45,7 +46,8 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { @Resource private UiAutomationMapper uiAutomationMapper; - + @Value("${test.selenium.chrome-driver-path}") + private String chromeDriverPath; /** @@ -63,15 +65,15 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { //修改ui_automation 状态为进行中 执行结果为running UiAutomation uiAutomation = new UiAutomation(); - uiAutomation.setStatus("2"); + uiAutomation.setId(automationId); uiAutomation.setExecutionResult("1"); - uiAutomation.setUpdateBy(DateUtils.getTime()); + uiAutomation.setUpdateTime(DateUtils.getNowDate()); uiAutomationMapper.updateUiAutomation(uiAutomation); Date startTime = DateUtils.getNowDate(); // 2. 创建执行报告 - Long reportId = uiReportService.insertUiReport(startTime, automationId, "1", steps.size()); + Long reportId = uiReportService.insertUiReport(startTime, automationId, "1", steps.size()); UiReport uiReport = new UiReport(); result.put("id", reportId); uiReport.setId(reportId); @@ -80,7 +82,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { for (UiSceneSteps step : steps) { orderNumber++; //创建报告步骤表 - createSceneStepsReport(orderNumber,step, reportId); + createSceneStepsReport(orderNumber, step, reportId); } try { // 3. 执行所有步骤 @@ -133,20 +135,21 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { uiReport.setStepsNotNumber(stepsNotNumber); uiReport.setFaiiRate( stepsErrorNumber == 0 ? "0%" : - String.format("%.2f%%", (double)stepsErrorNumber / steps.size() * 100) + String.format("%.2f%%", (double) stepsErrorNumber / steps.size() * 100) ); uiReportService.updateUiReport(uiReport); //修改ui_automation - uiAutomation = new UiAutomation(); - if (!uiAutomation.getExecutionResult().equals("2")){ - uiAutomation.setExecutionResult("3"); - uiAutomation.setStatus("3"); + UiAutomation uiAutomation1 = new UiAutomation(); + uiAutomation1.setId(automationId); + uiAutomation1.setExecutionResult("2"); + if (!uiAutomation.getExecutionResult().equals("2")) { + uiAutomation1.setExecutionResult("3"); } - uiAutomation.setUpdateBy(DateUtils.getTime()); - uiAutomation.setPassRate(stepsSucceedNumber == 0 ? "0%" : - String.format("%.2f%%", (double)stepsSucceedNumber / steps.size() * 100)); - uiAutomationMapper.updateUiAutomation(uiAutomation); + uiAutomation1.setUpdateTime(DateUtils.getNowDate()); + uiAutomation1.setPassRate(stepsSucceedNumber == 0 ? "0%" : + String.format("%.2f%%", (double) stepsSucceedNumber / steps.size() * 100)); + uiAutomationMapper.updateUiAutomation(uiAutomation1); } return result; } @@ -159,7 +162,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { */ private List validateAndGetSteps(Long automationId) { List steps = uiSceneStepsMapper.selectUiSceneStepsById(automationId); - steps = steps.stream().filter(e->e.getIsDisabled() == 0).collect(Collectors.toList()); + steps = steps.stream().filter(e -> e.getIsDisabled() == 0).collect(Collectors.toList()); if (CollectionUtils.isEmpty(steps)) { throw new IllegalArgumentException("步骤不能为空"); } @@ -176,7 +179,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { * @param steps * @param reportId */ - private Long createSceneStepsReport(Integer orderNumber,UiSceneSteps steps, Long reportId) { + private Long createSceneStepsReport(Integer orderNumber, UiSceneSteps steps, Long reportId) { UiSceneStepsReport uiSceneStepsReport = new UiSceneStepsReport(); uiSceneStepsReport.setReportId(reportId); uiSceneStepsReport.setName(steps.getName()); @@ -194,7 +197,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { * @param steps */ private void executeAllSteps(List steps, Long reportId) { - System.setProperty("webdriver.chrome.driver", "D:/chromedriver-win64/chromedriver.exe"); + System.setProperty("webdriver.chrome.driver", chromeDriverPath); WebDriver driver = new ChromeDriver(); SeleniumUtils seleniumUtils = new SeleniumUtils(driver); Integer orderNumber = 0; @@ -265,14 +268,13 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { } - /** * 执行步骤并记录日志 * - * @param step 步骤对象 - * @param seleniumUtils Selenium工具类 - * @param sceneStepsReportId 报告步骤ID - * @param stepExecution 具体的步骤执行方法 + * @param step 步骤对象 + * @param seleniumUtils Selenium工具类 + * @param sceneStepsReportId 报告步骤ID + * @param stepExecution 具体的步骤执行方法 * @param uiHighSettingVOList 高级设置列表 * @return boolean 是否继续执行后续步骤 (true=继续, false=终止) */ @@ -285,7 +287,14 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { OtherSettingsQO otherSettingsQO = otherSetting.getOtherSettingsQO(); Integer screenshotConfiguration = otherSettingsQO.getScreenshotConfiguration(); //是否截图 1当前步骤截图 2异常截图 3 不截图 //等待元素超时时间 - Integer waitElementTime = otherSettingsQO.getWaitElementTime()==null?0:otherSettingsQO.getWaitElementTime(); + Integer waitElementTime = otherSettingsQO.getWaitElementTime() == null ? 0 : otherSettingsQO.getWaitElementTime(); + if (waitElementTime > 0) { + // 转换为秒(至少1秒) + long timeoutInSeconds = Math.max(1, waitElementTime / 1000); + log.info("元素等待时间{}秒", timeoutInSeconds); + seleniumUtils.setWaitTimeout(timeoutInSeconds); + } + //前置操作设置 List beforeSettingList = extractbeforeSetting(uiHighSettingVOList); //后置操作设置 @@ -309,7 +318,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { if (screenshotConfiguration == 1) { report.setScreenshot(seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile())); - log.info("截图成功,路径:{}",seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile())); + log.info("截图成功,路径:{}", seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile())); } // 3. 执行具体步骤 stepExecution.execute(step, seleniumUtils); @@ -332,7 +341,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { } if (screenshotConfiguration == 2) { report.setScreenshot(seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile())); - log.info("截图成功,路径:{}",seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile())); + log.info("截图成功,路径:{}", seleniumUtils.takeScreenshotAsFile(TestConfig.getProfile())); } log.error("步骤执行失败: {}", e.getMessage()); } finally { @@ -340,7 +349,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { // 更新报告 report.setCreateTime(startTime); report.setUpdateTime(endTime); - report.setTake(DateUtils.differenceInMilliseconds(startTime,endTime) + "ms"); + report.setTake(DateUtils.differenceInMilliseconds(startTime, endTime) + "ms"); uiSceneStepsReportMapper.updateUiSceneStepsReport(report); } @@ -350,6 +359,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { /** * 提取前置操作 + * * @param settings * @return */ @@ -361,10 +371,11 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { /** * 获取(前置//后置)等待时间 + * * @param settingList * @return */ - private int getAwaitTime(List settingList){ + private int getAwaitTime(List settingList) { //获取前置等待时间 int totalWaitTime = settingList.stream() .map(UiHighSettingVO::getAwateTime) @@ -384,6 +395,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { /** * 提取后置操作 + * * @param settings * @return */ @@ -395,6 +407,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { /** * 提取错误处理设置 + * * @param settings * @return */ @@ -406,10 +419,9 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { } - - /** * 提取错误处理设置 + * * @param settings * @return */ @@ -421,56 +433,60 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { } - - - - - //---------------------浏览器操作--------------------------- /** * 打开网页 * - * @param step 步骤对象 + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ private void openWebPage(UiSceneSteps step, SeleniumUtils seleniumUtils) { - log.info("打开网页:{}",step.getUrl()); - seleniumUtils.openUrl(step.getUrl()); + //追加页面,在新的页面打开url,不勾选覆盖当前url 0不追加 1追加 + Integer isAppendPage = step.getIsAppendPage(); // 0=当前页,1=新标签页 + String url = step.getUrl(); + log.info("打开网页:{}, 模式:{}", url, isAppendPage == 1 ? "新标签页" : "当前页"); + if (isAppendPage != null && isAppendPage == 1) { + // 新标签页打开 + seleniumUtils.openUrlInNewTab(url); + } else { + // 默认当前页打开 + seleniumUtils.openUrl(url); + } } /** * 关闭网页 * - * @param step 步骤对象 + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ private void closeBrowser(UiSceneSteps step, SeleniumUtils seleniumUtils) { log.info("关闭网页"); - seleniumUtils.quit(); + seleniumUtils.closeCurrentWindow(); } /** * 切换窗口 * - * @param step 步骤对象 + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ private void switchWindow(UiSceneSteps step, SeleniumUtils seleniumUtils) { - if (step.getOperate()==1){ + if (step.getOperate() == 1) { log.info("根据句柄 ID 切换到指定窗口"); //句柄id String handleId = step.getHandleId(); seleniumUtils.switchToWindowByHandle(handleId); - }else if (step.getOperate()==2){ + } else if (step.getOperate() == 2) { log.info("根据网页索引号切换到指定窗口"); //网页索引号 Integer frameIndex = step.getFrameIndex(); seleniumUtils.switchToWindowByIndex(frameIndex); - }else if (step.getOperate()==3){ + } else if (step.getOperate() == 3) { log.info("切换到初始窗口"); seleniumUtils.switchToDefaultWindow(); - }else{ + } else { log.info("无效的窗口切换操作类型"); throw new IllegalArgumentException("无效的窗口切换操作类型"); } @@ -479,22 +495,22 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { /** * 设置窗口大小 * - * @param step 步骤对象 + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ private void resizeWindow(UiSceneSteps step, SeleniumUtils seleniumUtils) { - if (step.getOperate()==1){ + if (step.getOperate() == 1) { log.info("窗口最大化"); //窗口最大化 seleniumUtils.maximizeWindow(); - }else if (step.getOperate()==2){ + } else if (step.getOperate() == 2) { log.info("设置窗口大小"); String windowSize = step.getWindowSize(); String[] dimensions = windowSize.split("\\*"); int width = Integer.parseInt(dimensions[0]); int height = Integer.parseInt(dimensions[1]); seleniumUtils.setWindowSize(width, height); - }else{ + } else { log.info("无效的设置窗口大小"); throw new IllegalArgumentException("无效的设置窗口大小"); } @@ -504,18 +520,18 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { /** * 选择内嵌网页 * - * @param step 步骤对象 + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ private void selectEmbeddedPage(UiSceneSteps step, SeleniumUtils seleniumUtils) { - if (step.getOperate()==1){ + if (step.getOperate() == 1) { log.info("退出当前 frame(回到主页面)"); seleniumUtils.switchToDefaultContent(); - }else if (step.getOperate()==2){ + } else if (step.getOperate() == 2) { log.info("根据 frame 索引号切换到指定 frame"); //网页索引号 seleniumUtils.switchToFrameByIndex(step.getFrameIndex()); - }else if (step.getOperate()==3){ + } else if (step.getOperate() == 3) { log.info("根据定位方式切换 frame"); if ("2".equals(step.getOperateObject())) { //元素对象 @@ -525,7 +541,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { operateLocType, operateLocValue ); - }else{ + } else { //元素定位 UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId()); if (uiElement == null) { @@ -538,7 +554,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { elementLoc ); } - } else{ + } else { log.info("无效的选择内嵌网页"); throw new IllegalArgumentException("无效的选择内嵌网页"); } @@ -550,11 +566,11 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { /** * 弹窗操作 * - * @param step 步骤对象 + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ private void handlePopup(UiSceneSteps step, SeleniumUtils seleniumUtils) { - if (step.getOperate()==1){ + if (step.getOperate() == 1) { log.info("弹窗操作"); // 获取输入内容(如果需要) String inputValue = "1".equals(step.getIsEnter()) ? step.getInputValue() : null; @@ -564,7 +580,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { Integer.parseInt(operateWay), // 操作方式 (1=确定, 2=取消) inputValue // 输入内容 ); - }else{ + } else { log.info("无效的弹窗操作"); throw new IllegalArgumentException("无效的弹窗操作"); } @@ -575,7 +591,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { /** * 提交表单 * - * @param step 步骤对象 + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ private void submitForm(UiSceneSteps step, SeleniumUtils seleniumUtils) { @@ -586,7 +602,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { // 根据属性和值定位元素并提交表单 seleniumUtils.findElement(operateLocType, operateLocValue).submit(); log.info("通过元素对象提交表单,定位方式:{},定位值:{}", operateLocType, operateLocValue); - }else{ + } else { //元素定位 UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId()); if (uiElement == null) { @@ -603,7 +619,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { /** * 下拉框操作 * - * @param step 步骤对象 + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ private void handleDropdown(UiSceneSteps step, SeleniumUtils seleniumUtils) { @@ -616,7 +632,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { String operateLocValue = step.getOperateLocValue(); //值 dropdownElement = seleniumUtils.findElement(operateLocType, operateLocValue); log.info("通过元素对象定位下拉框,定位方式:{},定位值:{}", operateLocType, operateLocValue); - }else{ + } else { //元素定位 UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId()); if (uiElement == null) { @@ -648,7 +664,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { /** * 设置选项 * - * @param step 步骤对象 + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ private void setOption(UiSceneSteps step, SeleniumUtils seleniumUtils) { @@ -696,7 +712,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { /** * 等待元素 * - * @param step 步骤对象 + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ private void waitForElement(UiSceneSteps step, SeleniumUtils seleniumUtils) { @@ -712,7 +728,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { operateLocType, operateLocValue ); - }else{ + } else { //元素定位 UiElement uiElement = uiElementService.selectUiElementById(step.getOperateElementId()); String locType = uiElement.getLocType(); //属性 @@ -746,7 +762,8 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { /** * 鼠标点击操作 - * @param step 步骤对象 + * + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ private void mouseClick(UiSceneSteps step, SeleniumUtils seleniumUtils) { @@ -781,13 +798,14 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { throw new RuntimeException("鼠标操作类型必须是数字(1-5)", e); } catch (Exception e) { log.error("鼠标操作执行失败", e); - throw new RuntimeException("鼠标操作失败: " + e.getMessage(), e); + throw new RuntimeException("鼠标操作失败: " + e, e); } } /** * 鼠标移动操作 - * @param step 步骤对象 + * + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ private void mouseMove(UiSceneSteps step, SeleniumUtils seleniumUtils) { @@ -824,13 +842,14 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { throw new RuntimeException("鼠标移动类型必须是数字(1-2)", e); } catch (Exception e) { log.error("鼠标移动操作执行失败", e); - throw new RuntimeException("鼠标移动操作失败: " + e.getMessage(), e); + throw new RuntimeException("鼠标移动操作失败: " + e, e); } } /** * 输入操作 - * @param step 步骤对象 + * + * @param step 步骤对象 * @param seleniumUtils Selenium工具类 */ public void inputText(UiSceneSteps step, SeleniumUtils seleniumUtils) { @@ -883,16 +902,17 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService { } catch (Exception e) { log.error("输入操作执行失败", e); - throw new RuntimeException("输入操作失败: " + e.getMessage(), e); + throw new RuntimeException("输入操作失败: " + e, e); } } /** * 文件上传 + * * @param step * @param seleniumUtils */ - public void uploadFile(UiSceneSteps step, SeleniumUtils seleniumUtils){ + public void uploadFile(UiSceneSteps step, SeleniumUtils seleniumUtils) { } diff --git a/test-test/src/main/resources/mapper/test/UiReportMapper.xml b/test-test/src/main/resources/mapper/test/UiReportMapper.xml index a31dd80..3b3ee57 100644 --- a/test-test/src/main/resources/mapper/test/UiReportMapper.xml +++ b/test-test/src/main/resources/mapper/test/UiReportMapper.xml @@ -56,7 +56,7 @@ and steps_error_number = #{stepsErrorNumber} and steps_not_number = #{stepsNotNumber} - order by create_time asc + order by create_time desc