提交 94c58e3a authored 作者: 黄承天's avatar 黄承天

完成遍历测试执行类与方法

上级 e5dccc09
...@@ -101,6 +101,12 @@ ...@@ -101,6 +101,12 @@
<artifactId>selenium-java</artifactId> <artifactId>selenium-java</artifactId>
<version>4.0.0-alpha-4</version> <version>4.0.0-alpha-4</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.13.1</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
package com.zjty.autotest.pojo.report; package com.zjty.autotest.pojo.report;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/** /**
* <p>Description : autotest * <p>Description : autotest
* <p>Date : 2020/3/24 11:15 * <p>Date : 2020/3/24 11:15
* <p>@author : C * <p>@author : C
* 元素测试信息
*/ */
public class Detail { @Data
@AllArgsConstructor
@NoArgsConstructor
public class ElementDetail {
/** /**
* 元素类型 * 元素类型
...@@ -17,11 +25,6 @@ public class Detail { ...@@ -17,11 +25,6 @@ public class Detail {
*/ */
private Integer responseTime; private Integer responseTime;
/**
* 路径
*/
private String url;
/** /**
* 是否通过 * 是否通过
*/ */
...@@ -31,4 +34,5 @@ public class Detail { ...@@ -31,4 +34,5 @@ public class Detail {
* 信息(未通过理由) * 信息(未通过理由)
*/ */
private String message; private String message;
} }
...@@ -44,4 +44,8 @@ public class Measure { ...@@ -44,4 +44,8 @@ public class Measure {
*/ */
private String screenshot; private String screenshot;
/**
* 所有元素测试信息
*/
private List<ElementDetail> elementDetails;
} }
...@@ -3,7 +3,6 @@ package com.zjty.autotest.service; ...@@ -3,7 +3,6 @@ package com.zjty.autotest.service;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
@Service @Service
public class TransHelper { public class TransHelper {
......
...@@ -3,6 +3,7 @@ package com.zjty.autotest.service.impl; ...@@ -3,6 +3,7 @@ package com.zjty.autotest.service.impl;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Queues; import com.google.common.collect.Queues;
import com.google.common.collect.Sets; 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.Measure;
import com.zjty.autotest.pojo.report.Report; import com.zjty.autotest.pojo.report.Report;
import com.zjty.autotest.pojo.test.Input; import com.zjty.autotest.pojo.test.Input;
...@@ -11,15 +12,15 @@ import com.zjty.autotest.util.FileUtil; ...@@ -11,15 +12,15 @@ 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 org.openqa.selenium.*; import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate; import java.util.function.Predicate;
import static com.zjty.autotest.common.action.LabelType.*; import static com.zjty.autotest.common.action.LabelType.INPUT;
import static java.util.Objects.nonNull; import static java.util.Objects.nonNull;
/** /**
...@@ -66,8 +67,14 @@ public class SeleniumExecutor { ...@@ -66,8 +67,14 @@ public class SeleniumExecutor {
*/ */
private String currentUrl; private String currentUrl;
/**
* 当前测试url的源码
*/
private String currentSource;
public Report execute(Project project) { public Report execute(Project project) {
driver = WebDriverUtil.getWebDriver(project.getBrowser()); driver = WebDriverUtil.getWebDriver(project.getBrowser());
driver.manage().timeouts().pageLoadTimeout(2L, TimeUnit.SECONDS);
inputs = project.getInputs(); inputs = project.getInputs();
List<Measure> measures = Lists.newArrayList(); List<Measure> measures = Lists.newArrayList();
String os = ""; String os = "";
...@@ -102,111 +109,120 @@ public class SeleniumExecutor { ...@@ -102,111 +109,120 @@ public class SeleniumExecutor {
//打开网页 记录响应时间 //打开网页 记录响应时间
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
driver.get(currentUrl); driver.get(currentUrl);
currentSource = driver.getPageSource();
long endTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis();
Long responseTime = endTime - startTime; Long responseTime = endTime - startTime;
log.info("当前URL:{} 响应时间 {} ms 开始进行遍历...", currentUrl, responseTime); log.info("当前URL:{} 响应时间 {} ms 开始进行遍历...", currentUrl, responseTime);
log.info("剩余URL队列:{}", urlQueue);
log.info("正在获取当前网页所有元素..."); log.info("正在获取当前网页所有元素...");
//获取当前网页的所有元素并放入元素队列 //获取当前网页的所有元素并放入元素队列
getAllElements(driver); getAllElements(driver);
log.info("获取完毕...共{}个元素...", elements.size()); log.info("获取完毕...共{}个元素...", elements.size());
//元素序号重置 //元素序号重置
elementIndex = 0; elementIndex = 0;
//开始遍历操作元素队列中的元素 返回错误信息 //开始遍历操作元素队列中的元素 返回各个元素测试信息
String message = traversal(); List<ElementDetail> elementDetails = traversal();
//如果无错误信息则是通过 //如果全部元素通过则是通过
Boolean success = Objects.equals(message, ""); Boolean success = elementDetails.stream().allMatch(ElementDetail::getSuccess);
//如果出错 则提供截图 //如果出错 则提供截图
String screenshot = ""; String screenshot = null;
if (!success) { if (!success) {
String screenshotName = alterUrlName(currentUrl); String screenshotName = alterUrlName(currentUrl);
screenshot(screenshotName); screenshot(screenshotName);
screenshot = String.format("http://%s:%s/screenshots/%s", screenshotPrefixHost, screenshotPrefixPort, screenshotName); screenshot = String.format("http://%s:%s/screenshots/%s", screenshotPrefixHost, screenshotPrefixPort, screenshotName);
} }
//总合信息
HashSet<String> messages = Sets.newHashSet();
elementDetails.forEach(elementDetail -> messages.add(elementDetail.getMessage()));
StringBuilder message = new StringBuilder();
messages.forEach(message::append);
log.info("遍历完毕..."); log.info("遍历完毕...");
measure = new Measure( measure = new Measure(
currentUrl, currentUrl,
success, success,
responseTime.intValue(), responseTime.intValue(),
message, message.toString(),
screenshot screenshot,
elementDetails
); );
} }
return measure; return measure;
} }
private String traversal() { private List<ElementDetail> traversal() {
StringBuilder message = new StringBuilder(); List<ElementDetail> elementDetails = Lists.newArrayList();
while (elementIndex < elements.size()) { while (elementIndex < elements.size()) {
WebElement element = elements.get(elementIndex); WebElement element = elements.get(elementIndex);
String elementMsg = act(element); ElementDetail elementDetail = act(element);
if (nonNull(elementMsg)) { elementIndex++;
message.append(elementMsg); 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);
} }
return message.toString(); return elementDetails;
} }
private String act(WebElement element) { private ElementDetail act(WebElement element) {
String type = "";
String message = null; String message = null;
elementIndex++; Long responseTIme = 0L;
boolean success = false;
try { try {
if (isEnabledAndDisplayed(element)) { if (isEnabled(element)) {
log.info("操作第{}个元素 ------ text:[{}] ----- tag:[{}]", elementIndex + 1, element.getText(), element.getTagName()); log.info("操作第{}个元素 ------ text:[{}] ----- tag:[{}]", elementIndex + 1, element.getText(), element.getTagName());
if (isEnabledInput(element)) { if (isInputAble(element) && !inputs.isEmpty()) {
Input input = inputs.remove(0); Input input = inputs.remove(0);
element.sendKeys(input.getValue()); element.sendKeys(input.getValue());
} }
element.click(); element.click();
if (waitTime > 0) { success = true;
sleep(); Alert alert = ExpectedConditions.alertIsPresent().apply(driver);
}
//一旦页面发生过跳转 通过重新打开回到原来的页面后需要重新获取元素
Boolean pageChanged = checkPage();
if (pageChanged) {
reload();
traversal();
}
//警告窗口处理
Alert alert = getAlert();
if (nonNull(alert)) { if (nonNull(alert)) {
message = "出现警告窗:" + alert.getText(); message = "出现警告窗:" + alert.getText();
alert.accept(); alert.accept();
success = false;
} }
} else {
log.info("操作第{}个元素 ------ 该元素Enabled 跳过", elementIndex + 1);
} }
} catch (ElementNotInteractableException e) { } catch (ElementNotInteractableException e) {
message = "异常的布局;"; message = "异常的布局;";
log.error("error:在可操作范围之外的元素"); success = false;
} catch (TimeoutException ignored) { log.error("error:存在可操作范围之外的元素");
} catch (StaleElementReferenceException e) {
reload();
traversal();
} catch (Exception e) { } catch (Exception e) {
message = "预料之外的异常:" + e.getMessage() + ";"; message = "预料之外的异常:" + e.getMessage() + ";";
success = false;
log.error("error:" + e); log.error("error:" + e);
} }
return message; return new ElementDetail(
type,
responseTIme.intValue(),
success,
message
);
} }
private Boolean checkPage() { private Boolean checkURl() {
boolean pageChange = !Objects.equals( String practiseUrl = driver.getCurrentUrl();
currentUrl, return !Objects.equals(currentUrl, practiseUrl);
driver.getCurrentUrl() }
);
if (pageChange) { private Boolean checkSource() {
boolean newPage = !historyUrls.contains(driver.getCurrentUrl()); String practise = driver.getPageSource();
if (newPage) { return !Objects.equals(practise, currentSource);
urlQueue.add(driver.getCurrentUrl());
//去重防止重复添加
urlQueue = queueDuplicateRemoval(urlQueue);
driver.get(currentUrl);
}
return true;
} else {
return false;
}
} }
private Queue<String> queueDuplicateRemoval(Queue<String> queue) { private Queue<String> queueDuplicateRemoval(Queue<String> queue) {
...@@ -236,28 +252,20 @@ public class SeleniumExecutor { ...@@ -236,28 +252,20 @@ public class SeleniumExecutor {
} }
} }
private Alert getAlert() {
WebDriverWait wait = new WebDriverWait(driver, 4);
return wait.until((ExpectedCondition<Alert>) theDriver -> {
try {
return theDriver.switchTo().alert();
} catch (NoAlertPresentException e) {
return null;
}
});
}
private void reload() { private void reload() {
driver.get(currentUrl); driver.get(currentUrl);
currentSource = driver.getPageSource();
getAllElements(driver); getAllElements(driver);
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
private void sleep() { private void sleep() {
try { if (waitTime > 0) {
Thread.sleep(waitTime); try {
} catch (InterruptedException e) { Thread.sleep(waitTime);
e.printStackTrace(); } catch (InterruptedException e) {
e.printStackTrace();
}
} }
} }
...@@ -279,12 +287,17 @@ public class SeleniumExecutor { ...@@ -279,12 +287,17 @@ public class SeleniumExecutor {
} }
} }
private Boolean isEnabledInput(WebElement element) { private Boolean isInputAble(WebElement element) {
return Objects.equals(element.getTagName(), INPUT); return Objects.equals(element.getTagName(), INPUT);
} }
private Boolean isEnabledAndDisplayed(WebElement element) { @SuppressWarnings("unused")
return element.isEnabled() && element.isDisplayed(); private Boolean isClickAble(WebElement element) {
return nonNull(ExpectedConditions.elementToBeClickable(element).apply(driver));
}
private Boolean isEnabled(WebElement element) {
return nonNull(ExpectedConditions.elementToBeClickable(element).apply(driver));
} }
private String alterUrlName(String fileName) { private String alterUrlName(String fileName) {
......
...@@ -9,18 +9,21 @@ import com.zjty.autotest.pojo.test.Project; ...@@ -9,18 +9,21 @@ import com.zjty.autotest.pojo.test.Project;
import com.zjty.autotest.service.impl.SeleniumExecutor; import com.zjty.autotest.service.impl.SeleniumExecutor;
import com.zjty.autotest.util.WebDriverUtil; import com.zjty.autotest.util.WebDriverUtil;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.openqa.selenium.*; import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver; import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.logging.LogType; import org.openqa.selenium.support.ui.Sleeper;
import org.openqa.selenium.logging.LoggingPreferences;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import java.time.Duration;
import java.util.*; import java.util.*;
import java.util.logging.Level; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Slf4j @Slf4j
@SpringBootTest @SpringBootTest
...@@ -30,10 +33,10 @@ class AutotestApplicationTests { ...@@ -30,10 +33,10 @@ class AutotestApplicationTests {
SeleniumExecutor seleniumExecutor; SeleniumExecutor seleniumExecutor;
@Test @Test
public void execute() { public void execute() throws InterruptedException {
List<Input> inputs = Lists.newArrayList(); List<Input> inputs = Lists.newArrayList();
inputs.add(new Input(null,null,null,"caozuoyuan")); inputs.add(new Input(null, null, null, "caozuoyuan"));
inputs.add(new Input(null,null,null,"caozuoyuan123")); inputs.add(new Input(null, null, null, "caozuoyuan123"));
String url = "http://192.168.1.244:8080/person/#/login"; String url = "http://192.168.1.244:8080/person/#/login";
Project project = new Project( Project project = new Project(
...@@ -43,9 +46,29 @@ class AutotestApplicationTests { ...@@ -43,9 +46,29 @@ class AutotestApplicationTests {
url, url,
inputs inputs
); );
// String url2 = "file:///C:/code/wps/index.html";
// WebDriver driver = WebDriverUtil.getWebDriver("firefox");
// driver.manage().timeouts().pageLoadTimeout(4L, TimeUnit.SECONDS);
// driver.get(url);
// Sleeper.SYSTEM_SLEEPER.sleep(Duration.ofSeconds(2));
// String source1 = driver.getPageSource();
// driver.get(url2);
// driver.get(url);
// Sleeper.SYSTEM_SLEEPER.sleep(Duration.ofSeconds(2));
// String source2 = driver.getPageSource();
// System.out.println(Objects.equals(source1,source2));
Report report = seleniumExecutor.execute(project); Report report = seleniumExecutor.execute(project);
for (Measure measure : report.getMeasures()) { for (Measure measure : report.getMeasures()) {
System.out.println(measure); 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());
// }
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论