提交 87aa25c9 authored 作者: 黄承天's avatar 黄承天

增加可快速模式设置的机制 快速模式的是否已测过的判断为只对比元素的text内容

上级 5d9d76d0
...@@ -8,10 +8,14 @@ import com.zjty.autotest.common.action.LabelType; ...@@ -8,10 +8,14 @@ import com.zjty.autotest.common.action.LabelType;
import com.zjty.autotest.pojo.report.ElementDetail; import com.zjty.autotest.pojo.report.ElementDetail;
import com.zjty.autotest.pojo.report.Measure; import com.zjty.autotest.pojo.report.Measure;
import com.zjty.autotest.pojo.report.Report; import com.zjty.autotest.pojo.report.Report;
import com.zjty.autotest.pojo.test.*; import com.zjty.autotest.pojo.test.ElementEntry;
import com.zjty.autotest.pojo.test.ElementFeature;
import com.zjty.autotest.pojo.test.Input;
import com.zjty.autotest.pojo.test.Project;
import com.zjty.autotest.util.FileUtil; import com.zjty.autotest.util.FileUtil;
import com.zjty.autotest.util.WebDriverUtil; import com.zjty.autotest.util.WebDriverUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import org.apache.logging.log4j.util.Strings; import org.apache.logging.log4j.util.Strings;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
import org.openqa.selenium.*; import org.openqa.selenium.*;
...@@ -34,7 +38,7 @@ import java.util.*; ...@@ -34,7 +38,7 @@ import java.util.*;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.zjty.autotest.common.action.Action.*; import static java.util.Objects.isNull;
import static java.util.Objects.nonNull; import static java.util.Objects.nonNull;
/** /**
...@@ -51,6 +55,9 @@ public class SeleniumExecutor { ...@@ -51,6 +55,9 @@ public class SeleniumExecutor {
@Value("${screenshot-path}") @Value("${screenshot-path}")
private String screenshotPath; private String screenshotPath;
@Value("${selenium.executor.fast-mode}")
private Boolean fastMode;
private WebDriver driver; private WebDriver driver;
private List<Input> inputs = Lists.newArrayList(); private List<Input> inputs = Lists.newArrayList();
...@@ -61,9 +68,13 @@ public class SeleniumExecutor { ...@@ -61,9 +68,13 @@ public class SeleniumExecutor {
private Set<ElementFeature> currentHistoryFeatures = Sets.newHashSet(); private Set<ElementFeature> currentHistoryFeatures = Sets.newHashSet();
private Set<String> totalHistoryFeatures = Sets.newHashSet();
private Queue<String> urlQueue = Queues.newLinkedBlockingQueue(); private Queue<String> urlQueue = Queues.newLinkedBlockingQueue();
private Queue<ElementEntry> elementQueue = Queues.newLinkedBlockingQueue(); private Queue<ElementEntry> clickElementQueue = Queues.newLinkedBlockingQueue();
private Queue<ElementEntry> inputElementQueue = Queues.newLinkedBlockingQueue();
private WebDriverWait webDriverWait; private WebDriverWait webDriverWait;
...@@ -80,6 +91,9 @@ public class SeleniumExecutor { ...@@ -80,6 +91,9 @@ public class SeleniumExecutor {
private String currentUrl; private String currentUrl;
public Report execute(Project project) { public Report execute(Project project) {
historyUrls.clear();
urlQueue.clear();
clickElementQueue.clear();
driver = WebDriverUtil.getWebDriver(project.getBrowser()); driver = WebDriverUtil.getWebDriver(project.getBrowser());
driver.manage().window().maximize(); driver.manage().window().maximize();
webDriverWait = new WebDriverWait(driver, waitTime); webDriverWait = new WebDriverWait(driver, waitTime);
...@@ -116,6 +130,7 @@ public class SeleniumExecutor { ...@@ -116,6 +130,7 @@ public class SeleniumExecutor {
historyUrls.add(currentUrl); historyUrls.add(currentUrl);
log.info("当前URL:{} ", currentUrl); log.info("当前URL:{} ", currentUrl);
boolean connectAble = checkConnect(currentUrl); boolean connectAble = checkConnect(currentUrl);
boolean success;
if (connectAble) { if (connectAble) {
//打开网页 记录响应时间 //打开网页 记录响应时间
long responseTime = load(currentUrl); long responseTime = load(currentUrl);
...@@ -129,14 +144,14 @@ public class SeleniumExecutor { ...@@ -129,14 +144,14 @@ public class SeleniumExecutor {
messages.add(error); messages.add(error);
} }
//获取当前网页的所有元素并放入元素队列 //获取当前网页的所有元素并放入元素队列
log.info("获取完毕...共{}个元素...", elementQueue.size()); log.info("获取完毕...input共{}个元素...click共{}个元素...", inputElementQueue.size(), clickElementQueue.size());
//当前页面的历史元素记录重置 //当前页面的历史元素记录重置
currentHistoryFeatures.clear(); currentHistoryFeatures.clear();
//开始遍历操作元素队列中的元素 返回各个元素测试信息 //开始遍历操作元素队列中的元素 返回各个元素测试信息
List<ElementDetail> elementDetails = traversal(); List<ElementDetail> elementDetails = traversal();
measure.setElementDetails(elementDetails); measure.setElementDetails(elementDetails);
//如果全部元素通过则是通过 //如果全部元素通过则是通过
Boolean success = elementDetails.stream() success = isNull(error) && elementDetails.stream()
.filter(Objects::nonNull) .filter(Objects::nonNull)
.allMatch(ElementDetail::getSuccess); .allMatch(ElementDetail::getSuccess);
//如果未通过 则提供截图 //如果未通过 则提供截图
...@@ -159,6 +174,7 @@ public class SeleniumExecutor { ...@@ -159,6 +174,7 @@ public class SeleniumExecutor {
measure.setMessage(message.toString()); measure.setMessage(message.toString());
log.info("遍历完毕..."); log.info("遍历完毕...");
} else { } else {
measure.setSuccess(false);
measure.setMessage("无法访问的URL;"); measure.setMessage("无法访问的URL;");
measure.setElementDetails(Lists.newArrayList()); measure.setElementDetails(Lists.newArrayList());
} }
...@@ -166,19 +182,32 @@ public class SeleniumExecutor { ...@@ -166,19 +182,32 @@ public class SeleniumExecutor {
return measure; return measure;
} }
@SuppressWarnings("Duplicates")
private List<ElementDetail> traversal() { private List<ElementDetail> traversal() {
List<ElementDetail> elementDetails = Lists.newArrayList(); List<ElementDetail> elementDetails = Lists.newArrayList();
while (!elementQueue.isEmpty()) { while (!inputElementQueue.isEmpty()) {
ElementEntry elementEntry = elementQueue.poll(); ElementEntry elementEntry = inputElementQueue.poll();
ElementFeature feature = elementEntry.getFeature(); ElementFeature feature = elementEntry.getFeature();
if (!currentHistoryFeatures.contains(feature)) { if (!currentHistoryFeatures.contains(feature)) {
if (isInput(feature)) { ElementDetail elementDetail = actInput(elementEntry);
ElementDetail elementDetail = act(elementEntry, INPUT); if (!isSkipped(elementDetail)) {
elementDetails.add(elementDetail);
}
}
}
while (!clickElementQueue.isEmpty()) {
ElementEntry elementEntry = clickElementQueue.poll();
ElementFeature feature = elementEntry.getFeature();
if (fastMode) {
if (!totalHistoryFeatures.contains(feature.getText())){
ElementDetail elementDetail = actClick(elementEntry);
if (!isSkipped(elementDetail)) { if (!isSkipped(elementDetail)) {
elementDetails.add(elementDetail); elementDetails.add(elementDetail);
} }
}
} else { } else {
ElementDetail elementDetail = act(elementEntry, CLICK); if (!currentHistoryFeatures.contains(feature)) {
ElementDetail elementDetail = actClick(elementEntry);
if (!isSkipped(elementDetail)) { if (!isSkipped(elementDetail)) {
elementDetails.add(elementDetail); elementDetails.add(elementDetail);
} }
...@@ -188,7 +217,7 @@ public class SeleniumExecutor { ...@@ -188,7 +217,7 @@ public class SeleniumExecutor {
return elementDetails; return elementDetails;
} }
private ElementDetail act(ElementEntry elementEntry, String actType) { private ElementDetail actInput(ElementEntry elementEntry) {
WebElement element = elementEntry.getElement(); WebElement element = elementEntry.getElement();
ElementFeature feature = elementEntry.getFeature(); ElementFeature feature = elementEntry.getFeature();
String type = String.format("<%s>%s", feature.getTag(), feature.getText()); String type = String.format("<%s>%s", feature.getTag(), feature.getText());
...@@ -202,18 +231,57 @@ public class SeleniumExecutor { ...@@ -202,18 +231,57 @@ public class SeleniumExecutor {
if (isEnabled(element) && isDisPlayed(element)) { if (isEnabled(element) && isDisPlayed(element)) {
log.info("元素 ----- feature:[{}]", feature); log.info("元素 ----- feature:[{}]", feature);
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
if (Objects.equals(actType, INPUT)) {
log.info("input操作"); log.info("input操作");
if (!inputs.isEmpty()) { if (!inputs.isEmpty()) {
Input input = inputs.remove(0); Input input = inputs.get(0);
element.sendKeys(input.getValue()); element.sendKeys(input.getValue());
element.submit();
inputs.remove(0);
} }
success = true; success = true;
} else if (Objects.equals(actType, CLICK)) { long endTime = System.currentTimeMillis();
//响应时间
responseTime = endTime - startTime;
//检查页面变化 有变化则重新读取URL和元素
boolean urlChanged = checkPage();
boolean elementStaled = ExpectedConditions.stalenessOf(element).apply(driver);
boolean pageChanged = urlChanged || elementStaled;
if (pageChanged) {
inputElementQueue.clear();
clickElementQueue.clear();
}
}
} catch (Exception e) {
message = "不可输入的元素";
success = false;
log.error("error:" + e);
}
if (nonNull(elementEntry.getFrame())) {
driver.switchTo().defaultContent();
}
historyFeatures.add(feature);
currentHistoryFeatures.add(feature);
totalHistoryFeatures.add(feature.getText());
return new ElementDetail(type, (int) responseTime, success, message);
}
private ElementDetail actClick(ElementEntry elementEntry) {
WebElement element = elementEntry.getElement();
ElementFeature feature = elementEntry.getFeature();
String type = String.format("<%s>%s", feature.getTag(), feature.getText());
String message = Strings.EMPTY;
long responseTime = -1L;
boolean success = false;
try {
if (nonNull(elementEntry.getFrame())) {
driver.switchTo().frame(elementEntry.getFrame());
}
if (isEnabled(element) && isDisPlayed(element)) {
log.info("元素 ----- feature:[{}]", feature);
long startTime = System.currentTimeMillis();
log.info("click操作"); log.info("click操作");
actions.moveToElement(element).click().perform(); actions.moveToElement(element).click().perform();
success = true; success = true;
}
long endTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis();
//响应时间 //响应时间
responseTime = endTime - startTime; responseTime = endTime - startTime;
...@@ -267,6 +335,7 @@ public class SeleniumExecutor { ...@@ -267,6 +335,7 @@ public class SeleniumExecutor {
} }
historyFeatures.add(feature); historyFeatures.add(feature);
currentHistoryFeatures.add(feature); currentHistoryFeatures.add(feature);
totalHistoryFeatures.add(feature.getText());
return new ElementDetail(type, (int) responseTime, success, message); return new ElementDetail(type, (int) responseTime, success, message);
} }
...@@ -274,6 +343,11 @@ public class SeleniumExecutor { ...@@ -274,6 +343,11 @@ public class SeleniumExecutor {
return Objects.equals(elementDetail.getResponseTime(), -1) && Objects.equals(elementDetail.getMessage(), Strings.EMPTY); return Objects.equals(elementDetail.getResponseTime(), -1) && Objects.equals(elementDetail.getMessage(), Strings.EMPTY);
} }
/**
* 检查页面是否变化包括跳转或刷新 如果跳转则将新url加入队列
*
* @return 页面是否有变化 若有则原来的元素都已过期 需要重新获取元素
*/
private Boolean checkPage() { private Boolean checkPage() {
boolean urlChanged = checkURl(); boolean urlChanged = checkURl();
boolean pageChanged = false; boolean pageChanged = false;
...@@ -361,26 +435,24 @@ public class SeleniumExecutor { ...@@ -361,26 +435,24 @@ public class SeleniumExecutor {
} }
private void getAllElements() { private void getAllElements() {
elementQueue.clear(); clickElementQueue.clear();
// List<WebElement> frames = webDriverWait.until(webDriver -> webDriver.findElements(By.tagName("iframe")));
// List<WebElement> webElements = webDriverWait.until(webDriver -> driver.findElements(By.xpath("//*")).stream().filter(element -> element.findElements(By.xpath("*")).isEmpty()).collect(Collectors.toList()));
List<WebElement> webElements = webDriverWait.until(webDriver -> driver.findElements(By.xpath("//*"))); List<WebElement> webElements = webDriverWait.until(webDriver -> driver.findElements(By.xpath("//*")));
for (WebElement webElement : webElements) { for (WebElement webElement : webElements) {
ElementFeature feature = toFeature(webElement); ElementFeature feature;
if (fastMode) {
feature = toFeatureFast(webElement);
} else {
feature = toFeature(webElement);
}
ElementEntry entry = new ElementEntry(feature, webElement, null); ElementEntry entry = new ElementEntry(feature, webElement, null);
elementQueue.add(entry); if (webElement.findElements(By.xpath(".//*")).isEmpty()) {
if (isInput(feature)) {
inputElementQueue.add(entry);
} else {
clickElementQueue.add(entry);
}
}
} }
// if (!frames.isEmpty()) {
// for (WebElement frame : frames) {
// List<WebElement> webElementsInFrame = webDriverWait.until(webDriver -> frame.findElements(By.xpath("//*")).stream().filter(element -> element.findElements(By.xpath("*")).isEmpty()).collect(Collectors.toList()));
// Queue<ElementEntry> queue = Queues.newLinkedBlockingQueue();
// for (WebElement webElement : webElementsInFrame) {
// ElementFeature feature = toFeature(webElement);
// ElementEntry entry = new ElementEntry(feature, webElement, frame);
// queue.add(entry);
// }
// }
// }
} }
private Boolean isInput(ElementFeature feature) { private Boolean isInput(ElementFeature feature) {
...@@ -443,8 +515,7 @@ public class SeleniumExecutor { ...@@ -443,8 +515,7 @@ public class SeleniumExecutor {
List<LogEntry> entries = webDriverWait.until(webDriver -> webDriver.manage().logs().get(LogType.BROWSER).getAll()); List<LogEntry> entries = webDriverWait.until(webDriver -> webDriver.manage().logs().get(LogType.BROWSER).getAll());
return analyseLogError(entries.stream().findFirst().orElse(null)); return analyseLogError(entries.stream().findFirst().orElse(null));
} catch (Exception e) { } catch (Exception e) {
log.error("出现异常:"); log.error("出现异常:checkJsError()" + e);
e.printStackTrace();
return null; return null;
} }
} }
...@@ -479,6 +550,14 @@ public class SeleniumExecutor { ...@@ -479,6 +550,14 @@ public class SeleniumExecutor {
); );
} }
private ElementFeature toFeatureFast(WebElement element) {
return new ElementFeature(
element.getTagName(),
element.getText(),
null
);
}
private Boolean checkConnect(String url) { private Boolean checkConnect(String url) {
boolean connect = false; boolean connect = false;
String httpPrefix = "http"; String httpPrefix = "http";
......
server.port=13500 server.port=13500
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://120.55.57.35:3306/automated_testing?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true&characterEncoding=utf-8 spring.datasource.url=jdbc:mysql://localhost:3306/automated_testing?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true&characterEncoding=utf-8
spring.datasource.username=root spring.datasource.username=root
spring.datasource.password=root spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update spring.jpa.hibernate.ddl-auto=update
...@@ -21,7 +21,9 @@ logging.file.path=./log ...@@ -21,7 +21,9 @@ logging.file.path=./log
screenshot-path=/home/tykj/hct/auto/image screenshot-path=/home/tykj/hct/auto/image
selenium.executor.wait-time=2 selenium.executor.wait-time=4
selenium.executor.screenshot.url-host=120.55.57.35 selenium.executor.screenshot.url-host=120.55.57.35
selenium.executor.screenshot.url-port=13500 selenium.executor.screenshot.url-port=13500
selenium.executor.fast-mode=false
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论