selenium UI自动化实战
1.1项目框架
项目如何使用框架: 本项目采用unitest框架
设计模式是如何应用:本项目采用pageobject设计模式
UI对象库思想
项目设计
一个模块(被测项目的页面)对应一个py文件及一个测试类(测试文件)
每一个测试页面(系统的页面)中存储页面元素及此页面中涉及到的功能
每一个用例组合在一个测试类里面生成一个py文件
项目目标
我们在写自动化测试项目的时候一定要想好你的脚本都要哪些功能,页面元素平凡改动的时候是否需要大批量的修改脚本,及测试不同数据时是否也要修改脚本,那么能想到这些我们的初始目标差不多就有了
1.生成测试用例执行结果报告
2.生成测试用例执行日志
3.用例执行失败或者执行完成后自动发送邮件报告
用例执行失败或者成功时截取图片
5.数据驱动(读取测试数据,减少脚本维护成本)
更多资料
1.2项目目录结构
Retail_TestPro
Docs# 存放项目的相关文档
01测试计划
02测试大纲
03测试用例
04测试报告
05测试进度
06技术文档
07测试申请
Package# 存放第三方插件
HTMLTestRunner.py
Retail
Config
__init__.py
Conf.py# 读配置文件获取项目跟目录路径 并获取所有欲使用的目录文件的路径
Config.ini# 存放项目跟目录的路径
Data
TestData
__init__.py
elementDate.xlsx# 存放项目中所有的元素信息及测试数据
Email_receiver.txt# 存放邮件的接受者信息
Report# 测试报告
Image
Fail# 存放用例执行失败时的截图
Pass# 存放用例执行成功时的截图
Log# 存放用例执行过程中的log信息
TestReport# 存放测试用例执行完成后生成的测试报告
Test_case# 测试用例信息
Models # 存放一些公共方法
Doconfini.py# 读配置文件
Doexcel.py# 读excel文件
Driver.py# 存放driver
Log.py# 生成log
Myunit.py# 继承unittest.Testcase
Sendmail.py# 发送邮件
Strhandle.py# 字符串处理
Tcinfo.py# 测试用例基本信息
Testreport.py# 测试报告
Page_obj# 测试模块
Activerule_page.py
Base_page.py
Company_page.py
Createrule_page.py
Memberquery_page.py
Modifypw_page.py
Pointquery_page.py
ActiveRuleTc.py
CompanyQueryTc.py
CreateRuleTc.py
LoginTc.py
MemberQueryTc.py
ModifyPwTc.py
PointQueryTc.py
runTc.py# 执行测试用例
二.项目代码
1.config.ini (存放项目跟路径)
1
2
[project]
project_path = D:\\Petrochina_Retail_Test_Project
2.conf.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
\'\'\'
Code description:read config.ini, get path
Create time:
Developer:
\'\'\'
import
os
import
sys
from
retail.test_case.models.doconfIni
import
DoConfIni
# 获取当前路径
currPath
=
\\
os.path.split(os.path.realpath(__file__))[
0
]
# 读配置文件获取项目路径
readConfig
=
\\
DoConfIni()
proPath
=
\\
readConfig.getConfValue(os.path.join(currPath,
\'config.ini\'
),
\'project\'
,
\'project_path\'
)
# 获取日志路径
logPath
=
\\
os.path.join(proPath,
\'retail\'
,
\'report\'
,
\'Log\'
)
# 测试用例路径
tcPath
=
\\
os.path.join(proPath,
\'retail\'
,
\'test_case\'
)
# 获取报告路径
reportPath
=
\\
os.path.join(proPath,
\'retail\'
,
\'report\'
,
\'TestReport\'
)
# 获取测试数据路径
dataPath
=
\\
os.path.join(proPath,
\'retail\'
,
\'data\'
,
\'TestData\'
)
# 保存截图路径
# 错误截图
failImagePath
=
os.path.join(proPath,
\'retail\'
,
\'report\'
,
\'image\'
,
\'fail\'
)
# 成功截图
passImagePath
=
os.path.join(proPath,
\'retail\'
,
\'report\'
,
\'image\'
,
\'pass\'
)
# 被调函数名称
funcName
=
sys._getframe().f_code.co_name
# 被调函数所在行号
funcNo
=
sys._getframe().f_back.f_lineno
# 被调函数所在文件名称
funcFile
=
sys._getframe().f_code.co_filename
3.elementData.xlsx(json与yaml替换)
存放测试数据
4.公共方法models下面的文件
4.1doconfini.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
\'\'\'
Code description:read conf file
Create time:
Developer:
\'\'\'
import
logging
import
configparser
from
retail.config.conf
import
*
from
retail.test_case.models.log
import
Logger
log
=
Logger(__name__, CmdLevel
=
logging.INFO, FileLevel
=
logging.INFO)
class
DoConfIni(
object
):
def
__init__(
self
):
\"\"\"
:param filename:
\"\"\"
self
.cf
=
configparser.ConfigParser()
# 从ini文件中读数据
def
getConfValue(
self
,filename,section,name):
\"\"\"
:param config:
:param name:
:return:
\"\"\"
try
:
self
.cf.read(filename)
value
=
self
.cf.get(section,name)
except
Exception as e:
log.logger.exception(
\'read file [%s] for [%s] failed , did not get the value\'
%
(filename,section))
raise
e
else
:
log.logger.info(
\'read excel value [%s] successed! \'
%
value)
return
value
# 向ini文件中写数据
def
writeConfValue(
self
,filename, section, name, value):
\"\"\"
:param section: section
:param name: value name
:param value: value
:return: none
\"\"\"
try
:
self
.cf.add_section(section)
self
.cf.
set
(section, name, value)
self
.cf.write(
open
(filename,
\'w\'
))
except
Exception :
log.logger.exception(
\'section %s has been exist!\'
%
section)
raise
configparser.DuplicateSectionError(section)
else
:
log.logger.info(
\'write section\'
+
section
+
\'with value \'
+
value
+
\' successed!\'
)
if
__name__
=
=
\'__main__\'
:
file_path
=
currPath
print
(file_path)
read_config
=
DoConfIni()
value
=
read_config.getConfValue(os.path.join(currPath,
\'config.ini\'
),
\'project\'
,
\'project_path\'
)
print
(value)
read_config.writeConfValue(os.path.join(currPath,
\'config.ini\'
),
\'tesesection\'
,
\'name\'
,
\'hello word\'
)
4.2doexcel.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
\'\'\'
Code description:read excel.xlsx, get values
Create time:
Developer:
\'\'\'
import
xlrd
import
os
import
logging
from
retail.config
import
conf
from
retail.test_case.models.log
import
Logger
log
=
Logger(__name__, CmdLevel
=
logging.INFO, FileLevel
=
logging.INFO)
class
ReadExcel(
object
):
def
__init__(
self
,fileName
=
\'elementDate.xlsx\'
,sheetName
=
\'elementsInfo\'
):
\"\"\"
:param fileName:
:param sheetName:
\"\"\"
try
:
self
.dataFile
=
os.path.join(conf.dataPath, fileName)
self
.workBook
=
xlrd.open_workbook(
self
.dataFile)
self
.sheetName
=
self
.workBook.sheet_by_name(sheetName)
except
Exception:
log.logger.exception(
\'init class ReadExcel fail\'
, exc_info
=
True
)
raise
else
:
log.logger.info(
\'initing class ReadExcel\'
)
# 读excel中的数据
def
readExcel(
self
,rownum,colnum):
\"\"\"
:param rownum:
:param colnum:
:return:
\"\"\"
try
:
value
=
self
.sheetName.cell(rownum,colnum).value
except
Exception:
log.logger.exception(
\'read value from excel file fail\'
, exc_info
=
True
)
raise
else
:
log.logger.info(
\'reading value [%s] from excel file [%s] completed\'
%
(value,
self
.dataFile))
return
value
if
__name__
=
=
\'__main__\'
:
cellValue
=
ReadExcel().readExcel(
1
,
3
)
print
((cellValue))
4.3log.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
\'\'\'
Code description:log info
Create time:
Developer:
\'\'\'
import
logging
import
time
class
Logger(
object
):
def
__init__(
self
, logger, CmdLevel
=
logging.INFO, FileLevel
=
logging.INFO):
\"\"\"
:param logger:
:param CmdLevel:
:param FileLevel:
\"\"\"
self
.logger
=
logging.getLogger(logger)
self
.logger.setLevel(logging.DEBUG)
# 设置日志输出的默认级别
# 日志输出格式
fmt
=
logging.Formatter(
\'%(asctime)s - %(filename)s:[%(lineno)s] - [%(levelname)s] - %(message)s\'
)
# 日志文件名称
# self.LogFileName = os.path.join(conf.log_path, \"{0}.log\".format(time.strftime(\"%Y-%m-%d\")))# %H_%M_%S
currTime
=
time.strftime(
\"%Y-%m-%d\"
)
self
.LogFileName
=
r
\'D:\\Petrochina_Retail_Test_Project\\retail\\report\\Log\\log\'
+
currTime
+
\'.log\'
# 设置控制台输出
# sh = logging.StreamHandler()
# sh.setFormatter(fmt)
# sh.setLevel(CmdLevel)# 日志级别
# 设置文件输出
fh
=
logging.FileHandler(
self
.LogFileName)
fh.setFormatter(fmt)
fh.setLevel(FileLevel)
# 日志级别
# self.logger.addHandler(sh)
self
.logger.addHandler(fh)
# def debug(self, message):
# \"\"\"
#
# :param message:
# :return:
# \"\"\"
# self.logger.debug(message)
#
# def info(self,message):
# \"\"\"
#
# :param message:
# :return:
# \"\"\"
# self.logger.info(message)
#
# def warn(self,message):
# \"\"\"
#
# :param message:
# :return:
# \"\"\"
# self.logger.warning(message)
#
# def error(self,message):
# \"\"\"
#
# :param message:
# :return:
# \"\"\"
# self.logger.error(message)
#
# def criti(self,message):
# \"\"\"
#
# :param message:
# :return:
# \"\"\"
# self.logger.critical(message)
if
__name__
=
=
\'__main__\'
:
logger
=
Logger(
\"fox\"
,CmdLevel
=
logging.DEBUG, FileLevel
=
logging.DEBUG)
logger.logger.debug(
\"debug\"
)
logger.logger.log(logging.ERROR,
\'%(module)s %(info)s\'
,{
\'module\'
:
\'log日志\'
,
\'info\'
:
\'error\'
})
#ERROR,log日志 error
4.4sendmail.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
\'\'\'
Code description:send email
Create time:
Developer:
\'\'\'
import
smtplib
from
email.mime.text
import
MIMEText
from
email.header
import
Header
import
os
from
retail.config
import
conf
from
retail.test_case.models.log
import
Logger
log
=
Logger(__name__)
# 邮件发送接口
class
SendMail(
object
):
\'\'\'
邮件配置信息
\'\'\'
def
__init__(
self
,
receiver,
subject
=
\'Retail 系统测试报告\'
,
server
=
\'smtp.qq.com\'
,
fromuser
=
\'281754043@qq.com\'
,
frompassword
=
\'gifhhsbgqyovbhhc\'
,
sender
=
\'281754043@qq.com\'
):
\"\"\"
:param receiver:
:param subject:
:param server:
:param fromuser:
:param frompassword:
:param sender:
\"\"\"
self
._server
=
server
self
._fromuser
=
fromuser
self
._frompassword
=
frompassword
self
._sender
=
sender
self
._receiver
=
receiver
self
._subject
=
subject
def
sendEmail(
self
, fileName):
\"\"\"
:param filename:
:return:
\"\"\"
# 打开报告文件读取文件内容
try
:
f
=
open
(os.path.join(conf.reportPath, fileName),
\'rb\'
)
fileMsg
=
f.read()
except
Exception:
log.logger.exception(
\'open or read file [%s] failed,No such file or directory: %s\'
%
(fileName, conf.reportPath))
log.logger.info(
\'open and read file [%s] successed!\'
%
fileName)
else
:
f.close()
# 邮件主题
subject
=
\'Python test report\'
#
# 邮件设置
msg
=
MIMEText(fileMsg,
\'html\'
,
\'utf-8\'
)
msg[
\'subject\'
]
=
Header(subject,
\'utf-8\'
)
msg[
\'from\'
]
=
self
._sender
# 连接服务器,登录服务器,发送邮件
try
:
smtp
=
smtplib.SMTP()
smtp.connect(
self
._server)
smtp.login(
self
._fromuser,
self
._frompassword)
except
Exception:
log.logger.exception(
\'connect [%s] server failed or username and password incorrect!\'
%
smtp)
else
:
log.logger.info(
\'email server [%s] login success!\'
%
smtp)
try
:
smtp.sendmail(
self
._sender,
self
._receiver, msg.as_string())
except
Exception:
log.logger.exception(
\'send email failed!\'
)
else
:
log.logger.info(
\'send email successed!\'
)
# 从文件中读取邮件接收人信息
def
getReceiverInfo(fileName):
\'\'\'
:param filename: 读取接收邮件人信息
:return: 接收邮件人信息
\'\'\'
try
:
openFile
=
open
(os.path.join(conf.dataPath, fileName))
except
Exception:
log.logger.exception(
\'open or read file [%s] failed,No such file or directory: %s\'
%
(fileName, conf.dataPath))
else
:
log.logger.info(
\'open file [%s] successed!\'
%
fileName)
for
line
in
openFile:
msg
=
[i.strip()
for
i
in
line.split(
\',\'
)]
log.logger.info(
\'reading [%s] and got receiver value is [%s]\'
%
(fileName, msg))
return
msg
if
__name__
=
=
\'__main__\'
:
readMsg
=
getReceiverInfo(
\'mail_receiver.txt\'
)
sendmail
=
SendMail(readMsg)
sendmail.sendEmail(
\'2021-04-21 17_44_04.html\'
)
4.5strhandle.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
\'\'\'
Code description: string handle
Create time:
Developer:
\'\'\'
import
logging
from
retail.test_case.models.log
import
Logger
log
=
Logger(__name__, CmdLevel
=
logging.INFO, FileLevel
=
logging.INFO)
def
strhandle(
str
):
\"\"\"
:param str:
:return:
\"\"\"
#初始化字符、数字、空格、特殊字符的计数
try
:
lowerCase
=
0
upperCase
=
0
number
=
0
other
=
0
for
stritem
in
str
:
#如果在字符串中有小写字母,那么小写字母的数量+1
if
stritem.islower():
lowerCase
+
=
1
#如果在字符串中有数字,那么数字的数量+1
elif
stritem.isdigit():
number
+
=
1
elif
stritem.isupper():
# 大写字母
upperCase
+
=
1
#如果在字符串中有空格,那么空格的数量+1
else
:
other
+
=
1
return
lowerCase, upperCase, number, other
except
Exception as e:
log.logger.exception(
\'string handle error , please check!\'
, exc_info
=
True
)
raise
e
if
__name__
=
=
\'__main__\'
:
list
=
[
\'qwert\'
,
\'erwer\'
]
lowercase, uppercase, number, other
=
strhandle(
list
[
0
])
print
(
\"该字符串中的小写字母有:%d\"
%
lowercase)
print
(
\"该字符串中的大写写字母有:%d\"
%
uppercase)
print
(
\"该字符串中的数字有:%d\"
%
number)
print
(
\"该字符串中的特殊字符有:%d\"
%
other)
4.6testreport.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
\'\'\'
Code description:test report
Create time:
Developer:
\'\'\'
import
time
import
logging
import
unittest
from
BeautifulReport
import
BeautifulReport
import
HTMLTestRunner
from
retail.config
import
conf
from
retail.test_case.models.log
import
Logger
log
=
Logger(__name__, CmdLevel
=
logging.INFO, FileLevel
=
logging.INFO)
# 用HTMLTestRunner 实现的测试报告
def
testreport():
\"\"\"
:return:
\"\"\"
currTime
=
time.strftime(
\'%Y-%m-%d %H_%M_%S\'
)
fileName
=
conf.reportPath
+
r
\'\\report\'
+
currTime
+
\'.html\'
try
:
fp
=
open
(fileName,
\'wb\'
)
except
Exception :
log.logger.exception(
\'[%s] open error cause Failed to generate test report\'
%
fileName)
else
:
runner
=
HTMLTestRunner.HTMLTestRunner\\
(stream
=
fp, title
=
\'Retail sys测试报告\'
,
description
=
\'处理器:Intel(R) Core(TM) \'
\'i5-6200U CPU @ 2030GHz 2.40 GHz \'
\'内存:8G 系统类型: 64位 版本: windows 10 家庭中文版\'
)
log.logger.info(
\'successed to generate test report [%s]\'
%
fileName)
return
runner, fp, fileName
#
def
addTc(TCpath
=
conf.tcPath, rule
=
\'*TC.py\'
):
\"\"\"
:param TCpath: 测试用例存放路径
:param rule: 匹配的测试用例文件
:return: 测试套件
\"\"\"
discover
=
unittest.defaultTestLoader.discover(TCpath, rule)
return
discover
# 用BeautifulReport模块实现测试报告
def
runTc(discover):
\"\"\"
:param discover: 测试套件
:return:
\"\"\"
currTime
=
time.strftime(
\'%Y-%m-%d %H_%M_%S\'
)
fileName
=
currTime
+
\'.html\'
try
:
result
=
BeautifulReport(discover)
result.report(filename
=
fileName, description
=
\'测试报告\'
, log_path
=
conf.reportPath)
except
Exception:
log.logger.exception(
\'Failed to generate test report\'
, exc_info
=
True
)
else
:
log.logger.info(
\'successed to generate test report [%s]\'
%
fileName)
return
fileName
if
__name__
=
=
\'__main__\'
:
testreport()
suite
=
addTc(rule
=
\'*TC.py\'
)
runTc(suite)
4.7driver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
\'\'\'
Code description:save all driver info
Create time:
Developer:
\'\'\'
from
selenium
import
webdriver
import
logging
import
sys
from
retail.test_case.models.log
import
Logger
log
=
Logger(__name__, CmdLevel
=
logging.INFO, FileLevel
=
logging.INFO)
class
WDriver(
object
):
# Firefox driver
def
fireFoxDriver(
self
):
\"\"\"
:return:
\"\"\"
try
:
self
.driver
=
webdriver.Firefox()
except
Exception as e:
log.logger.exception(
\'FireFoxDriverServer.exe executable needs to be in PATH. Please download!\'
, exc_info
=
True
)
raise
e
else
:
log.logger.info(
\'%s:found the Firefox driver [%s] successed !\'
%
(sys._getframe().f_code.co_name,
self
.driver))
return
self
.driver
# chrom driver
def
chromeDriver(
self
):
\"\"\"
:return:
\"\"\"
try
:
# option = webdriver.ChromeOptions()# 实现不打开浏览器 执行web自动化测试脚本
# option.add_argument(\'headless\')#
# self.driver = webdriver.Chrome(chrome_options=option)
self
.driver
=
webdriver.Chrome()
except
Exception as e:
log.logger.exception(
\'ChromeDriverServer.exe executable needs to be in PATH. Please download!\'
,
exc_info
=
True
)
raise
e
else
:
log.logger.info(
\'%s:found the chrome driver [%s] successed !\'
%
(sys._getframe().f_code.co_name,
self
.driver))
return
self
.driver
# Ie driver
def
ieDriver(
self
):
\"\"\"
:return:
\"\"\"
try
:
self
.driver
=
webdriver.Ie()
except
Exception as e:
log.logger.exception(
\'IEDriverServer.exe executable needs to be in PATH. Please download!\'
,
exc_info
=
True
)
raise
e
else
:
log.logger.info(
\'%s:found the IE driver [%s] successed !\'
%
(sys._getframe().f_code.co_name,
self
.driver))
return
self
.driver
if
__name__
=
=
\'__main__\'
:
WDrive
=
WDriver()
WDrive.fireFoxDriver()
4.8myunittest.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
\'\'\'
Code description:unittest framwork
Create time:
Developer:
\'\'\'
from
retail.test_case.models.driver
import
WDriver
import
logging
import
unittest
from
retail.test_case.page_obj.login_page
import
LoginPage
from
retail.test_case.models.log
import
Logger
from
selenium
import
webdriver
log
=
Logger(__name__, CmdLevel
=
logging.INFO, FileLevel
=
logging.INFO)
class
MyunitTest(unittest.TestCase):
\"\"\"
\"\"\"
# add by xuechao at 2018.09.19
@classmethod
def
setUpClass(
cls
):
# 一个测试类(文件)执行一次打开浏览器, 节约每个用例打开一次浏览器的时间
#cls.driver = WDriver().fireFoxDriver()
cls
.driver
=
WDriver().chromeDriver()
cls
.driver.maximize_window()
log.logger.info(
\'opened the browser successed!\'
)
# ----------------------------
def
setUp(
self
):
\"\"\"
:return:
\"\"\"
self
.login
=
LoginPage(
self
.driver)
self
.login.
open
()
log.logger.info(
\'************************starting run test cases************************\'
)
def
tearDown(
self
):
\"\"\"
:return:
\"\"\"
self
.driver.refresh()
log.logger.info(
\'************************test case run completed************************\'
)
# add by linuxchao at 2018.09.19
@classmethod
def
tearDownClass(
cls
):
cls
.driver.quit()
log.logger.info(
\'quit the browser success!\'
)
#----------------------------
if
__name__
=
=
\'__main__\'
:
unittest.main()
4.9结束语
目前为止,我需要的所有的公共方法都编写完了, 后期再需要别的方法可以加,下面我们就开始编写我们的测试用例,由于我们使用的是PageObject模式,那么我们需要设计一个basepage页面,所有的页面或者说模块全部继承这个basepage,basepage主要编写所有页面的公共方法
5.base_page.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
\'\'\'
Code description: base page 封装一些公共方法
Create time:
Developer:
\'\'\'
from
selenium.webdriver.support.wait
import
WebDriverWait
from
selenium.webdriver.support
import
expected_conditions as EC
from
selenium.webdriver.common.by
import
By
import
os
import
logging
import
sys
from
retail.test_case.models.log
import
Logger
from
retail.config
import
conf
from
retail.test_case.models.doexcel
import
ReadExcel
eleData
=
ReadExcel()
# 存储系统所有的元素数据
testLoginData
=
ReadExcel(
\'elementDate.xlsx\'
,
\'userNamePw\'
)
# 登录模块测试数据
modifyPwData
=
ReadExcel(
\'elementDate.xlsx\'
,
\'modifyPw\'
)
# 修改密码模块测试数据
queryData
=
ReadExcel(
\'elementDate.xlsx\'
,
\'queryData\'
)
log
=
Logger(__name__, CmdLevel
=
logging.INFO, FileLevel
=
logging.INFO)
class
BasePage(
object
):
\"\"\"主菜单\"\"\"
menuList
=
\\
[(By.LINK_TEXT, eleData.readExcel(
7
,
3
)),
# 权限管理
(By.LINK_TEXT, eleData.readExcel(
8
,
3
)),
# 会员档案
(By.LINK_TEXT, eleData.readExcel(
9
,
3
)),
# 积分消费查询
(By.LINK_TEXT, eleData.readExcel(
10
,
3
)),
# 功能演示
(By.LINK_TEXT, eleData.readExcel(
11
,
3
)),
# 待办工作
(By.LINK_TEXT, eleData.readExcel(
12
,
3
)),
# 报表
(By.LINK_TEXT, eleData.readExcel(
13
,
3
)),
# 积分规则/活动查询
(By.LINK_TEXT, eleData.readExcel(
14
,
3
))]
# 积分规则/活动申请
def
__init__(
self
, driver,url
=
\'http://11.11.164.134:9081/rmms/modules/ep.rmms.portal/login/login.jsp\'
):
\"\"\"
:param driver:
:param url:
\"\"\"
self
.driver
=
driver
self
.base_url
=
url
def
_open(
self
,url):
\"\"\"
:param url:
:return:
\"\"\"
try
:
self
.driver.get(url)
self
.driver.implicitly_wait(
10
)
except
Exception as e:
log.logger.exception(e, exc_info
=
True
)
raise
ValueError(
\'%s address access error, please check!\'
%
url)
else
:
log.logger.info(
\'%s is accessing address %s at line[46]\'
%
(sys._getframe().f_code.co_name,url))
def
open
(
self
):
\"\"\"
:return:
\"\"\"
self
._open(
self
.base_url)
log.logger.info(
\'%s loading successed!\'
%
self
.base_url)
return
self
.base_url
# *loc 代表任意数量的位置参数
def
findElement(
self
,
*
loc):
\"\"\"
查找单一元素
:param loc:
:return:
\"\"\"
try
:
WebDriverWait(
self
.driver,
10
).until(EC.visibility_of_element_located(loc))
# log.logger.info(\'The page of %s had already find the element %s\'%(self,loc))
# return self.driver.find_element(*loc)
except
Exception as e:
log.logger.exception(
\'finding element timeout!, details\'
,exc_info
=
True
)
raise
e
else
:
log.logger.info(
\'The page of %s had already find the element %s\'
%
(
self
, loc))
return
self
.driver.find_element(
*
loc)
def
findElements(
self
,
*
loc):
\"\"\"
查找一组元素
:param loc:
:return:
\"\"\"
try
:
WebDriverWait(
self
.driver,
10
).until(EC.visibility_of_element_located(loc))
# log.logger.info(\'The page of %s had already find the element %s\' % (self, loc))
# return self.driver.find_elements(*loc)
except
Exception as e:
log.logger.exception(
\'finding element timeout!, details\'
, exc_info
=
True
)
raise
e
else
:
log.logger.info(
\'The page of %s had already find the element %s\'
%
(
self
, loc))
return
self
.driver.find_elements(
*
loc)
def
inputValue(
self
, inputBox, value):
\"\"\"
后期修改其他页面直接调用这个函数
:param inputBox:
:param value:
:return:
\"\"\"
inputB
=
self
.findElement(
*
inputBox)
try
:
inputB.clear()
inputB.send_keys(value)
except
Exception as e:
log.logger.exception(
\'typing value error!\'
, exc_info
=
True
)
raise
e
else
:
log.logger.info(
\'inputValue:[%s] is receiveing value [%s]\'
%
(inputBox, value))
# 获取元素数据
def
getValue(
self
,
*
loc):
\"\"\"
:param loc:
:return:
\"\"\"
element
=
self
.findElement(
*
loc)
try
:
value
=
element.text
#return value
except
Exception:
#element = self.find_element_re(*loc) # 2018.09.21 for log
value
=
element.get_attribute(
\'value\'
)
log.logger.info(
\'reading the element [%s] value [%s]\'
%
(loc, value))
return
value
except
:
log.logger.exception(
\'read value failed\'
, exc_info
=
True
)
raise
Exception
else
:
log.logger.info(
\'reading the element [%s] value [%s]\'
%
(loc,value))
return
value
def
getValues(
self
,
*
loc):
\"\"\"
:param loc:
:return:
\"\"\"
value_list
=
[]
try
:
for
element
in
self
.findElements(
*
loc):
value
=
element.text
value_list.append(value)
except
Exception as e:
log.logger.exception(
\'read value failed\'
, exc_info
=
True
)
raise
e
else
:
log.logger.info(
\'reading the element [%s] value [%s]\'
%
(loc,value_list))
return
value_list
# 执行js脚本
def
jScript(
self
,src):
\"\"\"
:param src:
:return:
\"\"\"
try
:
self
.driver.excute_script(src)
except
Exception as e:
log.logger.exception(
\'execute js script [%s] failed \'
%
src)
raise
e
else
:
log.logger.info(
\'execute js script [%s] successed \'
%
src)
# 判断元素是否存在
def
isElementExist(
self
, element):
\"\"\"
:param element:
:return:
\"\"\"
try
:
WebDriverWait(
self
.driver,
10
).until(EC.visibility_of_element_located(element))
except
:
# log.logger.exception(\'The element [%s] not exist\', exc_info=True)
return
False
else
:
# log.logger.info(\'The element [%s] have existed!\' %element)
return
True
# 截图
def
saveScreenShot(
self
, filename):
\"\"\"
:param filename:
:return:
\"\"\"
list_value
=
[]
list
=
filename.split(
\'.\'
)
for
value
in
list
:
list_value.append(value)
if
list_value[
1
]
=
=
\'png\'
or
list_value[
1
]
=
=
\'jpg\'
or
list_value[
1
]
=
=
\'PNG\'
or
list_value[
1
]
=
=
\'JPG\'
:
if
\'fail\'
in
list_value[
0
].split(
\'_\'
):
try
:
self
.driver.save_screenshot(os.path.join(conf.failImagePath, filename))
except
Exception:
log.logger.exception(
\'save screenshot failed !\'
, exc_info
=
True
)
else
:
log.logger.info(
\'the file [%s] save screenshot successed under [%s]\'
%
(filename, conf.failImagePath))
elif
\'pass\'
in
list_value[
0
]:
try
:
self
.driver.save_screenshot(os.path.join(conf.passImagePath, filename))
except
Exception:
log.logger.exception(
\'save screenshot failed !\'
, exc_info
=
True
)
else
:
log.logger.info(
\'the file [%s] save screenshot successed under [%s]\'
%
(filename, conf.passImagePath))
else
:
log.logger.info(
\'save screenshot failed due to [%s] format incorrect\'
%
filename)
else
:
log.logger.info(
\'the file name of [%s] format incorrect cause save screenshot failed, please check!\'
%
filename)
# 接受错误提示框
def
accept(
self
,
*
loc):
\"\"\"
:return:
\"\"\"
self
.findElement(
*
loc).click()
log.logger.info(
\'closed the error information fram successed!\'
)
if
__name__
=
=
\'__main__\'
:
pass
6.login_page.py(登陆页面)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
\'\'\'
Code description: login page
Create time:
Developer:
\'\'\'
from
selenium.webdriver.common.by
import
By
import
logging
import
sys
from
retail.test_case.page_obj.base_page
import
BasePage, eleData, testLoginData
from
retail.test_case.models.log
import
Logger
log
=
Logger(__name__, CmdLevel
=
logging.INFO, FileLevel
=
logging.INFO)
class
LoginPage(BasePage):
\"\"\"用户名,密码,登录按钮,保存信息,错误提示\"\"\"
userNameEle
=
(By.
ID
, eleData.readExcel(
1
,
3
))
passWordEle
=
(By.
ID
, eleData.readExcel(
2
,
3
))
loginBtnEle
=
(By.
ID
, eleData.readExcel(
3
,
3
))
saveInfoEle
=
(By.NAME, eleData.readExcel(
4
,
3
))
errorMessage
=
(By.
ID
, eleData.readExcel(
5
,
3
))
quitBtn
=
(By.
ID
, eleData.readExcel(
6
,
3
))
# 用户名和密码
unpwData
=
\\
[[testLoginData.readExcel(
1
,
0
), testLoginData.readExcel(
1
,
1
)],
# 正确的用户名和正确的密码
[testLoginData.readExcel(
2
,
0
), testLoginData.readExcel(
2
,
1
)],
# 错误的用户名和正确的密码
[testLoginData.readExcel(
3
,
0
), testLoginData.readExcel(
3
,
1
)],
# 空的用户名和正确的密码
[testLoginData.readExcel(
4
,
0
), testLoginData.readExcel(
4
,
1
)],
# 错误的用户名和错误的密码
[testLoginData.readExcel(
5
,
0
), testLoginData.readExcel(
5
,
1
)],
# 正确的用户名和空密码
[testLoginData.readExcel(
6
,
0
), testLoginData.readExcel(
6
,
1
)],
# 正确的用户名和错误的密码
[testLoginData.readExcel(
7
,
0
), testLoginData.readExcel(
7
,
1
)]]
# 空用户名和空密码
# 登录按钮
def
clickLoginBtn(
self
):
\"\"\"
:return:
\"\"\"
element
=
self
.findElement(
*
self
.loginBtnEle)
element.click()
log.logger.info(
\'%s ,logining....!\'
%
sys._getframe().f_code.co_name)
# 登录失败时提示
def
getFailedText(
self
):
\"\"\"
:return:
\"\"\"
info
=
self
.findElement(
*
self
.errorMessage).text
log.logger.info(
\'login failed : %s\'
%
info)
return
info
# 登录失败时弹出的alert
def
handleAlert(
self
):
\"\"\"
:return:
\"\"\"
try
:
alert
=
self
.driver.switch_to_alert()
text
=
alert.text
alert.accept()
except
Exception:
log.logger.exception(
\'handle alert failed, please check the details\'
,exc_info
=
True
)
raise
else
:
log.logger.info(
\'login failed ,%s handle alert successed alert info: %s!\'
%
(sys._getframe().f_code.co_name, text))
return
text
# 统一登录函数
def
loginFunc(
self
, username
=
\'rmln\'
, password
=
\'qwert1234!@#\'
):
\"\"\"
:param username:
:param password:
:return:
\"\"\"
self
.inputValue(
self
.userNameEle, username)
self
.inputValue(
self
.passWordEle, password)
self
.clickLoginBtn()
# 清空输入框数据
def
clearValue(
self
, element):
empty
=
self
.findElement(
*
element)
empty.clear()
log.logger.info(
\'emptying value.......\'
)
# 推出
def
quit(
self
):
self
.findElement(
*
self
.quitBtn).click()
log.logger.info(
\'quit\'
)
if
__name__
=
=
\'__main__\'
:
pass
7.LoginTC.py(登陆测试用例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
\"\"\"
Code description:login testcase
Create time:
Developer:
\"\"\"
import
unittest
import
time
import
logging
import
sys
from
retail.test_case.models.myunit
import
MyunitTest
from
retail.test_case.models.log
import
Logger
log
=
Logger(__name__, CmdLevel
=
logging.INFO, FileLevel
=
logging.INFO)
class
Login_TC(MyunitTest):
\"\"\"登录模块测试用例\"\"\"
def
test_login_success_correct_username_password(
self
):
\"\"\"用户名正确,密码正确,登录成功\"\"\"
self
.login.loginFunc()
currUrl
=
self
.driver.current_url
# 获取当前的url地址
try
:
self
.assertIn(
\'main\'
, currUrl,
\'main not in current url!\'
)
except
Exception:
self
.login.saveScreenShot(
\'correct_username_password_fail.png\'
)
raise
else
:
self
.login.saveScreenShot(
\'correct_username_password_pass.png\'
)
log.logger.info(
\'%s->run completed! please check the test report\'
%
(sys._getframe().f_code.co_name))
def
test_login_failed_incorrect_username(
self
):
\"\"\"用户名错误,密码正确,登录失败\"\"\"
self
.login.loginFunc(
self
.login.unpwData[
1
][
0
],
self
.login.unpwData[
1
][
1
])
failText
=
self
.login.getFailedText()
self
.assertEqual(
\'输入的用户名或密码错误,请重新输入!\'
, failText,
\'提示信息错误\'
)
log.logger.info(
\'%s->run completed! please check the test report\'
%
(sys._getframe().f_code.co_name))
def
test_login_failed_incorrect_password(
self
):
\"\"\"用户名正确,密码错误,登录失败\"\"\"
self
.login.loginFunc(
self
.login.unpwData[
5
][
0
],
self
.login.unpwData[
5
][
1
])
failText
=
self
.login.getFailedText()
self
.assertEqual(
\'输入的用户名或密码错误,请重新输入!\'
, failText,
\'提示信息错误\'
)
log.logger.info(
\'%s->run completed! please check the test report\'
%
(sys._getframe().f_code.co_name))
def
test_login_failed_username_password_blank(
self
):
\"\"\"用户名为空,密码为空,登录失败\"\"\"
self
.login.loginFunc(
self
.login.unpwData[
6
][
0
],
self
.login.unpwData[
6
][
1
])
failText
=
self
.login.handleAlert()
# 获取alert的提示信息
self
.assertEqual(
\'请填写用户名\'
, failText,
\'提示信息错误\'
)
log.logger.info(
\'%s->run completed! please check the test report\'
%
(sys._getframe().f_code.co_name))
def
test_login_failed_password_blank(
self
):
\"\"\"用户名正确,密码为空,登录失败\"\"\"
self
.login.loginFunc(
self
.login.unpwData[
4
][
0
],
self
.login.unpwData[
4
][
1
])
failText
=
self
.login.handleAlert()
# 获取alert的提示信息
self
.assertEqual(
\'请填写用户密码\'
, failText,
\'提示信息错误\'
)
log.logger.info(
\'%s->run completed! please check the test report\'
%
(sys._getframe().f_code.co_name))
def
test_login_failed_unpw_incorrect(
self
):
\"\"\"用户名错误,密码错误,登录失败\"\"\"
# try:
self
.login.loginFunc(
self
.login.unpwData[
3
][
0
],
self
.login.unpwData[
4
][
0
])
failText
=
self
.login.getFailedText()
self
.assertEqual (
\'输入的用户名或密码错误,请重新输入!\'
, failText,
\'failed\'
)
log.logger.info(
\'%s->run completed! please check the test report\'
%
(sys._getframe().f_code.co_name))
def
test_login(
self
):
\"\"\"循环测试登录功能\"\"\"
for
listitem
in
self
.login.unpwData:
self
.login.inputValue(
self
.login.userNameEle,listitem[
0
])
time.sleep(
2
)
self
.login.inputValue(
self
.login.passWordEle,listitem[
1
])
time.sleep(
2
)
self
.login.clickLoginBtn()
time.sleep(
2
)
if
listitem[
0
]
=
=
\'rmln\'
and
listitem[
1
]
=
=
\'qwert1234!@#\'
:
currUrl
=
self
.driver.current_url
self
.assertIn (
\'main\'
, currUrl)
self
.login.quit()
elif
listitem[
0
]
=
=
\'rmln\'
and
listitem[
1
] !
=
\'qwert1234!@#\'
:
if
listitem[
1
]
=
=
\'\':
failText
=
self
.login.handleAlert()
# 获取alert的提示信息
self
.assertEqual(
\'请填写用户密码\'
, failText,
\'提示信息错误\'
)
else
:
failText
=
self
.login.getFailedText()
self
.assertEqual(
\'输入的用户名或密码错误,请重新输入!\'
, failText,
\'提示信息错误\'
)
elif
listitem[
0
] !
=
\'rmln\'
and
listitem[
1
]
=
=
\'qwert1234!@#\'
:
if
listitem[
0
]
=
=
\'\':
failText
=
self
.login.handleAlert()
# 获取alert的提示信息
self
.assertEqual(
\'请填写用户名\'
, failText,
\'提示信息错误\'
)
else
:
failText
=
self
.login.getFailedText()
self
.assertEqual(
\'输入的用户名或密码错误,请重新输入!\'
, failText,
\'提示信息错误\'
)
elif
listitem[
0
]
=
=
listitem[
1
]
=
=
\'\':
failText
=
self
.login.handleAlert()
# 获取alert的提示信息
self
.assertEqual(
\'请填写用户名\'
, failText,
\'提示信息错误\'
)
else
:
failText
=
self
.login.getFailedText()
self
.assertEqual(
\'输入的用户名或密码错误,请重新输入!\'
, failText,
\'提示信息错误\'
)
log.logger.info(
\'%s->run completed! please check the test report\'
%
(sys._getframe().f_code.co_name))
if
__name__
=
=
\'__main__\'
:
unittest.main()
8.modifypw_page.py(修改密码页面)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
\'\'\'
Code description:modify password page
Create time:
Developer:
\'\'\'
import
logging
import
time
from
selenium.webdriver.common.by
import
By
from
selenium.webdriver.common.action_chains
import
ActionChains
from
retail.test_case.page_obj.base_page
import
BasePage, eleData, modifyPwData
from
retail.test_case.models.log
import
Logger
log
=
Logger(__name__, CmdLevel
=
logging.INFO, FileLevel
=
logging.INFO)
class
PrimaryMenu(BasePage):
\"\"\"密码数据\"\"\"
pwdList
=
\\
[[modifyPwData.readExcel(
1
,
0
), modifyPwData.readExcel(
1
,
1
), modifyPwData.readExcel(
1
,
2
)],
[modifyPwData.readExcel(
2
,
0
), modifyPwData.readExcel(
2
,
1
), modifyPwData.readExcel(
2
,
2
)],
[modifyPwData.readExcel(
3
,
0
), modifyPwData.readExcel(
3
,
1
), modifyPwData.readExcel(
3
,
2
)],
[modifyPwData.readExcel(
4
,
0
), modifyPwData.readExcel(
4
,
1
), modifyPwData.readExcel(
4
,
2
)],
[modifyPwData.readExcel(
5
,
0
), modifyPwData.readExcel(
5
,
1
), modifyPwData.readExcel(
5
,
2
)]]
\"\"\"权限管理下拉菜单\"\"\"
menuPersonal
=
(By.LINK_TEXT, eleData.readExcel(
15
,
3
))
menuModifyPwd
=
(By.LINK_TEXT, eleData.readExcel(
16
,
3
))
\"\"\"密码修改\"\"\"
oldPwd
=
(By.
ID
, eleData.readExcel(
17
,
3
))
newPwd
=
(By.
ID
, eleData.readExcel(
18
,
3
))
commitPwd
=
(By.
ID
, eleData.readExcel(
19
,
3
))
\"\"\"错误提示框及确定\"\"\"
errMessage
=
(By.XPATH, eleData.readExcel(
20
,
3
))
closeBtn
=
(By.CSS_SELECTOR, eleData.readExcel(
21
,
3
))
\"\"\"密码说明\"\"\"
readMe
=
(By.
ID
, eleData.readExcel(
22
,
3
))
\"\"\"保存\"\"\"
saveBtn
=
(By.XPATH, eleData.readExcel(
23
,
3
))
# 主菜单
def
findMenu(
self
,
*
menuList):
\"\"\"
:param menu_list:
:return:
\"\"\"
return
self
.findElement(
*
menuList)
# 旧密码输入框
def
inputOldPw(
self
, oldPwd
=
\'\'):
\"\"\"\"\"\"
try
:
self
.findElement(
*
self
.oldPwd).clear()
self
.findElement(
*
self
.oldPwd).send_keys(oldPwd)
except
Exception:
log.logger.exception(
\'input Pw [%s] for oldPw [%s] fail\'
%
(oldPwd,
self
.oldPwd))
raise
else
:
log.logger.info(
\'inputing Pw [%s] for oldPw [%s] \'
%
(oldPwd,
self
.oldPwd))
# 新密码输入框
def
inputNewPw(
self
, newPwd
=
\'\'):
\"\"\"
:param newPwd:
:return:
\"\"\"
try
:
self
.findElement(
*
self
.newPwd).clear()
self
.findElement(
*
self
.newPwd).send_keys(newPwd)
except
Exception:
log.logger.exception(
\'input Pw [%s] for newPw [%s] fail\'
%
(newPwd,
self
.newPwd))
raise
else
:
log.logger.info(
\'inputing Pw [%s] for newPw [%s] \'
%
(newPwd,
self
.newPwd))
# 确认密码输入框
def
inputConfirmPw(
self
, confirmPwd
=
\'\'):
\"\"\"
:param confirmPwd:
:return:
\"\"\"
try
:
self
.findElement(
*
self
.commitPwd).clear()
self
.findElement(
*
self
.commitPwd).send_keys(confirmPwd)
except
Exception:
log.logger.exception(
\'input Pw [%s] for commitPw [%s] fail\'
%
(confirmPwd,
self
.commitPwd))
raise
else
:
log.logger.info(
\'inputing Pw [%s] for commitPw [%s] \'
%
(confirmPwd,
self
.commitPwd))
# 保存
def
saveButton(
self
):
\"\"\"
:return:
\"\"\"
try
:
self
.driver.implicitly_wait(
5
)
clickbutton
=
self
.findElement(
*
self
.saveBtn)
time.sleep(
1
)
clickbutton.click()
except
Exception:
log.logger.exception(
\'click save button fail\'
)
raise
else
:
log.logger.info(
\'clciking the button\'
)
# 修改密码功能菜单
def
modifyPwMenu(
self
):
\"\"\"
:return:
\"\"\"
try
:
self
.findElement(
*
self
.menuList[
0
]).click()
self
.findElement(
*
self
.menuPersonal).click()
self
.findElement(
*
self
.menuModifyPwd).click()
except
Exception:
log.logger.exception(
\'not found menu [%s]-[%s]-[%s]\'
%
(
self
.menuList[
0
],
self
.menuPersonal,
self
.menuModifyPwd))
raise
else
:
log.logger.info(
\'finding menu [%s]-[%s]-[%s]\'
%
(
self
.menuList[
0
],
self
.menuPersonal,
self
.menuModifyPwd))
self
.driver.implicitly_wait(
2
)
# 修改密码
def
modifyPw(
self
,
list
):
\"\"\"
:param list:
:return:
\"\"\"
try
:
self
.inputOldPw(
list
[
0
])
self
.inputNewPw(
list
[
1
])
self
.inputConfirmPw(
list
[
2
])
self
.saveButton()
except
Exception:
log.logger.exception(
\'input oldpw/newpw/commitpw [%s]/[%s]/[%s] fail\'
%
(
list
[
0
],
list
[
1
],
list
[
2
]))
raise
else
:
log.logger.info(
\'modifing pw [%s]/[%s]/[%s]\'
%
(
list
[
0
],
list
[
1
],
list
[
2
]))
# 错误提示框
def
errorDialog(
self
, commit_btn
=
(By.
ID
,
\'unieap_form_Button_1_unieap_input\'
)):
\"\"\"
:type commit_btn: 元祖
\"\"\"
try
:
messages_frame
=
self
.findElement(
*
self
.errMessage)
text
=
messages_frame.text
element
=
self
.findElement(
*
commit_btn)
time.sleep(
2
)
action
=
ActionChains(
self
.driver)
action.move_to_element(element).perform()
time.sleep(
2
)
element.click()
action.reset_actions()
# 释放鼠标
except
Exception:
log.logger.exception(
\'close errMsgFram [%s] or get text [%s]fail\'
%
(
self
.errMessage))
raise
else
:
log.logger.info(
\'close errMsgFram [%s] and get text [%s] success\'
%
(
self
.errMessage, text))
return
text
# 关闭提示框
def
closeErrMsg(
self
, element):
try
:
ele
=
self
.findElement(
*
element)
action
=
ActionChains(
self
.driver)
action.move_to_element(ele).perform()
time.sleep(
2
)
ele.click()
action.reset_actions()
except
Exception:
log.logger.exception(
\'close the err msg ifram fail\'
, exc_info
=
True
)
raise
else
:
log.logger.info(
\'closing the err msg ifram success!\'
)
if
__name__
=
=
\'__main__\'
:
pass
9.ModifyPw.py(修改密码测试用例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
\'\'\'
Code description:权限管理/个人设置/密码修改 testcase
Create time:
Developer:
\'\'\'
import
time
from
retail.test_case.models.myunit
import
MyunitTest
from
retail.test_case.page_obj.modifypw_page
import
PrimaryMenu
from
retail.test_case.models.strhandle
import
strhandle
class
ModifyPw_TC(MyunitTest):
\"\"\"权限管理/个人设置/密码修改模块测试用例\"\"\"
def
test_menu_is_display(
self
):
\"\"\"主菜单校验\"\"\"
self
.login.loginFunc()
menu
=
PrimaryMenu(
self
.driver)
time.sleep(
4
)
num
=
0
for
menu_item
in
menu.menuList:
# 循环遍历并断言菜单是否正确
self
.assertEqual(menu.menuList[num][
1
],(menu.findMenu(
*
menu_item).text),
\'菜单不存在\'
)
num
=
num
+
1
def
test_modify_password_len(
self
):
\"\"\"旧密码非空,新密码长度小于4位,确认密码非空,修改密码失败,弹窗提示\"\"\"
self
.login.loginFunc()
menu
=
PrimaryMenu(
self
.driver)
menu.modifyPwMenu()
# 查找修改密码页面
menu.modifyPw(menu.pwdList[
0
])
# 修改密码
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'密码长度至少 4 位!\'
, text,
\'提示信息错误\'
)
# 密码长度不满足时断言提示信息
def
test_modify_password_strebgth(
self
):
\"\"\"旧密码非空,新密码长度大于4且强度不够,确认密码非空,修改密码失败,弹窗提示\"\"\"
self
.login.loginFunc()
menu
=
PrimaryMenu(
self
.driver)
menu.modifyPwMenu()
# 查找修改密码页面
menu.modifyPw(menu.pwdList[
1
])
# 修改密码
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'密码强度不够,请重新输入密码!\'
, text,
\' 密码强度不够,请重新输入密码!\'
)
# 密码强度不满足时断言提示信息
def
test_modify_password_incorrect(
self
):
\"\"\"旧密码不正确非空,新密码等于确认密码且满足条件,修改密码失败,弹窗提示\"\"\"
self
.login.loginFunc()
menu
=
PrimaryMenu(
self
.driver)
menu.modifyPwMenu()
# 查找修改密码页面
menu.modifyPw(menu.pwdList[
2
])
# 修改密码
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'旧密码输入错误!\'
, text,
\'旧密码输入错误!\'
)
# 新密码和确认码不同时断言提示信息
def
test_modify_password_difference(
self
):
\"\"\"旧密码非空,新密码不等于确认密码且新密码满足条件,修改密码失败,弹窗提示\"\"\"
self
.login.loginFunc()
menu
=
PrimaryMenu(
self
.driver)
menu.modifyPwMenu()
# 查找修改密码页面
menu.modifyPw(menu.pwdList[
3
])
# 修改密码
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'两次输入的新密码不同!\'
, text,
\'两次输入的新密码不同!\'
)
# 新密码和确认码不同时断言提示信息
def
test_modify_password_all_blank(
self
):
\"\"\"旧密码,新密码,确认密码任意为空,修改密码失败,弹窗提示\"\"\"
self
.login.loginFunc()
menu
=
PrimaryMenu(
self
.driver)
menu.modifyPwMenu()
# 查找修改密码页面
menu.modifyPw(menu.pwdList[
4
])
# 修改密码
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'该输入项的值不能为空!\'
, text,
\' 该输入项的值不能为空!\'
)
# 所有密码均为空时断言提示信息
def
test_modify_password(
self
):
\"\"\"循环校验提示信息\"\"\"
self
.login.loginFunc()
menu
=
PrimaryMenu(
self
.driver)
menu.modifyPwMenu()
# 查找修改密码页面
error_list
=
[]
for
list
in
range
(
len
(menu.pwdList)):
menu.modifyPw(menu.pwdList[
list
])
if
menu.isElementExist(menu.errMessage):
text
=
menu.errorDialog(menu.closeBtn)
# 这里只判断是否有提示框弹出,如有说明修改失败,没有或者其他提示框默认为修改成功
error_list.append(text)
else
:
self
.assertTrue(menu.isElementExist(
*
menu.errMessage),
\'error fram not exist, please open bug\'
)
self
.assertEqual(
\'密码长度至少 4 位!\'
,error_list[
0
],
\'log infomation error!\'
)
self
.assertEqual(
\'密码强度不够,请重新输入密码!\'
, error_list[
1
],
\'log infomation error!\'
)
self
.assertEqual(
\'旧密码输入错误!\'
, error_list[
2
],
\'log infomation error!\'
)
self
.assertEqual(
\'两次输入的新密码不同!\'
, error_list[
3
],
\'log infomation error!\'
)
self
.assertEqual(
\'该输入项的值不能为空!\'
, error_list[
4
],
\'log infomation error!\'
)
def
test_modifypw(
self
):
\"\"\"循环测试修改密码功能\"\"\"
self
.login.loginFunc()
# 登录
menu
=
PrimaryMenu(
self
.driver)
menu.modifyPwMenu()
# 查找修改密码页面
for
item
in
menu.pwdList:
menu.modifyPw(item)
if
menu.isElementExist(menu.errMessage):
# 如果存在提示框 再断言提示信息是否正确
if
item[
0
] !
=
\'
\' and len(item[1]) < 4 and item[2] !=\'
\':
# 新密码长度校验
text
=
menu.errorDialog(menu.closeBtn)
try
:
self
.assertEqual(
\'密码长度至少 4 位!\'
,text,
\'the message incorrect!\'
)
except
Exception:
menu.saveScreenShot(
\'fail_密码长度.png\'
)
raise
elif
item[
0
] !
=
\'
\' and len(item[1]) >= 4 and item[2] !=\'
\': # 新密码强度校验 [\'
a
\', \'
qwert
\', \'
qwert\'],
lowercase, uppercase, number, other
=
strhandle(item[
1
])
if
lowercase >
0
and
uppercase >
0
and
number
=
=
0
and
other
=
=
0
:
# 小写 大写
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'密码强度不够,请重新输入密码!\'
, text,
\' 密码强度不够,请重新输入密码!\'
)
elif
uppercase >
0
and
other >
0
and
number
=
=
0
and
lowercase
=
=
0
:
# 大写 特殊字符
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'密码强度不够,请重新输入密码!\'
, text,
\' 密码强度不够,请重新输入密码!\'
)
elif
lowercase >
0
and
other >
0
and
number
=
=
0
and
uppercase
=
=
0
:
# 小写 特殊字符
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'密码强度不够,请重新输入密码!\'
, text,
\' 密码强度不够,请重新输入密码!\'
)
elif
lowercase
=
=
0
and
other
=
=
0
and
number >
0
and
uppercase >
0
:
# 大写 数字
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'密码强度不够,请重新输入密码!\'
, text,
\' 密码强度不够,请重新输入密码!\'
)
elif
lowercase >
0
and
other
=
=
0
and
number >
0
and
uppercase
=
=
0
:
# 小写 数字
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'密码强度不够,请重新输入密码!\'
, text,
\' 密码强度不够,请重新输入密码!\'
)
elif
lowercase >
0
and
other
=
=
0
and
number
=
=
0
and
uppercase
=
=
0
:
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'密码强度不够,请重新输入密码!\'
, text,
\' 密码强度不够,请重新输入密码!\'
)
elif
lowercase
=
=
0
and
other >
0
and
number
=
=
0
and
uppercase
=
=
0
:
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'密码强度不够,请重新输入密码!\'
, text,
\' 密码强度不够,请重新输入密码!\'
)
elif
lowercase
=
=
0
and
other
=
=
0
and
number >
0
and
uppercase
=
=
0
:
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'密码强度不够,请重新输入密码!\'
, text,
\' 密码强度不够,请重新输入密码!\'
)
elif
lowercase
=
=
0
and
other
=
=
0
and
number
=
=
0
and
uppercase >
0
:
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'密码强度不够,请重新输入密码!\'
, text,
\' 密码强度不够,请重新输入密码!\'
)
elif
item[
0
] !
=
\'qwert1234!@#\'
and
item[
1
]
=
=
item[
2
]:# >
=
4
lowercase, uppercase, number, other
=
strhandle(item[
1
])
if
(lowercase >
0
and
uppercase >
0
and
number >
0
)
or
(
lowercase >
0
and
uppercase >
0
and
other >
0
)
or
(
number >
0
and
other >
0
and
lowercase >
0
)
or
(
number >
0
and
other >
0
and
uppercase >
0
):
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'旧密码输入错误!\'
, text,
\'旧密码输入错误!\'
)
# 新密码和确认码不同时断言提示信息
elif
item[
0
]
=
=
\'qwert1234!@#$\'
and
item[
1
] !
=
item[
2
]:#
and
item[
1
] >
=
4
:
lowercase, uppercase, number, other
=
strhandle(item[
1
])
if
(lowercase >
0
and
uppercase >
0
and
number >
0
)
or
(
lowercase >
0
and
uppercase >
0
and
other >
0
)
or
(
number >
0
and
other >
0
and
lowercase >
0
)
or
(
number >
0
and
other >
0
and
uppercase >
0
):
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'两次输入的新密码不同!\'
, text,
\' 两次输入的新密码不同!\'
)
else
:
print
(
\'test value incorrect! please check it\'
)
elif
item[
0
]
=
=
\'
\' or item[1] ==\'
\' or item[2] ==\'
\':
# 输入项为空校验
text
=
menu.errorDialog(menu.closeBtn)
self
.assertIn(
\'该输入项的值不能为空!\'
, text,
\' 该输入项的值不能为空!\'
)
# 所有密码均为空时断言提示信息
else
:
self
.assertTrue(menu.isElementExist(menu.errMessage),
\'error fram not exist, please check the test value or file bug\'
)
if
__name__
=
=
\'__main__\'
:
pass
10.RunTc.py(执行测试用例)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#! user/bin/python
\'\'\'
Code description:auto run test case
Create time:
Developer:
\'\'\'
import
unittest
import
time
from
BeautifulReport
import
BeautifulReport
from
retail.config.conf
import
*
from
retail.test_case.models.testreport
import
testreport
# TODO : will be use jenkins continuous intergration teachnology manage the auto project
if
__name__
=
=
\'__main__\'
:
# currTime = time.strftime(\'%Y-%m-%d %H_%M_%S\')
# filename = currTime + \'.html\'
# # 第一种测试报告
# test_suite = unittest.defaultTestLoader.discover(tcPath, pattern=\'*Tc.py\')
# result = BeautifulReport(test_suite)
# result.report(filename= filename, description=\'test report\', log_path=reportPath)
# # 第二种测试报告
runner, fp, fileName
=
testreport()
test_suite
=
unittest.defaultTestLoader.discover(tcPath, pattern
=
\'LoginTc.py\'
)
runner.run(test_suite)
fp.close()
11.备注
from BeautifulReport import BeautifulReport 这个报告需要自己网上找一下(很多类似的测试报告源码,不一定非使用本案例中的报告模板)
12.输出结果展示
1.创建规则失败时截图
2.登录成功截图
3.用例执行日志
4.测试报告
最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走! 希望能帮助到你!【100%无套路免费领取】