执行高级设置 断言和数据提取
This commit is contained in:
@@ -8,6 +8,7 @@ import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Date;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
|
||||
@@ -232,4 +233,14 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
|
||||
}
|
||||
return endTime.getTime() - startTime.getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化日期为 yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String formatDateTime(Date date) {
|
||||
return date.toInstant()
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDateTime()
|
||||
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -867,4 +867,41 @@ public class SeleniumUtils {
|
||||
driver.get(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据提取提取窗口信息
|
||||
* @param windowType
|
||||
* @return
|
||||
*/
|
||||
public String extractWindowInformation(String windowType) {
|
||||
switch (windowType) {
|
||||
case "1": // 窗口 Handle
|
||||
return driver.getWindowHandle();
|
||||
case "2": // 网页标题
|
||||
return driver.getTitle();
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid windowType: " + windowType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找多个元素
|
||||
* @param locType
|
||||
* @param locValue
|
||||
* @return
|
||||
*/
|
||||
public List<WebElement> findElements(String locType, String locValue) {
|
||||
return driver.findElements(getLocator(locType, locValue));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取网页标题
|
||||
* @return
|
||||
*/
|
||||
public String getTitle(){
|
||||
return driver.getTitle();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,13 +2,17 @@ package com.test.test.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.test.common.utils.SeleniumUtils;
|
||||
import com.test.test.domain.UiAutomation;
|
||||
import com.test.test.domain.qo.UiAutomationDataQO;
|
||||
import com.test.test.domain.qo.UiAutomationQO;
|
||||
import com.test.test.service.IUiAutomationService;
|
||||
import com.test.test.service.IUiSceneStepsService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.chrome.ChromeDriver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import com.test.common.annotation.Log;
|
||||
import com.test.common.core.controller.BaseController;
|
||||
@@ -32,6 +36,8 @@ public class UiAutomationController extends BaseController
|
||||
private IUiAutomationService uiAutomationService;
|
||||
@Autowired
|
||||
private IUiSceneStepsService uiSceneStepsService;
|
||||
@Value("${test.selenium.chrome-driver-path}")
|
||||
private String chromeDriverPath;
|
||||
|
||||
/**
|
||||
* 查询ui自动化列表
|
||||
@@ -110,11 +116,17 @@ public class UiAutomationController extends BaseController
|
||||
public AjaxResult executeStep(@RequestParam Long id)
|
||||
{
|
||||
try{
|
||||
String triggerMode = "1"; //手动执行
|
||||
log.info("执行完成!");
|
||||
return success(uiSceneStepsService.executeStep(id));
|
||||
return success(uiSceneStepsService.executeStep(id,triggerMode));
|
||||
} catch (Exception e) {
|
||||
log.error("执行完成!",e);
|
||||
return error("执行完成!");
|
||||
System.setProperty("webdriver.chrome.driver", chromeDriverPath);
|
||||
WebDriver driver = new ChromeDriver();
|
||||
SeleniumUtils seleniumUtils = new SeleniumUtils(driver);
|
||||
//关闭浏览器
|
||||
seleniumUtils.quit();
|
||||
log.error("执行错误!",e);
|
||||
return error("执行错误!"+e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.test.test.domain.qo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class AssertionConfigQO {
|
||||
/** 弹窗文本数组 */
|
||||
private List<AssertionQO> popupTexts = new ArrayList<>();
|
||||
|
||||
/** 元素断言数组 */
|
||||
private List<AssertionQO> elementAssertions = new ArrayList<>();
|
||||
|
||||
/** 下拉框数组 */
|
||||
private List<AssertionQO> dropdownBoxes = new ArrayList<>();
|
||||
|
||||
/** 网页标题数组 */
|
||||
private List<AssertionQO> webTitles = new ArrayList<>();
|
||||
}
|
||||
@@ -18,10 +18,10 @@ public class AssertionQO {
|
||||
private String operateObject;
|
||||
|
||||
/** 元素库名称 */
|
||||
private Integer operateGroupId;
|
||||
private Long operateGroupId;
|
||||
|
||||
/** 元素id */
|
||||
private Integer operateElementId;
|
||||
private Long operateElementId;
|
||||
|
||||
/** 元素定位类型 id css ……*/
|
||||
private String operateLocType;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.test.test.domain.qo;
|
||||
|
||||
import lombok.Data;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据提取配置(新版嵌套结构)
|
||||
*/
|
||||
@Data
|
||||
public class DataExtractionConfigQO {
|
||||
/** 窗口信息提取配置 */
|
||||
private List<DataExtractionQO> windowExtractions;
|
||||
|
||||
/** 元素信息提取配置 */
|
||||
private List<DataExtractionQO> elementExtractions;
|
||||
}
|
||||
@@ -8,14 +8,14 @@ import lombok.Data;
|
||||
@Data
|
||||
public class DataExtractionQO {
|
||||
|
||||
/** 1提取元素信息 2提取窗口信息 */
|
||||
/** 1提取窗口信息 2提取元素信息 */
|
||||
private String informationType;
|
||||
|
||||
/** 1普通对象(store) 2元素文本(storeText) 3元素值(storeValue) 4元素属性(storeAttribute)
|
||||
/** informationType为2时 1普通对象(store) 2元素文本(storeText) 3元素值(storeValue) 4元素属性(storeAttribute)
|
||||
* 5CSS属性(storeCssAttribute) 6匹配 xpath 的元素数量(storeXpathCount) */
|
||||
private String elementType;
|
||||
|
||||
/** 1窗口 Handle(storeWindowHandle) 2网页标题(storeTitle) */
|
||||
/** informationType为1时 1窗口 Handle(storeWindowHandle) 2网页标题(storeTitle) */
|
||||
private String windowType;
|
||||
|
||||
/**值 */
|
||||
@@ -26,10 +26,10 @@ public class DataExtractionQO {
|
||||
private String operateObject;
|
||||
|
||||
/** 元素库名称 */
|
||||
private Integer operateGroupId;
|
||||
private Long operateGroupId;
|
||||
|
||||
/** 元素id */
|
||||
private Integer operateElementId;
|
||||
private Long operateElementId;
|
||||
|
||||
/** 元素定位类型 id css ……*/
|
||||
private String operateLocType;
|
||||
@@ -37,7 +37,7 @@ public class DataExtractionQO {
|
||||
/** 元素定位值 */
|
||||
private String operateLocValue;
|
||||
|
||||
/**元素属性*/
|
||||
/** 普通对象 元素属性 元素css属性*/
|
||||
private String elementAttribute;
|
||||
|
||||
/**是否禁用 0否 1是 */
|
||||
|
||||
@@ -56,16 +56,13 @@ public class UiHighSettingQO extends BaseEntity
|
||||
/** 是否删除 */
|
||||
private Integer delFlag;
|
||||
|
||||
/** 等待元素超时时间 */
|
||||
private Integer waitElementTime;
|
||||
|
||||
/** 截图配置 */
|
||||
private Integer screenshotConfiguration;
|
||||
/**其他设置*/
|
||||
OtherSettingsQO otherSettingsQO = new OtherSettingsQO();
|
||||
|
||||
/**数据提取*/
|
||||
private List<DataExtractionQO> dataExtractionQOList = new ArrayList<>();
|
||||
private DataExtractionConfigQO dataExtractionQOList = new DataExtractionConfigQO();
|
||||
|
||||
/**断言*/
|
||||
private List<AssertionQO> assertionQOList = new ArrayList<>();
|
||||
private AssertionConfigQO assertionQOList = new AssertionConfigQO();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.test.test.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 断言报告结果
|
||||
*/
|
||||
@Data
|
||||
public class AssertionReportVO {
|
||||
|
||||
/**
|
||||
* 断言名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private String errorInfo;
|
||||
|
||||
/**
|
||||
* 是否成功 0否 1是
|
||||
*/
|
||||
private String isSuccess;
|
||||
}
|
||||
@@ -1,13 +1,10 @@
|
||||
package com.test.test.domain.vo;
|
||||
|
||||
import com.test.common.annotation.Excel;
|
||||
import com.test.common.core.domain.BaseEntity;
|
||||
import com.test.test.domain.qo.AssertionConfigQO;
|
||||
import com.test.test.domain.qo.AssertionQO;
|
||||
import com.test.test.domain.qo.DataExtractionQO;
|
||||
import com.test.test.domain.qo.DataExtractionConfigQO;
|
||||
import com.test.test.domain.qo.OtherSettingsQO;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -48,10 +45,10 @@ public class UiHighSettingVO
|
||||
private Integer isDisabled;
|
||||
|
||||
/**断言*/
|
||||
private List<AssertionQO> assertionQOList = new ArrayList<>();
|
||||
private AssertionConfigQO assertionQOList = new AssertionConfigQO();
|
||||
|
||||
/**数据提取*/
|
||||
private List<DataExtractionQO> dataExtractionQOList = new ArrayList<>();
|
||||
private DataExtractionConfigQO dataExtractionQOList =new DataExtractionConfigQO();
|
||||
|
||||
/**其他设置*/
|
||||
private OtherSettingsQO otherSettingsQO;
|
||||
|
||||
@@ -19,6 +19,6 @@ public interface IUiSceneStepsService
|
||||
* @param automationId 场景id
|
||||
* @return
|
||||
*/
|
||||
Map<String,Object> executeStep(Long automationId);
|
||||
Map<String,Object> executeStep(Long automationId,String triggerMode);
|
||||
|
||||
}
|
||||
|
||||
@@ -76,16 +76,44 @@ public class UiAutomationServiceImpl implements IUiAutomationService {
|
||||
new TypeReference<List<AssertionQO>>() {
|
||||
}
|
||||
);
|
||||
uiHighSettingVO.setAssertionQOList(assertionList);
|
||||
List<AssertionQO> popupTexts = new ArrayList<>();
|
||||
List<AssertionQO> elementAssertions = new ArrayList<>();
|
||||
List<AssertionQO> dropdownBoxes = new ArrayList<>();
|
||||
List<AssertionQO> webTitles = new ArrayList<>();
|
||||
for (AssertionQO extractionQO : assertionList) {
|
||||
if ("1".equals(extractionQO.getAssertionType())) {
|
||||
popupTexts.add(extractionQO);
|
||||
} else if ("2".equals(extractionQO.getAssertionType())) {
|
||||
elementAssertions.add(extractionQO);
|
||||
}else if ("3".equals(extractionQO.getAssertionType())) {
|
||||
dropdownBoxes.add(extractionQO);
|
||||
}else if ("4".equals(extractionQO.getAssertionType())) {
|
||||
webTitles.add(extractionQO);
|
||||
}
|
||||
}
|
||||
uiHighSettingVO.getAssertionQOList().setPopupTexts(popupTexts);
|
||||
uiHighSettingVO.getAssertionQOList().setElementAssertions(elementAssertions);
|
||||
uiHighSettingVO.getAssertionQOList().setDropdownBoxes(dropdownBoxes);
|
||||
uiHighSettingVO.getAssertionQOList().setWebTitles(webTitles);
|
||||
// 转换extractionDataJson 数据提取
|
||||
if (StringUtils.isNotBlank(uiHighSetting.getExtractionDataJson())) {
|
||||
List<DataExtractionQO> extractionData = null;
|
||||
extractionData = objectMapper.readValue(
|
||||
uiHighSetting.getExtractionDataJson(),
|
||||
new TypeReference<List<DataExtractionQO>>(){
|
||||
new TypeReference<List<DataExtractionQO>>() {
|
||||
}
|
||||
);
|
||||
uiHighSettingVO.setDataExtractionQOList(extractionData);
|
||||
List<DataExtractionQO> windowExtractions = new ArrayList<>();
|
||||
List<DataExtractionQO> elementExtractions = new ArrayList<>();
|
||||
for (DataExtractionQO extractionQO : extractionData) {
|
||||
if ("1".equals(extractionQO.getInformationType())) {
|
||||
windowExtractions.add(extractionQO);
|
||||
} else if ("2".equals(extractionQO.getInformationType())) {
|
||||
elementExtractions.add(extractionQO);
|
||||
}
|
||||
}
|
||||
uiHighSettingVO.getDataExtractionQOList().setWindowExtractions(windowExtractions);
|
||||
uiHighSettingVO.getDataExtractionQOList().setElementExtractions(elementExtractions);
|
||||
}
|
||||
// 转换otherSetting 其他设置
|
||||
if (StringUtils.isNotBlank(uiHighSetting.getOtherSetting())) {
|
||||
@@ -122,7 +150,25 @@ public class UiAutomationServiceImpl implements IUiAutomationService {
|
||||
new TypeReference<List<AssertionQO>>() {
|
||||
}
|
||||
);
|
||||
uiHighSettingVO.setAssertionQOList(assertionList);
|
||||
List<AssertionQO> popupTexts = new ArrayList<>();
|
||||
List<AssertionQO> elementAssertions = new ArrayList<>();
|
||||
List<AssertionQO> dropdownBoxes = new ArrayList<>();
|
||||
List<AssertionQO> webTitles = new ArrayList<>();
|
||||
for (AssertionQO extractionQO : assertionList) {
|
||||
if ("1".equals(extractionQO.getAssertionType())) {
|
||||
popupTexts.add(extractionQO);
|
||||
} else if ("2".equals(extractionQO.getAssertionType())) {
|
||||
elementAssertions.add(extractionQO);
|
||||
}else if ("3".equals(extractionQO.getAssertionType())) {
|
||||
dropdownBoxes.add(extractionQO);
|
||||
}else if ("4".equals(extractionQO.getAssertionType())) {
|
||||
webTitles.add(extractionQO);
|
||||
}
|
||||
}
|
||||
uiHighSettingVO.getAssertionQOList().setPopupTexts(popupTexts);
|
||||
uiHighSettingVO.getAssertionQOList().setElementAssertions(elementAssertions);
|
||||
uiHighSettingVO.getAssertionQOList().setDropdownBoxes(dropdownBoxes);
|
||||
uiHighSettingVO.getAssertionQOList().setWebTitles(webTitles);
|
||||
// 转换extractionDataJson 数据提取
|
||||
if (StringUtils.isNotBlank(uiHighSetting.getExtractionDataJson())) {
|
||||
List<DataExtractionQO> extractionData = null;
|
||||
@@ -131,7 +177,17 @@ public class UiAutomationServiceImpl implements IUiAutomationService {
|
||||
new TypeReference<List<DataExtractionQO>>() {
|
||||
}
|
||||
);
|
||||
uiHighSettingVO.setDataExtractionQOList(extractionData);
|
||||
List<DataExtractionQO> windowExtractions = new ArrayList<>();
|
||||
List<DataExtractionQO> elementExtractions = new ArrayList<>();
|
||||
for (DataExtractionQO extractionQO : extractionData) {
|
||||
if ("1".equals(extractionQO.getInformationType())) {
|
||||
windowExtractions.add(extractionQO);
|
||||
} else if ("2".equals(extractionQO.getInformationType())) {
|
||||
elementExtractions.add(extractionQO);
|
||||
}
|
||||
}
|
||||
uiHighSettingVO.getDataExtractionQOList().setWindowExtractions(windowExtractions);
|
||||
uiHighSettingVO.getDataExtractionQOList().setElementExtractions(elementExtractions);
|
||||
}
|
||||
// 转换otherSetting 其他设置
|
||||
if (StringUtils.isNotBlank(uiHighSetting.getOtherSetting())) {
|
||||
@@ -187,7 +243,6 @@ public class UiAutomationServiceImpl implements IUiAutomationService {
|
||||
uiAutomation.setUpdateTime(DateUtils.getNowDate());
|
||||
uiAutomation.setCreateBy(SecurityUtils.getUsername());
|
||||
uiAutomation.setUpdateBy(SecurityUtils.getUsername());
|
||||
// uiAutomation.setStatus("1"); //未开始
|
||||
uiAutomation.setDutyBy(SecurityUtils.getUsername());
|
||||
uiAutomation.setDelFlag(0);
|
||||
uiAutomation.setCrontabStatus(0); //未开启
|
||||
@@ -218,22 +273,27 @@ public class UiAutomationServiceImpl implements IUiAutomationService {
|
||||
uiHighSetting.setCreateBy(SecurityUtils.getUsername());
|
||||
uiHighSetting.setCreateTime(DateUtils.getNowDate());
|
||||
try {
|
||||
List<DataExtractionQO> combinedList1 = new ArrayList<>();
|
||||
combinedList1.addAll(uiHighSettingQO.getDataExtractionQOList().getWindowExtractions());
|
||||
combinedList1.addAll(uiHighSettingQO.getDataExtractionQOList().getElementExtractions());
|
||||
//数据提取
|
||||
String jsonStr = objectMapper.writeValueAsString(uiHighSettingQO.getDataExtractionQOList());
|
||||
String jsonStr = objectMapper.writeValueAsString(combinedList1);
|
||||
if (jsonStr != null) {
|
||||
uiHighSetting.setExtractionDataJson(jsonStr);
|
||||
}
|
||||
//断言
|
||||
jsonStr = objectMapper.writeValueAsString(uiHighSettingQO.getAssertionQOList());
|
||||
List<AssertionQO> combinedList2 = new ArrayList<>();
|
||||
combinedList2.addAll(uiHighSettingQO.getAssertionQOList().getPopupTexts());
|
||||
combinedList2.addAll(uiHighSettingQO.getAssertionQOList().getElementAssertions());
|
||||
combinedList2.addAll(uiHighSettingQO.getAssertionQOList().getDropdownBoxes());
|
||||
combinedList2.addAll(uiHighSettingQO.getAssertionQOList().getWebTitles());
|
||||
jsonStr = objectMapper.writeValueAsString(combinedList2);
|
||||
if (jsonStr != null) {
|
||||
uiHighSetting.setAssertionJson(jsonStr);
|
||||
}
|
||||
//其他设置
|
||||
if (uiHighSettingQO.getWaitElementTime() != null || uiHighSettingQO.getScreenshotConfiguration() != null) {
|
||||
OtherSettingsQO settings = new OtherSettingsQO();
|
||||
settings.setWaitElementTime(uiHighSettingQO.getWaitElementTime());
|
||||
settings.setScreenshotConfiguration(uiHighSettingQO.getScreenshotConfiguration());
|
||||
jsonStr = objectMapper.writeValueAsString(settings);
|
||||
if (uiHighSettingQO.getOtherSettingsQO()!=null) {
|
||||
jsonStr = objectMapper.writeValueAsString(uiHighSettingQO.getOtherSettingsQO());
|
||||
uiHighSetting.setOtherSetting(jsonStr);
|
||||
}
|
||||
} catch (JsonProcessingException e) {
|
||||
@@ -297,22 +357,27 @@ public class UiAutomationServiceImpl implements IUiAutomationService {
|
||||
uiHighSetting.setCreateBy(SecurityUtils.getUsername());
|
||||
uiHighSetting.setCreateTime(DateUtils.getNowDate());
|
||||
try {
|
||||
List<DataExtractionQO> combinedList1 = new ArrayList<>();
|
||||
combinedList1.addAll(uiHighSettingQO.getDataExtractionQOList().getWindowExtractions());
|
||||
combinedList1.addAll(uiHighSettingQO.getDataExtractionQOList().getElementExtractions());
|
||||
//数据提取
|
||||
String jsonStr = objectMapper.writeValueAsString(uiHighSettingQO.getDataExtractionQOList());
|
||||
String jsonStr = objectMapper.writeValueAsString(combinedList1);
|
||||
if (jsonStr != null) {
|
||||
uiHighSetting.setExtractionDataJson(jsonStr);
|
||||
}
|
||||
//断言
|
||||
jsonStr = objectMapper.writeValueAsString(uiHighSettingQO.getAssertionQOList());
|
||||
List<AssertionQO> combinedList2 = new ArrayList<>();
|
||||
combinedList2.addAll(uiHighSettingQO.getAssertionQOList().getPopupTexts());
|
||||
combinedList2.addAll(uiHighSettingQO.getAssertionQOList().getElementAssertions());
|
||||
combinedList2.addAll(uiHighSettingQO.getAssertionQOList().getDropdownBoxes());
|
||||
combinedList2.addAll(uiHighSettingQO.getAssertionQOList().getWebTitles());
|
||||
jsonStr = objectMapper.writeValueAsString(combinedList2);
|
||||
if (jsonStr != null) {
|
||||
uiHighSetting.setAssertionJson(jsonStr);
|
||||
}
|
||||
//其他设置
|
||||
if (uiHighSettingQO.getWaitElementTime() != null || uiHighSettingQO.getScreenshotConfiguration() != null) {
|
||||
OtherSettingsQO settings = new OtherSettingsQO();
|
||||
settings.setWaitElementTime(uiHighSettingQO.getWaitElementTime());
|
||||
settings.setScreenshotConfiguration(uiHighSettingQO.getScreenshotConfiguration());
|
||||
jsonStr = objectMapper.writeValueAsString(settings);
|
||||
if (uiHighSettingQO.getOtherSettingsQO()!=null) {
|
||||
jsonStr = objectMapper.writeValueAsString(uiHighSettingQO.getOtherSettingsQO());
|
||||
uiHighSetting.setOtherSetting(jsonStr);
|
||||
}
|
||||
} catch (JsonProcessingException e) {
|
||||
|
||||
@@ -95,7 +95,7 @@ public class UiReportServiceImpl implements IUiReportService
|
||||
UiAutomation automation = uiAutomationMapper.selectUiAutomationById(automationId);
|
||||
String name = automation.getName();
|
||||
UiReport uiReport = new UiReport();
|
||||
uiReport.setName(name + "-" + DateUtils.getTime());
|
||||
uiReport.setName(name + "-" + DateUtils.formatDateTime(startTime));
|
||||
uiReport.setReportType("场景");
|
||||
uiReport.setCreateTime(startTime);
|
||||
uiReport.setCreateBy(SecurityUtils.getUsername());
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
package com.test.test.service.impl;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.test.common.config.TestConfig;
|
||||
import com.test.common.utils.DateUtils;
|
||||
import com.test.common.utils.SecurityUtils;
|
||||
import com.test.common.utils.SeleniumUtils;
|
||||
import com.test.common.utils.StringUtils;
|
||||
import com.test.test.domain.*;
|
||||
import com.test.test.domain.qo.OtherSettingsQO;
|
||||
import com.test.test.domain.qo.*;
|
||||
import com.test.test.domain.vo.AssertionReportVO;
|
||||
import com.test.test.domain.vo.UiHighSettingVO;
|
||||
import com.test.test.mapper.UiAutomationMapper;
|
||||
import com.test.test.mapper.UiSceneStepsMapper;
|
||||
@@ -18,10 +25,10 @@ import com.test.test.service.*;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.checkerframework.checker.units.qual.C;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.openqa.selenium.*;
|
||||
import org.openqa.selenium.chrome.ChromeDriver;
|
||||
import org.openqa.selenium.support.ui.Select;
|
||||
import org.openqa.selenium.support.ui.UnexpectedTagNameException;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -56,10 +63,13 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
* @param automationId
|
||||
* @return
|
||||
*/
|
||||
public Map<String, Object> executeStep(Long automationId) {
|
||||
public Map<String, Object> executeStep(Long automationId,String triggerMode) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("msg", "");
|
||||
result.put("id", 0L);
|
||||
AtomicInteger totalAssertions = new AtomicInteger(0);
|
||||
AtomicInteger successAssertions = new AtomicInteger(0);
|
||||
Gson gson = new Gson();
|
||||
// 1. 验证并获取步骤
|
||||
List<UiSceneSteps> steps = validateAndGetSteps(automationId);
|
||||
|
||||
@@ -73,7 +83,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
|
||||
Date startTime = DateUtils.getNowDate();
|
||||
// 2. 创建执行报告
|
||||
Long reportId = uiReportService.insertUiReport(startTime, automationId, "1", steps.size());
|
||||
Long reportId = uiReportService.insertUiReport(startTime, automationId, triggerMode, steps.size());
|
||||
UiReport uiReport = new UiReport();
|
||||
result.put("id", reportId);
|
||||
uiReport.setId(reportId);
|
||||
@@ -120,6 +130,24 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
} else if (report.getExecutionFlag().equals("0")) {
|
||||
stepsNotNumber++;
|
||||
}
|
||||
//成功断言数
|
||||
String assertionJson = report.getAssertionJson();
|
||||
if (assertionJson != null && !assertionJson.trim().isEmpty()) {
|
||||
try {
|
||||
List<AssertionReportVO> assertions = gson.fromJson(
|
||||
assertionJson,
|
||||
new TypeToken<List<AssertionReportVO>>(){}.getType()
|
||||
);
|
||||
int stepAssertionCount = assertions.size();
|
||||
int stepSuccessCount = (int) assertions.stream()
|
||||
.filter(a -> "1".equals(a.getIsSuccess()))
|
||||
.count();
|
||||
totalAssertions.addAndGet(stepAssertionCount);
|
||||
successAssertions.addAndGet(stepSuccessCount);
|
||||
} catch (Exception e) {
|
||||
log.error("步骤[{}]断言数据解析失败: {}", report.getId(), assertionJson, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allSuccess) {
|
||||
scenesSucceedNumber = 1;
|
||||
@@ -127,6 +155,10 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
scenesErrorNumber = 1;
|
||||
}
|
||||
}
|
||||
uiReport.setSuccessAssertion("0/0");
|
||||
String globalAssertionResult = successAssertions.get() + "/" + totalAssertions.get();
|
||||
uiReport.setSuccessAssertion(globalAssertionResult);
|
||||
|
||||
uiReport.setScenesSucceedNumber(scenesSucceedNumber);
|
||||
uiReport.setScenesErrorNumber(scenesErrorNumber);
|
||||
uiReport.setScenesNotNumber(0);
|
||||
@@ -136,6 +168,8 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
uiReport.setFaiiRate(
|
||||
stepsErrorNumber == 0 ? "0%" :
|
||||
String.format("%.2f%%", (double) stepsErrorNumber / steps.size() * 100)
|
||||
|
||||
|
||||
);
|
||||
uiReportService.updateUiReport(uiReport);
|
||||
|
||||
@@ -214,6 +248,8 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
List<UiHighSettingVO> uiHighSettingVOList = uiAutomationService.getUiHighSettingVOList(step.getId());
|
||||
executeSingleStep(step, seleniumUtils, uiSceneStepsReports.get(0).getId(), uiHighSettingVOList);
|
||||
}
|
||||
//关闭浏览器
|
||||
seleniumUtils.quit();
|
||||
}
|
||||
|
||||
private void executeSingleStep(UiSceneSteps step, SeleniumUtils seleniumUtils,
|
||||
@@ -263,6 +299,8 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
boolean shouldContinue = executeStepWithLog(step, seleniumUtils, sceneStepsReportId,
|
||||
execution, uiHighSettingVOList);
|
||||
if (!shouldContinue) {
|
||||
//关闭浏览器
|
||||
seleniumUtils.quit();
|
||||
throw new IllegalArgumentException("步骤执行失败,根据设置终止场景执行");
|
||||
}
|
||||
}
|
||||
@@ -285,20 +323,29 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
UiHighSettingVO errorSetting = extractErrorSetting(uiHighSettingVOList);
|
||||
UiHighSettingVO otherSetting = extractOtherSetting(uiHighSettingVOList);
|
||||
OtherSettingsQO otherSettingsQO = otherSetting.getOtherSettingsQO();
|
||||
Integer screenshotConfiguration = otherSettingsQO.getScreenshotConfiguration(); //是否截图 1当前步骤截图 2异常截图 3 不截图
|
||||
//等待元素超时时间
|
||||
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);
|
||||
Integer screenshotConfiguration = 0;
|
||||
if (otherSettingsQO != null) {
|
||||
screenshotConfiguration = otherSettingsQO.getScreenshotConfiguration() == null ? 0 : otherSettingsQO.getScreenshotConfiguration();
|
||||
//等待元素超时时间
|
||||
Integer waitElementTime = otherSettingsQO.getWaitElementTime() == null ? -1 : otherSettingsQO.getWaitElementTime();
|
||||
if (waitElementTime > 0) {
|
||||
// 转换为秒(至少1秒)
|
||||
long timeoutInSeconds = Math.max(1, waitElementTime / 1000);
|
||||
log.info("元素等待时间{}秒", timeoutInSeconds);
|
||||
seleniumUtils.setWaitTimeout(timeoutInSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//前置操作设置
|
||||
List<UiHighSettingVO> beforeSettingList = extractbeforeSetting(uiHighSettingVOList);
|
||||
// 获取前置操作数据集合(判空)
|
||||
Map<String, Object> beforeData = CollectionUtils.isEmpty(beforeSettingList)
|
||||
? new HashMap<>()
|
||||
: filterBydataExtractionQOList(beforeSettingList, seleniumUtils);
|
||||
//后置操作设置
|
||||
List<UiHighSettingVO> afterSettingList = extractafterSetting(uiHighSettingVOList);
|
||||
|
||||
//前置等待时间
|
||||
int beforeAwaitTime = getAwaitTime(beforeSettingList);
|
||||
//后置等待时间
|
||||
@@ -328,7 +375,6 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
log.info("执行后置等待: {}ms", afterAwaitTime);
|
||||
Thread.sleep(afterAwaitTime);
|
||||
}
|
||||
|
||||
report.setLogInfo("OK");
|
||||
report.setExecutionFlag("1");
|
||||
} catch (Exception e) {
|
||||
@@ -345,18 +391,50 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
}
|
||||
log.error("步骤执行失败: {}", e.getMessage());
|
||||
} finally {
|
||||
//获取后置操作数据集合
|
||||
Map<String, Object> afterData = CollectionUtils.isEmpty(afterSettingList)
|
||||
? new HashMap<>()
|
||||
: filterBydataExtractionQOList(afterSettingList, seleniumUtils);
|
||||
Map<String, Object> mergedData = new HashMap<>();
|
||||
if (!beforeData.isEmpty()) {
|
||||
mergedData.put("前置数据提取", beforeData);
|
||||
}
|
||||
if (!afterData.isEmpty()) {
|
||||
mergedData.put("后置数据提取", afterData);
|
||||
}
|
||||
// 设置到报告
|
||||
try {
|
||||
String json = mergedData.isEmpty() ? null : new ObjectMapper().writeValueAsString(mergedData);
|
||||
report.setExtractionDataJson(json);
|
||||
} catch (JsonProcessingException e) {
|
||||
report.setExtractionDataJson("JsonProcessingException error");
|
||||
}
|
||||
Map<String, Object> stringObjectMap = filterByAssertionQOList(afterSettingList, seleniumUtils);
|
||||
//断言失败是否终止
|
||||
String continueExecution1 = (String) stringObjectMap.get("continueExecution");
|
||||
if (continueExecution1.equals("1")){
|
||||
continueExecution = false;
|
||||
report.setLogInfo("");
|
||||
report.setExecutionFlag("2");
|
||||
}
|
||||
List<AssertionReportVO> assertionReportVOS = (List<AssertionReportVO>) stringObjectMap.get("assertionReportVOS");
|
||||
Gson gson = new Gson();
|
||||
report.setAssertionJson(assertionReportVOS.isEmpty() ? null : gson.toJson(assertionReportVOS));
|
||||
endTime = DateUtils.getNowDate();
|
||||
// 更新报告
|
||||
report.setCreateTime(startTime);
|
||||
report.setUpdateTime(endTime);
|
||||
report.setTake(DateUtils.differenceInMilliseconds(startTime, endTime) + "ms");
|
||||
uiSceneStepsReportMapper.updateUiSceneStepsReport(report);
|
||||
|
||||
}
|
||||
|
||||
return continueExecution;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 提取前置操作
|
||||
*
|
||||
@@ -369,6 +447,505 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
.collect(Collectors.toList()); // 返回默认设置
|
||||
}
|
||||
|
||||
/**
|
||||
* 断言
|
||||
* @param settingList
|
||||
* @param seleniumUtils
|
||||
* @return
|
||||
*/
|
||||
public Map<String, Object> filterByAssertionQOList(List<UiHighSettingVO> settingList, SeleniumUtils seleniumUtils) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
String continueExecution = "2";
|
||||
List<AssertionReportVO> assertionReports = new ArrayList<>();
|
||||
|
||||
result.put("continueExecution", continueExecution);
|
||||
result.put("assertionReportVOS", assertionReports);
|
||||
List<UiHighSettingVO> uiHighSettingVOS = settingList.stream()
|
||||
.filter(setting -> setting.getOperateType().equals("2") && 0 == setting.getIsDisabled())
|
||||
.toList();
|
||||
|
||||
if (CollectionUtils.isEmpty(uiHighSettingVOS)) {
|
||||
return result;
|
||||
}
|
||||
for (UiHighSettingVO uiHighSettingVO : uiHighSettingVOS) {
|
||||
AssertionConfigQO assertion = uiHighSettingVO.getAssertionQOList();
|
||||
List<AssertionQO> assertionQOList = new ArrayList<>();
|
||||
assertionQOList.addAll(assertion.getPopupTexts());
|
||||
assertionQOList.addAll(assertion.getElementAssertions());
|
||||
assertionQOList.addAll(assertion.getDropdownBoxes());
|
||||
assertionQOList.addAll(assertion.getWebTitles());
|
||||
if (!CollectionUtils.isEmpty(assertionQOList)) {
|
||||
for (AssertionQO assertionQO : assertionQOList) {
|
||||
if ("1".equals(assertionQO.getIsDisabled())) {
|
||||
continue;
|
||||
}
|
||||
AssertionReportVO report = new AssertionReportVO();
|
||||
report.setName("1".equals(assertionQO.getIsFailedAbort())?"assert":"verify");
|
||||
report.setIsSuccess("1"); // 默认成功
|
||||
|
||||
try {
|
||||
boolean assertionResult = false;
|
||||
String errorDetail = "";
|
||||
|
||||
switch (assertionQO.getAssertionType()) {
|
||||
case "1": // 弹窗文本断言
|
||||
assertionResult = handleAlertAssertion(assertionQO, seleniumUtils, report);
|
||||
break;
|
||||
case "2": // 元素断言
|
||||
assertionResult = handleElementAssertion(assertionQO, seleniumUtils, report);
|
||||
break;
|
||||
case "3": // 下拉框断言
|
||||
assertionResult = handleDropdownAssertion(assertionQO, seleniumUtils, report);
|
||||
break;
|
||||
case "4": // 网页标题断言
|
||||
assertionResult = handleTitleAssertion(assertionQO, seleniumUtils, report);
|
||||
break;
|
||||
default:
|
||||
errorDetail = "不支持的断言类型: " + assertionQO.getAssertionType();
|
||||
report.setErrorInfo(errorDetail);
|
||||
report.setIsSuccess("0");
|
||||
}
|
||||
|
||||
if (!assertionResult && "1".equals(assertionQO.getIsFailedAbort())) {
|
||||
continueExecution = "1";
|
||||
result.put("continueExecution", continueExecution);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
report.setErrorInfo("断言执行异常: " + e.getMessage());
|
||||
report.setIsSuccess("0");
|
||||
log.error("断言执行异常", e);
|
||||
}
|
||||
|
||||
assertionReports.add(report);
|
||||
}
|
||||
}
|
||||
}
|
||||
result.put("assertionReportVOS", assertionReports);
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean handleAlertAssertion(AssertionQO assertionQO,
|
||||
SeleniumUtils seleniumUtils,
|
||||
AssertionReportVO report) {
|
||||
try {
|
||||
// 1. 获取弹窗文本(带10秒等待)
|
||||
String actualText = seleniumUtils.getAlertText();
|
||||
String expectedText = assertionQO.getExpectations();
|
||||
report.setErrorInfo("");
|
||||
// 3. 文本比较
|
||||
if (!actualText.equals(expectedText)) {
|
||||
report.setErrorInfo(String.format(
|
||||
"弹窗文本不匹配,实际值:'%s',期望值:'%s'",
|
||||
actualText, expectedText
|
||||
));
|
||||
report.setIsSuccess("0");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4. 根据配置处理弹窗
|
||||
if ("1".equals(assertionQO.getIsPopText())) {
|
||||
seleniumUtils.acceptAlert(); // 点击确认
|
||||
log.info("弹窗断言成功,已点击确认");
|
||||
} else {
|
||||
log.info("弹窗断言成功,未执行点击操作");
|
||||
}
|
||||
report.setIsSuccess("1");
|
||||
return true;
|
||||
|
||||
} catch (NoAlertPresentException e) {
|
||||
report.setErrorInfo("弹窗未出现:" + e.getMessage());
|
||||
report.setIsSuccess("0");
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
report.setErrorInfo("弹窗处理异常:" + e.getMessage());
|
||||
report.setIsSuccess("0");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理元素断言
|
||||
* @param assertionQO 断言配置
|
||||
* @param seleniumUtils Selenium工具类
|
||||
* @param report 断言报告
|
||||
* @return 断言是否成功
|
||||
*/
|
||||
private boolean handleElementAssertion(AssertionQO assertionQO,
|
||||
SeleniumUtils seleniumUtils,
|
||||
AssertionReportVO report) {
|
||||
WebElement element = null;
|
||||
String locatorDescription = "";
|
||||
report.setErrorInfo("");
|
||||
try {
|
||||
// 1. 获取元素定位信息
|
||||
if ("1".equals(assertionQO.getOperateObject())) {
|
||||
// 从数据库查询元素信息
|
||||
//元素定位
|
||||
UiElement uiElement = uiElementService.selectUiElementById(assertionQO.getOperateElementId());
|
||||
if (uiElement == null) {
|
||||
report.setErrorInfo("元素ID " + assertionQO.getOperateElementId() + " 不存在");
|
||||
report.setIsSuccess("0");
|
||||
return false;
|
||||
}
|
||||
element = seleniumUtils.findElement(uiElement.getLocType(), uiElement.getElementLoc());
|
||||
locatorDescription = String.format("元素ID:%d (%s=%s)",
|
||||
assertionQO.getOperateElementId(),
|
||||
uiElement.getLocType(),
|
||||
uiElement.getElementLoc());
|
||||
} else if ("2".equals(assertionQO.getOperateObject())) {
|
||||
// 直接使用配置的定位信息
|
||||
element = seleniumUtils.findElement(
|
||||
assertionQO.getOperateLocType(),
|
||||
assertionQO.getOperateLocValue()
|
||||
);
|
||||
locatorDescription = String.format("直接定位 (%s=%s)",
|
||||
assertionQO.getOperateLocType(),
|
||||
assertionQO.getOperateLocValue());
|
||||
}
|
||||
// 3. 执行断言
|
||||
boolean result = false;
|
||||
String actualValue = "";
|
||||
String expectedValue = assertionQO.getExpectations();
|
||||
|
||||
switch (assertionQO.getAssertionMode()) {
|
||||
case "1": // 元素被选中(Checked)
|
||||
actualValue = String.valueOf(element.isSelected());
|
||||
result = element.isSelected();
|
||||
if (!result) {
|
||||
report.setErrorInfo(locatorDescription + " 未被选中");
|
||||
}
|
||||
break;
|
||||
|
||||
case "2": // 元素可编辑(Editable)
|
||||
actualValue = String.valueOf(element.isEnabled());
|
||||
result = element.isEnabled();
|
||||
if (!result) {
|
||||
report.setErrorInfo(locatorDescription + " 不可编辑");
|
||||
}
|
||||
break;
|
||||
|
||||
case "3": // 元素存在(ElementPresent)
|
||||
result = true; // 如果能找到元素,说明存在
|
||||
break;
|
||||
|
||||
case "4": // 元素不存在(ElementNotPresent)
|
||||
report.setErrorInfo("元素存在性断言应使用其他方式实现");
|
||||
return false;
|
||||
|
||||
case "5": // 元素未被选中(NotChecked)
|
||||
actualValue = String.valueOf(element.isSelected());
|
||||
result = !element.isSelected();
|
||||
if (!result) {
|
||||
report.setErrorInfo(locatorDescription + " 已被选中");
|
||||
}
|
||||
break;
|
||||
|
||||
case "6": // 元素不可编辑(NotEditable)
|
||||
actualValue = String.valueOf(element.isEnabled());
|
||||
result = !element.isEnabled();
|
||||
if (!result) {
|
||||
report.setErrorInfo(locatorDescription + " 可编辑");
|
||||
}
|
||||
break;
|
||||
|
||||
case "7": // 元素文本不等于期望(NotText)
|
||||
actualValue = element.getText();
|
||||
result = !actualValue.equals(expectedValue);
|
||||
if (!result) {
|
||||
report.setErrorInfo(String.format(
|
||||
"%s 文本等于期望值(实际:'%s',期望不等于:'%s')",
|
||||
locatorDescription, actualValue, expectedValue
|
||||
));
|
||||
}
|
||||
break;
|
||||
|
||||
case "8": // 元素文本等于期望(Text)
|
||||
actualValue = element.getText();
|
||||
result = actualValue.equals(expectedValue);
|
||||
if (!result) {
|
||||
report.setErrorInfo(String.format(
|
||||
"%s 文本不等于期望值(实际:'%s',期望:'%s')",
|
||||
locatorDescription, actualValue, expectedValue
|
||||
));
|
||||
}
|
||||
break;
|
||||
|
||||
case "9": // 元素值等于期望(Value)
|
||||
actualValue = element.getAttribute("value");
|
||||
result = actualValue.equals(expectedValue);
|
||||
if (!result) {
|
||||
report.setErrorInfo(String.format(
|
||||
"%s 值不等于期望值(实际:'%s',期望:'%s')",
|
||||
locatorDescription, actualValue, expectedValue
|
||||
));
|
||||
}
|
||||
break;
|
||||
|
||||
case "10": // 元素文本包含期望(InText)
|
||||
actualValue = element.getText();
|
||||
result = actualValue.contains(expectedValue);
|
||||
if (!result) {
|
||||
report.setErrorInfo(String.format(
|
||||
"%s 文本不包含期望内容(实际:'%s',期望包含:'%s')",
|
||||
locatorDescription, actualValue, expectedValue
|
||||
));
|
||||
}
|
||||
break;
|
||||
|
||||
case "11": // 元素文本不包含期望(NotlnText)
|
||||
actualValue = element.getText();
|
||||
result = !actualValue.contains(expectedValue);
|
||||
if (!result) {
|
||||
report.setErrorInfo(String.format(
|
||||
"%s 文本包含不应出现的内容(实际:'%s',期望不包含:'%s')",
|
||||
locatorDescription, actualValue, expectedValue
|
||||
));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
report.setErrorInfo("不支持的断言方式: " + assertionQO.getAssertionMode());
|
||||
return false;
|
||||
}
|
||||
report.setIsSuccess(result ? "1" : "0");
|
||||
return result;
|
||||
} catch (NoSuchElementException e) {
|
||||
if ("3".equals(assertionQO.getAssertionMode())) {
|
||||
// 元素存在断言时,找不到元素应该返回false
|
||||
report.setErrorInfo(locatorDescription + " 不存在");
|
||||
report.setIsSuccess("0");
|
||||
return false;
|
||||
}
|
||||
report.setErrorInfo("元素定位失败: " + e.getMessage());
|
||||
report.setIsSuccess("0");
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
report.setErrorInfo("元素断言异常: " + e.getMessage());
|
||||
report.setIsSuccess("0");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理下拉框断言
|
||||
* @param assertionQO 断言配置
|
||||
* @param seleniumUtils Selenium工具类
|
||||
* @param report 断言报告
|
||||
* @return 断言是否成功
|
||||
*/
|
||||
private boolean handleDropdownAssertion(AssertionQO assertionQO,
|
||||
SeleniumUtils seleniumUtils,
|
||||
AssertionReportVO report) {
|
||||
WebElement dropdown = null;
|
||||
String locatorDescription = "";
|
||||
report.setErrorInfo("");
|
||||
try {
|
||||
// 1. 获取下拉框元素
|
||||
if ("1".equals(assertionQO.getOperateObject())) {
|
||||
UiElement uiElement = uiElementService.selectUiElementById(assertionQO.getOperateElementId());
|
||||
if (uiElement == null) {
|
||||
report.setErrorInfo("元素ID " + assertionQO.getOperateElementId() + " 不存在");
|
||||
report.setIsSuccess("0");
|
||||
return false;
|
||||
}
|
||||
dropdown = seleniumUtils.findElement(uiElement.getLocType(), uiElement.getElementLoc());
|
||||
locatorDescription = String.format("下拉框ID:%d (%s=%s)",
|
||||
assertionQO.getOperateElementId(),
|
||||
uiElement.getLocType(),
|
||||
uiElement.getElementLoc());
|
||||
} else {
|
||||
dropdown = seleniumUtils.findElement(
|
||||
assertionQO.getOperateLocType(),
|
||||
assertionQO.getOperateLocValue()
|
||||
);
|
||||
locatorDescription = String.format("下拉框 (%s=%s)",
|
||||
assertionQO.getOperateLocType(),
|
||||
assertionQO.getOperateLocValue());
|
||||
}
|
||||
// 2. 转换为Select对象
|
||||
Select select = new Select(dropdown);
|
||||
WebElement selectedOption = select.getFirstSelectedOption();
|
||||
String actualValue = selectedOption.getAttribute("value");
|
||||
String actualText = selectedOption.getText();
|
||||
String expectedValue = assertionQO.getExpectations();
|
||||
|
||||
// 4. 执行断言
|
||||
boolean result = false;
|
||||
switch (assertionQO.getAssertionMode()) {
|
||||
case "1": // 所选元素的值等于期望(SelectedValue)
|
||||
result = actualValue.equals(expectedValue);
|
||||
if (!result) {
|
||||
report.setErrorInfo(String.format(
|
||||
"下拉框选中值不匹配(实际:'%s',期望:'%s')",
|
||||
actualValue, expectedValue
|
||||
));
|
||||
}
|
||||
break;
|
||||
|
||||
case "2": // 下拉框选项显示的文本等于期望(SelectedLabel)
|
||||
result = actualText.equals(expectedValue);
|
||||
if (!result) {
|
||||
report.setErrorInfo(String.format(
|
||||
"下拉框选中文本不匹配(实际:'%s',期望:'%s')",
|
||||
actualText, expectedValue
|
||||
));
|
||||
}
|
||||
break;
|
||||
|
||||
case "3": // 所选元素的值不等于期望(NotSelectedValue)
|
||||
result = !actualValue.equals(expectedValue);
|
||||
if (!result) {
|
||||
report.setErrorInfo(String.format(
|
||||
"下拉框选中值不应匹配(实际:'%s',期望不等于:'%s')",
|
||||
actualValue, expectedValue
|
||||
));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
report.setErrorInfo("不支持的断言方式: " + assertionQO.getAssertionMode());
|
||||
return false;
|
||||
}
|
||||
|
||||
report.setIsSuccess(result ? "1" : "0");
|
||||
return result;
|
||||
} catch (NoSuchElementException e) {
|
||||
report.setErrorInfo("下拉框元素不存在: " + e.getMessage());
|
||||
report.setIsSuccess("0");
|
||||
return false;
|
||||
} catch (UnexpectedTagNameException e) {
|
||||
report.setErrorInfo("元素不是下拉框: " + e.getMessage());
|
||||
report.setIsSuccess("0");
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
report.setErrorInfo("下拉框断言异常: " + e.getMessage());
|
||||
report.setIsSuccess("0");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理网页标题断言
|
||||
* @param assertionQO 断言配置
|
||||
* @param seleniumUtils Selenium工具类
|
||||
* @param report 断言报告
|
||||
* @return 断言是否成功
|
||||
*/
|
||||
private boolean handleTitleAssertion(AssertionQO assertionQO,
|
||||
SeleniumUtils seleniumUtils,
|
||||
AssertionReportVO report) {
|
||||
try {
|
||||
// 1. 获取实际标题和期望标题
|
||||
String actualTitle = seleniumUtils.getTitle();
|
||||
String expectedTitle = assertionQO.getExpectations();
|
||||
report.setErrorInfo("");
|
||||
|
||||
// 3. 执行完全匹配比较
|
||||
boolean result = actualTitle.equals(expectedTitle);
|
||||
if (!result) {
|
||||
report.setErrorInfo(String.format(
|
||||
"网页标题不匹配(实际:'%s',期望:'%s')",
|
||||
actualTitle, expectedTitle
|
||||
));
|
||||
}
|
||||
report.setIsSuccess(result ? "1" : "0");
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
report.setErrorInfo("获取网页标题失败: " + e.getMessage());
|
||||
report.setIsSuccess("0");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据提取集合
|
||||
* @param settingList
|
||||
* @return
|
||||
*/
|
||||
public Map<String,Object> filterBydataExtractionQOList(List<UiHighSettingVO> settingList, SeleniumUtils seleniumUtils) {
|
||||
List<UiHighSettingVO> uiHighSettingVOS = settingList.stream()
|
||||
.filter(setting -> setting.getOperateType().equals("3") && setting.getIsDisabled() == 0)
|
||||
.toList();
|
||||
Map<String,Object> variableStorage = new HashMap<>();
|
||||
if (CollectionUtils.isEmpty(uiHighSettingVOS)) {
|
||||
return variableStorage;
|
||||
}
|
||||
for (UiHighSettingVO uiHighSettingVO : uiHighSettingVOS) {
|
||||
DataExtractionConfigQO dataExtractionQO = uiHighSettingVO.getDataExtractionQOList();
|
||||
List<DataExtractionQO> dataExtractionQOList = new ArrayList<>();
|
||||
dataExtractionQOList.addAll(dataExtractionQO.getElementExtractions());
|
||||
dataExtractionQOList.addAll(dataExtractionQO.getWindowExtractions());
|
||||
if (!CollectionUtils.isEmpty(dataExtractionQOList)) {
|
||||
for (DataExtractionQO extraction : dataExtractionQOList) {
|
||||
if ("1".equals(extraction.getIsDisabled())) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
String variableName = extraction.getValue();
|
||||
String extractedValue = extractData(extraction,seleniumUtils);
|
||||
variableStorage.put(variableName, extractedValue);
|
||||
log.info("Extracted '{}' = {}", variableName, extractedValue);
|
||||
} catch (NoSuchElementException e) {
|
||||
log.info("Extracted '" + extraction.getValue() + "' = NoSuchElementException");
|
||||
variableStorage.put(extraction.getValue(), "NoSuchElementException");
|
||||
} catch (Exception e) {
|
||||
log.error("Error extracting '" + extraction.getValue() + "': " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return variableStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数据提取集合具体实现
|
||||
* @param extraction
|
||||
* @param seleniumUtils
|
||||
* @return
|
||||
*/
|
||||
private String extractData(DataExtractionQO extraction,SeleniumUtils seleniumUtils) {
|
||||
if ("1".equals(extraction.getInformationType())) {
|
||||
return seleniumUtils.extractWindowInformation(extraction.getWindowType());
|
||||
} else if ("2".equals(extraction.getInformationType())) {
|
||||
WebElement element = null;
|
||||
String locType = "";
|
||||
String elementLoc = "";
|
||||
if ("1".equals(extraction.getOperateObject())) {
|
||||
//元素定位
|
||||
UiElement uiElement = uiElementService.selectUiElementById(extraction.getOperateElementId());
|
||||
if (uiElement == null) {
|
||||
return "";
|
||||
}
|
||||
locType = uiElement.getLocType(); //属性
|
||||
elementLoc = uiElement.getElementLoc();//值
|
||||
} else if ("2".equals(extraction.getOperateObject())) {
|
||||
locType = extraction.getOperateLocType(); //属性
|
||||
elementLoc = extraction.getOperateLocValue();//值
|
||||
}
|
||||
element = seleniumUtils.findElement(locType, elementLoc);
|
||||
switch (extraction.getElementType()) {
|
||||
case "1": // 普通对象
|
||||
return extraction.getElementAttribute(); // 直接返回属性值
|
||||
case "2": // 元素文本
|
||||
return element.getText();
|
||||
case "3": // 元素值
|
||||
return element.getAttribute("value");
|
||||
case "4": // 元素属性
|
||||
return element.getAttribute(extraction.getElementAttribute());
|
||||
case "5": // CSS属性
|
||||
return element.getCssValue(extraction.getElementAttribute());
|
||||
case "6": // 匹配 xpath 的元素数量(storeXpathCount)
|
||||
return String.valueOf(seleniumUtils.findElements(locType,elementLoc).size());
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取(前置//后置)等待时间
|
||||
*
|
||||
@@ -916,4 +1493,7 @@ public class UiSceneStepsServiceImpl implements IUiSceneStepsService {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user