Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xm-uitest-sow
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xiamai-test
xm-uitest-sow
Commits
bc7dbb43
Commit
bc7dbb43
authored
Jun 18, 2021
by
linguangwei
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
登录-开课-结束课程-关闭客户端
parent
03c8c945
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
228 additions
and
59 deletions
+228
-59
.idea/inspectionProfiles/Project_Default.xml
+20
-0
.idea/workspace.xml
+0
-0
main.py
+2
-2
requirements.txt
+4
-2
src/framework/common.py
+106
-4
src/pageobject/basepage.py
+35
-4
src/pageobject/mainpage.py
+58
-45
src/testcase/testLoginPage.py
+3
-2
No files found.
.idea/inspectionProfiles/Project_Default.xml
0 → 100644
View file @
bc7dbb43
<component
name=
"InspectionProjectProfileManager"
>
<profile
version=
"1.0"
>
<option
name=
"myName"
value=
"Project Default"
/>
<inspection_tool
class=
"PyPep8NamingInspection"
enabled=
"true"
level=
"WEAK WARNING"
enabled_by_default=
"true"
>
<option
name=
"ignoredErrors"
>
<list>
<option
value=
"N806"
/>
</list>
</option>
</inspection_tool>
<inspection_tool
class=
"PyUnresolvedReferencesInspection"
enabled=
"true"
level=
"WARNING"
enabled_by_default=
"true"
>
<option
name=
"ignoredIdentifiers"
>
<list>
<option
value=
"requests.models.Response.__getitem__"
/>
</list>
</option>
</inspection_tool>
</profile>
</component>
\ No newline at end of file
.idea/workspace.xml
View file @
bc7dbb43
This diff is collapsed.
Click to expand it.
main.py
View file @
bc7dbb43
...
@@ -4,13 +4,13 @@ from src.framework.HTMLTestRunner import HTMLTestRunner
...
@@ -4,13 +4,13 @@ from src.framework.HTMLTestRunner import HTMLTestRunner
from
src.framework
import
common
from
src.framework
import
common
from
src.testcase.testLoginPage
import
TestLoginPage
as
TLP
from
src.testcase.testLoginPage
import
TestLoginPage
as
TLP
# from src.testcase.testHomePage import TestHomePage as TH
P
from
src.testcase.testMainPage
import
TestMainPage
as
TM
P
# from src.testcase.testWordPage import TestWordPage as TWP
# from src.testcase.testWordPage import TestWordPage as TWP
if
__name__
==
'__main__'
:
if
__name__
==
'__main__'
:
testunit
=
unittest
.
TestSuite
()
testunit
=
unittest
.
TestSuite
()
testunit
.
addTest
(
TLP
(
'testLogin'
))
testunit
.
addTest
(
TLP
(
'testLogin'
))
# testunit.addTests([THP('testHonors'), THP('testModifyPassword'), THP('testModifyInformation'), THP('testLogout'), THP('testWordTest
')])
testunit
.
addTests
([
TMP
(
'test_1_UnStartLive'
),
TMP
(
'test_2_StartLive'
),
TMP
(
'test_3_ReviewLive
'
)])
# testunit.addTests([TWP('testWordsEvaluation'), TWP('testWordReinforcement'), TWP('test_unit'), TWP('testOfflineDictation'), TWP('testPreview'), TWP('testShorthand'), TWP('testDictation'), TWP('testMemoryWrite'), TWP('testPostTest'), TWP('testReview'), TWP('testxiaoxiaole')])
# testunit.addTests([TWP('testWordsEvaluation'), TWP('testWordReinforcement'), TWP('test_unit'), TWP('testOfflineDictation'), TWP('testPreview'), TWP('testShorthand'), TWP('testDictation'), TWP('testMemoryWrite'), TWP('testPostTest'), TWP('testReview'), TWP('testxiaoxiaole')])
# 定义报告输出路径
# 定义报告输出路径
...
...
requirements.txt
View file @
bc7dbb43
selenium
==3.141.0
selenium
==3.141.0
pytest
==6.2.4
pytest
==6.2.4
\ No newline at end of file
Pillow
~=8.2.0
requests
~=2.25.1
\ No newline at end of file
src/framework/common.py
View file @
bc7dbb43
import
time
import
json
import
math
import
operator
import
os
import
os
import
random
import
string
import
time
from
functools
import
reduce
import
requests
from
PIL
import
Image
def
year_to_minute
():
def
year_to_minute
():
return
time
.
strftime
(
'
%
Y
%
m
%
d
%
H
%
M
%
S'
,
time
.
localtime
(
time
.
time
()))
return
time
.
strftime
(
'
%
Y
%
m
%
d
%
H
%
M
%
S'
,
time
.
localtime
(
time
.
time
()))
def
now_time
():
return
int
(
time
.
time
()
*
1000
)
def
year_to_day
():
def
year_to_day
():
return
time
.
strftime
(
'
%
Y
%
m
%
d'
,
time
.
localtime
(
time
.
time
()))
return
time
.
strftime
(
'
%
Y
-
%
m-
%
d'
,
time
.
localtime
(
time
.
time
()))
def
file_abspath
():
def
file_abspath
():
return
os
.
path
.
abspath
(
__file__
)
.
split
(
'src'
)[
0
]
return
os
.
path
.
abspath
(
__file__
)
.
split
(
'src'
)[
0
]
\ No newline at end of file
def
screenshot_path
():
screenshot_file
=
file_abspath
()
+
"/screenshots/"
+
year_to_day
()
if
not
os
.
path
.
exists
(
screenshot_file
):
os
.
mkdir
(
screenshot_file
)
return
screenshot_file
# 比较图片差异度,result越大,差异度越大,result=0,图片相同
def
compare_pictures
(
pic1
,
pic2
):
image1
=
Image
.
open
(
pic1
)
image2
=
Image
.
open
(
pic2
)
h1
=
image1
.
histogram
()
h2
=
image2
.
histogram
()
result
=
math
.
sqrt
(
reduce
(
operator
.
add
,
list
(
map
(
lambda
a
,
b
:
(
a
-
b
)
**
2
,
h1
,
h2
)))
/
len
(
h1
))
return
result
# 获取登录token
def
get_token
():
headers
=
{
"Content-Type"
:
"application/json; charset=UTF-8"
,
"User-Agent"
:
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/91.0.4472.77 Safari/537.36"
}
params
=
{
"phone"
:
"13777867342"
,
"authCode"
:
"0000"
,
"appTermEnum"
:
"XIAOMAI_CLOUD_CLASS_PC_WEB_ADMIN"
}
data
=
json
.
dumps
(
params
)
url
=
"https://gateway.xiaomai5.com/hades/anon/hades/login?storeId=null&token=null&storeUserId=null&userId=null"
r
=
requests
.
post
(
url
=
url
,
data
=
data
,
headers
=
headers
)
try
:
xmtoken
=
r
.
json
()[
"result"
][
"xmToken"
]
except
Exception
as
e
:
return
r
.
json
()[
"message"
]
return
xmtoken
# 创建一个直播课,返回课程id和课程名称
def
create_a_live
(
start_time
,
start_time2
=
None
):
xmtoken
=
get_token
()
while
xmtoken
==
"登录过频繁"
:
# 休息5s是因为可能会登录频繁
time
.
sleep
(
5
)
xmtoken
=
get_token
()
print
(
xmtoken
)
dt
=
year_to_day
()
+
' 00:00:00'
calendarTime
=
int
(
time
.
mktime
(
time
.
strptime
(
dt
,
"
%
Y-
%
m-
%
d
%
H:
%
M:
%
S"
)))
*
1000
startTime
=
now_time
()
+
start_time
*
60
*
1000
endTime
=
calendarTime
+
23
*
60
*
60
*
1000
# endTime = startTime + 5*60*1000
courseName
=
''
.
join
(
random
.
sample
(
string
.
ascii_letters
+
string
.
digits
,
8
))
courseName2
=
''
.
join
(
random
.
sample
(
string
.
ascii_letters
+
string
.
digits
,
8
))
url
=
"https://gateway.xiaomai5.com/hades/public/courseCloud/createLiveCloudCourse?storeId=1211601438838495999"
\
"&token={}&storeUserId=1394257952460828673&userId=1394908740376522754"
.
format
(
xmtoken
)
params
=
{
"adminIds"
:
[],
"calendarTime"
:
[
calendarTime
],
"categoryId"
:
"1386892090935164929"
,
"endTime"
:
endTime
,
"needRecord"
:
"YES"
,
"startTime"
:
startTime
,
"courseName"
:
courseName
,
"storeId"
:
"1211601438838495999"
,
"teacherId"
:
"1394908740376522754"
,
"whetherVisitorsJoin"
:
"NO"
,
"scheduleMediaRequests"
:
[],
"operatorId"
:
"1394908740376522754"
}
data
=
json
.
dumps
(
params
)
headers
=
{
"Content-Type"
:
"application/json; charset=UTF-8"
,
"User-Agent"
:
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/91.0.4472.77 Safari/537.36"
,
"storeId"
:
"1211601438838495999"
,
"storeUserId"
:
"1394257952460828673"
,
"xmtoken"
:
xmtoken
,
"userId"
:
"1394908740376522754"
,
"product"
:
"xmCloudClass"
}
r
=
requests
.
post
(
url
=
url
,
data
=
data
,
headers
=
headers
)
if
start_time2
is
not
None
:
time
.
sleep
(
2
)
startTime2
=
now_time
()
+
start_time2
*
60
*
1000
params2
=
{
"adminIds"
:
[],
"calendarTime"
:
[
calendarTime
],
"categoryId"
:
"1386892090935164929"
,
"endTime"
:
endTime
,
"needRecord"
:
"YES"
,
"startTime"
:
startTime2
,
"courseName"
:
courseName2
,
"storeId"
:
"1211601438838495999"
,
"teacherId"
:
"1394908740376522754"
,
"whetherVisitorsJoin"
:
"NO"
,
"scheduleMediaRequests"
:
[],
"operatorId"
:
"1394908740376522754"
}
data2
=
json
.
dumps
(
params2
)
r2
=
requests
.
post
(
url
=
url
,
data
=
data2
,
headers
=
headers
)
try
:
# 校验result中是否会返回课程id
assert
r
.
json
()[
"result"
]
!=
''
assert
r2
.
json
()[
"result"
]
!=
''
list1
=
[
courseName
,
courseName2
]
return
list1
except
Exception
as
e
:
print
(
e
.
args
)
else
:
try
:
# 校验result中是否会返回课程id
assert
r
.
json
()[
"result"
]
!=
''
return
courseName
except
Exception
as
e
:
print
(
e
.
args
)
src/pageobject/basepage.py
View file @
bc7dbb43
from
time
import
sleep
from
time
import
sleep
from
config
import
readConfig
# pages基类
# pages基类
from
selenium.webdriver.common.action_chains
import
ActionChains
from
selenium.webdriver.common.keys
import
Keys
from
selenium.common.exceptions
import
NoSuchElementException
from
selenium.common.exceptions
import
NoSuchElementException
from
selenium.webdriver.common.by
import
By
class
Page
(
object
):
class
Page
(
object
):
...
@@ -21,6 +26,10 @@ class Page(object):
...
@@ -21,6 +26,10 @@ class Page(object):
def
input_text
(
self
,
loc
,
text
):
def
input_text
(
self
,
loc
,
text
):
self
.
find_element
(
*
loc
)
.
send_keys
(
text
)
self
.
find_element
(
*
loc
)
.
send_keys
(
text
)
# 获取元素文本
def
get_text
(
self
,
loc
):
return
self
.
driver
.
find_element
(
*
loc
)
.
text
# 点击框点击
# 点击框点击
def
click
(
self
,
loc
):
def
click
(
self
,
loc
):
self
.
find_element
(
*
loc
)
.
click
()
self
.
find_element
(
*
loc
)
.
click
()
...
@@ -60,9 +69,13 @@ class Page(object):
...
@@ -60,9 +69,13 @@ class Page(object):
def
sleep
(
self
,
seconds
):
def
sleep
(
self
,
seconds
):
return
sleep
(
seconds
)
return
sleep
(
seconds
)
# 键盘down
def
keys_down
(
self
):
ActionChains
(
self
.
driver
)
.
key_down
(
Keys
.
DOWN
)
.
key_up
(
Keys
.
DOWN
)
.
perform
()
# 屏幕最大化
# 屏幕最大化
def
max
(
self
):
def
max
(
self
,
*
loc
):
self
.
driver
.
maximize_window
()
self
.
driver
.
find_element
(
*
loc
)
.
click
()
# 判断元素是否存在于页面
# 判断元素是否存在于页面
def
ifElementExist
(
self
,
loc
):
def
ifElementExist
(
self
,
loc
):
...
@@ -84,4 +97,23 @@ class Page(object):
...
@@ -84,4 +97,23 @@ class Page(object):
# 关闭窗口
# 关闭窗口
def
close
(
self
,
loc
,
num
):
def
close
(
self
,
loc
,
num
):
self
.
find_elements
(
*
loc
)[
num
]
.
click
()
self
.
find_elements
(
*
loc
)[
num
]
.
click
()
\ No newline at end of file
def
save_screenshot
(
self
,
filename
):
self
.
driver
.
save_screenshot
(
filename
)
def
login
(
self
):
driver
=
self
.
driver
login_page
=
Page
(
driver
=
driver
)
# 手机号登录按钮
phone_login
=
(
By
.
ID
,
"rc-tabs-0-tab-2"
)
# 账号输入框
account_input
=
(
By
.
ID
,
"xmphone"
)
# 密码输入框
password_input
=
(
By
.
ID
,
"xmpwd"
)
# 登录按钮
login_button
=
(
By
.
CLASS_NAME
,
"submit"
)
login_page
.
click
(
phone_login
)
login_page
.
input_text
(
account_input
,
readConfig
.
test_account
())
login_page
.
input_text
(
password_input
,
readConfig
.
test_password
())
login_page
.
click
(
login_button
)
src/pageobject/mainpage.py
View file @
bc7dbb43
...
@@ -3,61 +3,75 @@ from selenium.webdriver.common.by import By
...
@@ -3,61 +3,75 @@ from selenium.webdriver.common.by import By
# 主页面
# 主页面
class
Home
Page
(
LoginPage
):
class
Main
Page
(
LoginPage
):
# 元素集
# 元素集
# '未完成任务'按钮
# "今日"按钮
incomplete
=
(
By
.
XPATH
,
"//div[text()='未完成任务']"
)
today_btn
=
(
By
.
CLASS_NAME
,
"today"
)
# '未完成任务'按钮
# "月份"按钮
completed
=
(
By
.
XPATH
,
"//div[text()='已完成任务']"
)
month_btn
=
(
By
.
CLASS_NAME
,
"month"
)
# 荣誉榜按钮
# "最小化"按钮
honors
=
(
By
.
XPATH
,
"//span[text()='荣誉榜']"
)
min_btn
=
(
By
.
XPATH
,
"//div[@class='iconBaner']//span[1]"
)
# 修改密码按钮
# "刷新"按钮
modifypassword
=
(
By
.
XPATH
,
"//span[text()='修改密码']"
)
refresh_btn
=
(
By
.
XPATH
,
"//div[@class='iconBaner']//span[2]"
)
# 修改信息按钮
# "关闭"按钮
modifyinformation
=
(
By
.
XPATH
,
"//span[text()='修改信息']"
)
close_btn
=
(
By
.
XPATH
,
"//div[@class='iconBaner']//span[3]"
)
# 退出系统按钮
# 获取直播列表
logout
=
(
By
.
XPATH
,
"//span[text()='退出系统']"
)
live_list
=
(
By
.
CLASS_NAME
,
"list-content"
)
# 单词量测试按钮
# "进入直播间"按钮 format里面的参数还是要继续修改,先创建课程,再通过课程名称来查看进入直播间按钮
wordtest
=
(
By
.
XPATH
,
"//div[text()='单词量测试']"
)
in_live_btn
=
(
By
.
XPATH
,
"""//div[text()={{coursename}}]/..//button[@class="ant-btn ant-btn-primary"]"""
.
format
())
# 开始直播按钮
start_live_btn
=
(
By
.
XPATH
,
"""//span[text()="是"]"""
)
# 结束直播按钮
stop_live_btn
=
(
By
.
XPATH
,
"""//span[text()="结束直播"]"""
)
# 二次确认直播按钮
cancel_stop_live_btn
=
(
By
.
XPATH
,
"""//span[text()="取 消"]"""
)
# 验证元素
# 验证元素
# 荣誉榜-总排行
# 开启/关闭摄像头按钮
total_tanking
=
(
By
.
XPATH
,
"//li[text()='总排行']"
)
camera_btn
=
(
By
.
XPATH
,
"//div[@class='camera']/span"
)
# 修改密码-确认密码
confirm_password
=
(
By
.
CLASS_NAME
,
"title"
)
# 修改信息-姓名
name
=
(
By
.
CLASS_NAME
,
"title.short"
)
# 单词量测试-学段测试
stage_test
=
(
By
.
XPATH
,
"//div[text()='学段测试']"
)
def
__init__
(
self
,
driver
):
def
__init__
(
self
,
driver
):
LoginPage
.
__init__
(
self
,
driver
)
LoginPage
.
__init__
(
self
,
driver
)
# 点击'
未完成任务
'
# 点击'
今日
'
def
click_
incomplete
(
self
):
def
click_
today_btn
(
self
):
self
.
click
(
self
.
incomplete
)
self
.
click
(
self
.
today_btn
)
# 点击'
已完成任务
'
# 点击'
月份
'
def
click_
completed
(
self
):
def
click_
month_btn
(
self
):
self
.
click
(
self
.
completed
)
self
.
click
(
self
.
month_btn
)
# 点击'
荣誉榜
'
# 点击'
最小化
'
def
click_
honors
(
self
):
def
click_
min_btn
(
self
):
self
.
click
(
self
.
honors
)
self
.
click
(
self
.
min_btn
)
# 点击'
修改密码
'
# 点击'
刷新
'
def
click_
modifypassword
(
self
):
def
click_
refresh_btn
(
self
):
self
.
click
(
self
.
modifypassword
)
self
.
click
(
self
.
refresh_btn
)
# 点击'
修改信息
'
# 点击'
关闭
'
def
click_
modifyinformatio
n
(
self
):
def
click_
close_bt
n
(
self
):
self
.
click
(
self
.
modifyinformatio
n
)
self
.
click
(
self
.
close_bt
n
)
# 点击'退出系统'
# 点击'进入直播间'
def
click_logout
(
self
):
def
click_in_live_btn
(
self
,
coursename
):
self
.
click
(
self
.
logout
)
self
.
in_live_btn
=
(
By
.
XPATH
,
"""//div[text()="{}"]/..//button[@class="ant-btn ant-btn-primary"]"""
.
format
(
coursename
))
self
.
click
(
self
.
in_live_btn
)
# 点击'单词量测试'
def
click_camera_btn
(
self
):
def
click_wordtest
(
self
):
self
.
click
(
self
.
camera_btn
)
self
.
click
(
self
.
wordtest
)
\ No newline at end of file
def
start_live
(
self
):
self
.
click
(
self
.
start_live_btn
)
def
stop_live
(
self
):
self
.
click
(
self
.
stop_live_btn
)
def
get_live_name
(
self
):
self
.
keys_down
()
# 获取按钮文本
def
get_btn_text
(
self
,
coursename
):
self
.
in_live_btn
=
(
By
.
XPATH
,
"""//div[text()="{}"]/..//button[@class="ant-btn"]"""
.
format
(
coursename
))
return
self
.
get_text
(
self
.
in_live_btn
)
src/testcase/testLoginPage.py
View file @
bc7dbb43
from
src.pageobject.loginpage
import
LoginPage
from
src.pageobject.loginpage
import
LoginPage
from
src.framework.logger
import
Logger
from
src.framework.logger
import
Logger
from
src.framework.appDriver
import
get_app_driver
from
config
import
readConfig
from
config
import
readConfig
from
commom.appDriver
import
get_app_driver
import
unittest
import
unittest
...
@@ -14,7 +14,7 @@ class TestLoginPage(unittest.TestCase):
...
@@ -14,7 +14,7 @@ class TestLoginPage(unittest.TestCase):
def
setUp
(
self
)
->
None
:
def
setUp
(
self
)
->
None
:
print
(
11111
)
print
(
11111
)
# 指定
chrome的webdriver路径
# 指定
Pc端的本地路径,在/config/config.ini配置
self
.
driver
=
get_app_driver
(
self
.
cloud_class_location
)
self
.
driver
=
get_app_driver
(
self
.
cloud_class_location
)
def
tearDown
(
self
)
->
None
:
def
tearDown
(
self
)
->
None
:
...
@@ -29,6 +29,7 @@ class TestLoginPage(unittest.TestCase):
...
@@ -29,6 +29,7 @@ class TestLoginPage(unittest.TestCase):
login_page
.
input_password
(
password
=
self
.
password
)
login_page
.
input_password
(
password
=
self
.
password
)
login_page
.
click_login
()
login_page
.
click_login
()
login_page
.
sleep
(
1
)
login_page
.
sleep
(
1
)
# 校验是否存在店铺名称的元素
self
.
assertTrue
(
login_page
.
ifElementExist
(
login_page
.
store_name
))
self
.
assertTrue
(
login_page
.
ifElementExist
(
login_page
.
store_name
))
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment