提交 ddfa4f29 authored 作者: 孙洁清's avatar 孙洁清

Merge branch 'master' of git.yfzx.zjtys.com.cn:hct/auto-test

package com.zjty.autotest.pojo.test;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.jsoup.nodes.Attributes;
import org.openqa.selenium.WebElement;
/**
* <p>Description : autotest
* <p>Date : 2020/3/26 16:25
* <p>@author : C
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ElementMapping {
Integer order;
WebElement webElement;
Attributes attributes;
}
package com.zjty.autotest.service.impl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Queues;
import com.google.common.collect.Sets;
import com.zjty.autotest.pojo.report.ElementDetail;
import com.zjty.autotest.pojo.report.Measure;
import com.zjty.autotest.pojo.report.Report;
import com.zjty.autotest.pojo.test.ElementMapping;
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.WebDriverUtil;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Attributes;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Sleeper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static com.zjty.autotest.common.action.LabelType.INPUT;
import static java.util.Objects.nonNull;
......@@ -46,16 +55,15 @@ public class SeleniumExecutor {
private Set<String> historyUrls = Sets.newHashSet();
private Set<Attributes> historyAttributes = Sets.newHashSet();
private Set<Attributes> currentHistoryAttributes = Sets.newHashSet();
private Queue<String> windowQueue = Queues.newLinkedBlockingDeque();
private Queue<String> urlQueue = Queues.newLinkedBlockingDeque();
private List<WebElement> elements = Lists.newArrayList();
/**
* 元素序号记录
*/
private Integer elementIndex;
private List<ElementMapping> elementMappings = Lists.newArrayList();
/**
* 当前进行的窗口页
......@@ -112,16 +120,19 @@ public class SeleniumExecutor {
currentSource = driver.getPageSource();
long endTime = System.currentTimeMillis();
Long responseTime = endTime - startTime;
sleep();
log.info("当前URL:{} 响应时间 {} ms 开始进行遍历...", currentUrl, responseTime);
log.info("剩余URL队列:{}", urlQueue);
log.info("正在获取当前网页所有元素...");
//获取当前网页的所有元素并放入元素队列
getAllElements(driver);
Map<Attributes, WebElement> elements = getAllElements(driver);
log.info("获取完毕...共{}个元素...", elements.size());
elements.forEach((attributes, element) -> System.out.println(attributes));
//元素序号重置
elementIndex = 0;
currentHistoryAttributes.clear();
//开始遍历操作元素队列中的元素 返回各个元素测试信息
List<ElementDetail> elementDetails = traversal();
List<ElementDetail> elementDetails = Lists.newArrayList();
traversal(elements, elementDetails);
//如果全部元素通过则是通过
Boolean success = elementDetails.stream().allMatch(ElementDetail::getSuccess);
//如果出错 则提供截图
......@@ -149,46 +160,79 @@ public class SeleniumExecutor {
return measure;
}
private List<ElementDetail> traversal() {
List<ElementDetail> elementDetails = Lists.newArrayList();
while (elementIndex < elements.size()) {
WebElement element = elements.get(elementIndex);
ElementDetail elementDetail = act(element);
elementIndex++;
boolean urlChanged = checkURl();
boolean sourceChanged = checkSource();
if (urlChanged) {
boolean newPage = !historyUrls.contains(driver.getCurrentUrl())
&& !Sets.newHashSet(urlQueue).contains(driver.getCurrentUrl())
&& sourceChanged;
if (newPage) {
log.info("检测到新url:{} 加入队列 ", driver.getCurrentUrl());
urlQueue.add(driver.getCurrentUrl());
urlQueue = queueDuplicateRemoval(urlQueue);
}
reload();
private void traversal(Map<Attributes, WebElement> elements, List<ElementDetail> elementDetails) {
elements = removeHistoryElements(elements);
for (Attributes attributes : elements.keySet()) {
WebElement element = elements.get(attributes);
if (!currentHistoryAttributes.contains(attributes) && isInputAble(element)) {
ElementDetail elementDetail = actInput(attributes, element);
elementDetails.add(elementDetail);
}
if (sourceChanged) {
reload();
}
for (Attributes attributes : elements.keySet()) {
WebElement element = elements.get(attributes);
if (!currentHistoryAttributes.contains(attributes) && isClickAble(element)) {
ElementDetail elementDetail = actClick(attributes, element);
boolean urlChanged = checkURl();
boolean sourceChanged = checkSource();
if (urlChanged) {
boolean newPage = !historyUrls.contains(driver.getCurrentUrl())
&& !Sets.newHashSet(urlQueue).contains(driver.getCurrentUrl())
&& sourceChanged;
if (newPage) {
log.info("检测到新url:{} 加入队列 ", driver.getCurrentUrl());
urlQueue.add(driver.getCurrentUrl());
urlQueue = queueDuplicateRemoval(urlQueue);
}
Map<Attributes, WebElement> reload = reload();
traversal(reload, elementDetails);
}
// if (sourceChanged) {
// Map<Attributes, WebElement> reload = reload();
// traversal(reload, elementDetails);
// }
elementDetails.add(elementDetail);
}
elementDetails.add(elementDetail);
}
return elementDetails;
// while (elementIndex < this.elements.size()) {
// WebElement element = this.elements.get(elementIndex);
// ElementDetail elementDetail = actClick(element,);
// elementIndex++;
// boolean urlChanged = checkURl();
// boolean sourceChanged = checkSource();
// if (urlChanged) {
// boolean newPage = !historyUrls.contains(driver.getCurrentUrl())
// && !Sets.newHashSet(urlQueue).contains(driver.getCurrentUrl())
// && sourceChanged;
// if (newPage) {
// log.info("检测到新url:{} 加入队列 ", driver.getCurrentUrl());
// urlQueue.add(driver.getCurrentUrl());
// urlQueue = queueDuplicateRemoval(urlQueue);
// }
// reload();
// }
// if (sourceChanged) {
// reload();
// }
// elementDetails.add(elementDetail);
// }
}
private ElementDetail act(WebElement element) {
String type = "";
private ElementDetail actInput(Attributes attributes, WebElement element) {
String type = element.getTagName();
String message = null;
Long responseTIme = 0L;
Long responseTIme = -1L;
boolean success = false;
try {
if (isEnabled(element)) {
log.info("操作第{}个元素 ------ text:[{}] ----- tag:[{}]", elementIndex + 1, element.getText(), element.getTagName());
if (isInputAble(element) && !inputs.isEmpty()) {
log.info("Input元素 ------ text:[{}] ----- tag:[{}] ---- attrs:[{}]", element.getText(), element.getTagName(), attributes);
long startTime = System.currentTimeMillis();
if (!inputs.isEmpty()) {
Input input = inputs.remove(0);
element.sendKeys(input.getValue());
}
element.click();
long endTime = System.currentTimeMillis();
Long responseTime = endTime - startTime;
success = true;
Alert alert = ExpectedConditions.alertIsPresent().apply(driver);
if (nonNull(alert)) {
......@@ -197,7 +241,43 @@ public class SeleniumExecutor {
success = false;
}
}
} catch (ElementNotInteractableException e) {
message = "异常的布局;";
success = false;
log.error("error:存在可操作范围之外的元素");
} catch (Exception e) {
message = "预料之外的异常:" + e.getMessage() + ";";
success = false;
log.error("error:" + e);
}
historyAttributes.add(attributes);
currentHistoryAttributes.add(attributes);
return new ElementDetail(
type,
responseTIme.intValue(),
success,
message
);
}
private ElementDetail actClick(Attributes attributes, WebElement element) {
String type = element.getTagName();
String message = null;
Long responseTIme = 0L;
boolean success = false;
try {
if (isEnabled(element)) {
log.info("Click 元素 ------ text:[{}] ----- tag:[{}] ---- attrs:[{}]", element.getText(), element.getTagName(), attributes);
element.click();
sleep();
success = true;
Alert alert = ExpectedConditions.alertIsPresent().apply(driver);
if (nonNull(alert)) {
message = "出现警告窗:" + alert.getText();
alert.accept();
success = false;
}
}
} catch (ElementNotInteractableException e) {
message = "异常的布局;";
success = false;
......@@ -207,6 +287,8 @@ public class SeleniumExecutor {
success = false;
log.error("error:" + e);
}
historyAttributes.add(attributes);
currentHistoryAttributes.add(attributes);
return new ElementDetail(
type,
responseTIme.intValue(),
......@@ -252,36 +334,49 @@ public class SeleniumExecutor {
}
}
private void reload() {
private Map<Attributes, WebElement> reload() {
driver.get(currentUrl);
sleep();
currentSource = driver.getPageSource();
getAllElements(driver);
return getAllElements(driver);
}
@SuppressWarnings("unused")
private void sleep() {
if (waitTime > 0) {
try {
Thread.sleep(waitTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Sleeper.SYSTEM_SLEEPER.sleep(Duration.ofSeconds(2L));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void getAllElements(WebDriver driver) {
elements.clear();
private Map<Attributes, WebElement> getAllElements(WebDriver driver) {
elementMappings.clear();
List<WebElement> webElements = Lists.newArrayList();
driver.findElements(By.xpath("*"))
.forEach(this::getSubElements);
.forEach(element -> getSubElements(element, webElements));
Document document = Jsoup.parse(driver.getPageSource());
List<Element> jElements = document.getAllElements().stream()
.filter(element -> element.childrenSize() == 0)
.collect(Collectors.toList());
Map<Attributes, WebElement> result = Maps.newHashMap();
for (int i = 0; i < webElements.size(); i++) {
WebElement webElement = webElements.get(i);
Element jElement = jElements.get(i);
if (elementMatch(webElement, jElement)) {
result.put(jElement.attributes(), webElement);
}
}
return result;
}
private void getSubElements(WebElement element) {
private void getSubElements(WebElement element, List<WebElement> elements) {
try {
List<WebElement> results = element.findElements(By.xpath("*"));
if (results.isEmpty()) {
elements.add(element);
} else {
results.forEach(this::getSubElements);
results.forEach(webElement -> getSubElements(webElement, elements));
}
} catch (StaleElementReferenceException ignored) {
}
......@@ -293,11 +388,19 @@ public class SeleniumExecutor {
@SuppressWarnings("unused")
private Boolean isClickAble(WebElement element) {
return nonNull(ExpectedConditions.elementToBeClickable(element).apply(driver));
try {
return nonNull(ExpectedConditions.elementToBeClickable(element).apply(driver));
} catch (Exception e){
return false;
}
}
private Boolean isEnabled(WebElement element) {
return nonNull(ExpectedConditions.elementToBeClickable(element).apply(driver));
try {
return nonNull(ExpectedConditions.elementToBeClickable(element).apply(driver));
} catch (Exception e){
return false;
}
}
private String alterUrlName(String fileName) {
......@@ -319,4 +422,41 @@ public class SeleniumExecutor {
FileUtil.output(bytes, FileUtil.WORK_PATH + "screenshots\\" + name + ".png");
}
private Boolean elementMatch(WebElement webElement, Element element) {
boolean attributesMatch = element.attributes().asList().stream()
.allMatch(attribute -> Objects.equals(attribute.getValue(), webElement.getAttribute(attribute.getKey())));
boolean tagMatch = Objects.equals(webElement.getTagName(), element.tagName());
boolean textMatch = Objects.equals(webElement.getText(), element.text());
if (element.attributes().isEmpty()) {
if (element.hasText()) {
return tagMatch && textMatch;
} else {
return tagMatch;
}
} else {
if (element.hasText()) {
return attributesMatch && tagMatch && textMatch;
} else {
return attributesMatch && tagMatch;
}
}
}
private Map<Attributes, WebElement> removeHistoryElements(Map<Attributes, WebElement> elements) {
Map<Attributes, WebElement> result = Maps.newHashMap(elements);
elements.forEach((attributes, element) -> {
if (historyAttributes.contains(attributes)) {
result.remove(attributes, element);
}
});
return result;
}
private void removeHistoryElements() {
elementMappings.forEach((elementMapping) -> {
if (historyAttributes.contains(elementMapping.getAttributes())) {
elementMappings.remove(elementMapping);
}
});
}
}
......@@ -9,18 +9,17 @@ import com.zjty.autotest.pojo.test.Project;
import com.zjty.autotest.service.impl.SeleniumExecutor;
import com.zjty.autotest.util.WebDriverUtil;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.boot.jaxb.SourceType;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Attributes;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.Sleeper;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
......@@ -35,8 +34,8 @@ class AutotestApplicationTests {
@Test
public void execute() throws InterruptedException {
List<Input> inputs = Lists.newArrayList();
inputs.add(new Input(null, null, null, "caozuoyuan"));
inputs.add(new Input(null, null, null, "caozuoyuan123"));
inputs.add(new Input(null, null, null, "caozuoyuan"));
String url = "http://192.168.1.244:8080/person/#/login";
Project project = new Project(
......@@ -57,18 +56,26 @@ class AutotestApplicationTests {
// Sleeper.SYSTEM_SLEEPER.sleep(Duration.ofSeconds(2));
// String source2 = driver.getPageSource();
// System.out.println(Objects.equals(source1,source2));
Report report = seleniumExecutor.execute(project);
for (Measure measure : report.getMeasures()) {
System.out.println(measure);
}
// Document document = Jsoup.parse(driver.getPageSource());
// List<Element> elements = document.getAllElements().stream()
// .filter(element -> element.childrenSize() == 0)
// .collect(Collectors.toList());
// for (Element element : elements) {
// System.out.println(element.attributes());
// System.out.println("==============================================");
// System.out.println(String.format("tag:%s text:%s attrs:%s",element.tagName(),element.text(),element.attributes()));
// }
}
private Boolean elementMatch(WebElement webElement, Attributes Attributes) {
return Attributes.asList().stream().allMatch(attribute -> Objects.equals(attribute.getValue(), webElement.getAttribute(attribute.getKey())));
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论