Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
A
auto-test
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
黄承天
auto-test
Commits
87aa25c9
提交
87aa25c9
authored
5月 11, 2020
作者:
黄承天
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
增加可快速模式设置的机制 快速模式的是否已测过的判断为只对比元素的text内容
上级
5d9d76d0
显示空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
116 行增加
和
35 行删除
+116
-35
SeleniumExecutor.java
...java/com/zjty/autotest/service/impl/SeleniumExecutor.java
+112
-33
application.properties
src/main/resources/application.properties
+4
-2
没有找到文件。
src/main/java/com/zjty/autotest/service/impl/SeleniumExecutor.java
浏览文件 @
87aa25c9
...
...
@@ -8,10 +8,14 @@ import com.zjty.autotest.common.action.LabelType;
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.*
;
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.WebDriverUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
net.bytebuddy.build.HashCodeAndEqualsPlugin
;
import
org.apache.logging.log4j.util.Strings
;
import
org.jsoup.nodes.Element
;
import
org.openqa.selenium.*
;
...
...
@@ -34,7 +38,7 @@ import java.util.*;
import
java.util.function.Predicate
;
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
;
/**
...
...
@@ -51,6 +55,9 @@ public class SeleniumExecutor {
@Value
(
"${screenshot-path}"
)
private
String
screenshotPath
;
@Value
(
"${selenium.executor.fast-mode}"
)
private
Boolean
fastMode
;
private
WebDriver
driver
;
private
List
<
Input
>
inputs
=
Lists
.
newArrayList
();
...
...
@@ -61,9 +68,13 @@ public class SeleniumExecutor {
private
Set
<
ElementFeature
>
currentHistoryFeatures
=
Sets
.
newHashSet
();
private
Set
<
String
>
totalHistoryFeatures
=
Sets
.
newHashSet
();
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
;
...
...
@@ -80,6 +91,9 @@ public class SeleniumExecutor {
private
String
currentUrl
;
public
Report
execute
(
Project
project
)
{
historyUrls
.
clear
();
urlQueue
.
clear
();
clickElementQueue
.
clear
();
driver
=
WebDriverUtil
.
getWebDriver
(
project
.
getBrowser
());
driver
.
manage
().
window
().
maximize
();
webDriverWait
=
new
WebDriverWait
(
driver
,
waitTime
);
...
...
@@ -116,6 +130,7 @@ public class SeleniumExecutor {
historyUrls
.
add
(
currentUrl
);
log
.
info
(
"当前URL:{} "
,
currentUrl
);
boolean
connectAble
=
checkConnect
(
currentUrl
);
boolean
success
;
if
(
connectAble
)
{
//打开网页 记录响应时间
long
responseTime
=
load
(
currentUrl
);
...
...
@@ -129,14 +144,14 @@ public class SeleniumExecutor {
messages
.
add
(
error
);
}
//获取当前网页的所有元素并放入元素队列
log
.
info
(
"获取完毕...
共{}个元素..."
,
e
lementQueue
.
size
());
log
.
info
(
"获取完毕...
input共{}个元素...click共{}个元素..."
,
inputElementQueue
.
size
(),
clickE
lementQueue
.
size
());
//当前页面的历史元素记录重置
currentHistoryFeatures
.
clear
();
//开始遍历操作元素队列中的元素 返回各个元素测试信息
List
<
ElementDetail
>
elementDetails
=
traversal
();
measure
.
setElementDetails
(
elementDetails
);
//如果全部元素通过则是通过
Boolean
success
=
elementDetails
.
stream
()
success
=
isNull
(
error
)
&&
elementDetails
.
stream
()
.
filter
(
Objects:
:
nonNull
)
.
allMatch
(
ElementDetail:
:
getSuccess
);
//如果未通过 则提供截图
...
...
@@ -159,6 +174,7 @@ public class SeleniumExecutor {
measure
.
setMessage
(
message
.
toString
());
log
.
info
(
"遍历完毕..."
);
}
else
{
measure
.
setSuccess
(
false
);
measure
.
setMessage
(
"无法访问的URL;"
);
measure
.
setElementDetails
(
Lists
.
newArrayList
());
}
...
...
@@ -166,19 +182,32 @@ public class SeleniumExecutor {
return
measure
;
}
@SuppressWarnings
(
"Duplicates"
)
private
List
<
ElementDetail
>
traversal
()
{
List
<
ElementDetail
>
elementDetails
=
Lists
.
newArrayList
();
while
(!
e
lementQueue
.
isEmpty
())
{
ElementEntry
elementEntry
=
e
lementQueue
.
poll
();
while
(!
inputE
lementQueue
.
isEmpty
())
{
ElementEntry
elementEntry
=
inputE
lementQueue
.
poll
();
ElementFeature
feature
=
elementEntry
.
getFeature
();
if
(!
currentHistoryFeatures
.
contains
(
feature
))
{
if
(
isInput
(
feature
))
{
ElementDetail
elementDetail
=
act
(
elementEntry
,
INPUT
);
ElementDetail
elementDetail
=
actInput
(
elementEntry
);
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
))
{
elementDetails
.
add
(
elementDetail
);
}
}
}
else
{
ElementDetail
elementDetail
=
act
(
elementEntry
,
CLICK
);
if
(!
currentHistoryFeatures
.
contains
(
feature
))
{
ElementDetail
elementDetail
=
actClick
(
elementEntry
);
if
(!
isSkipped
(
elementDetail
))
{
elementDetails
.
add
(
elementDetail
);
}
...
...
@@ -188,7 +217,7 @@ public class SeleniumExecutor {
return
elementDetails
;
}
private
ElementDetail
act
(
ElementEntry
elementEntry
,
String
actType
)
{
private
ElementDetail
act
Input
(
ElementEntry
elementEntry
)
{
WebElement
element
=
elementEntry
.
getElement
();
ElementFeature
feature
=
elementEntry
.
getFeature
();
String
type
=
String
.
format
(
"<%s>%s"
,
feature
.
getTag
(),
feature
.
getText
());
...
...
@@ -202,18 +231,57 @@ public class SeleniumExecutor {
if
(
isEnabled
(
element
)
&&
isDisPlayed
(
element
))
{
log
.
info
(
"元素 ----- feature:[{}]"
,
feature
);
long
startTime
=
System
.
currentTimeMillis
();
if
(
Objects
.
equals
(
actType
,
INPUT
))
{
log
.
info
(
"input操作"
);
if
(!
inputs
.
isEmpty
())
{
Input
input
=
inputs
.
remove
(
0
);
Input
input
=
inputs
.
get
(
0
);
element
.
sendKeys
(
input
.
getValue
());
element
.
submit
();
inputs
.
remove
(
0
);
}
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操作"
);
actions
.
moveToElement
(
element
).
click
().
perform
();
success
=
true
;
}
long
endTime
=
System
.
currentTimeMillis
();
//响应时间
responseTime
=
endTime
-
startTime
;
...
...
@@ -267,6 +335,7 @@ public class SeleniumExecutor {
}
historyFeatures
.
add
(
feature
);
currentHistoryFeatures
.
add
(
feature
);
totalHistoryFeatures
.
add
(
feature
.
getText
());
return
new
ElementDetail
(
type
,
(
int
)
responseTime
,
success
,
message
);
}
...
...
@@ -274,6 +343,11 @@ public class SeleniumExecutor {
return
Objects
.
equals
(
elementDetail
.
getResponseTime
(),
-
1
)
&&
Objects
.
equals
(
elementDetail
.
getMessage
(),
Strings
.
EMPTY
);
}
/**
* 检查页面是否变化包括跳转或刷新 如果跳转则将新url加入队列
*
* @return 页面是否有变化 若有则原来的元素都已过期 需要重新获取元素
*/
private
Boolean
checkPage
()
{
boolean
urlChanged
=
checkURl
();
boolean
pageChanged
=
false
;
...
...
@@ -361,26 +435,24 @@ public class SeleniumExecutor {
}
private
void
getAllElements
()
{
elementQueue
.
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()));
clickElementQueue
.
clear
();
List
<
WebElement
>
webElements
=
webDriverWait
.
until
(
webDriver
->
driver
.
findElements
(
By
.
xpath
(
"//*"
)));
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
);
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
)
{
...
...
@@ -443,8 +515,7 @@ public class SeleniumExecutor {
List
<
LogEntry
>
entries
=
webDriverWait
.
until
(
webDriver
->
webDriver
.
manage
().
logs
().
get
(
LogType
.
BROWSER
).
getAll
());
return
analyseLogError
(
entries
.
stream
().
findFirst
().
orElse
(
null
));
}
catch
(
Exception
e
)
{
log
.
error
(
"出现异常:"
);
e
.
printStackTrace
();
log
.
error
(
"出现异常:checkJsError()"
+
e
);
return
null
;
}
}
...
...
@@ -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
)
{
boolean
connect
=
false
;
String
httpPrefix
=
"http"
;
...
...
src/main/resources/application.properties
浏览文件 @
87aa25c9
server.port
=
13500
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.password
=
root
spring.jpa.hibernate.ddl-auto
=
update
...
...
@@ -21,7 +21,9 @@ logging.file.path=./log
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-port
=
13500
selenium.executor.fast-mode
=
false
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论