PO封装设计模式 -- Web页面端测试
一、已登录页面 -->新建PO封装的包 -- 以下源码适用于python3以上的版本
代码优化新增 Image -->对操作步骤进行截图
二、basepage 包基础类的封装如下:
from selenium.webdriver.support.wait import WebDriverWait #显示等待
from selenium.webdriver.support import expected_conditions as EC #判断元素是否定位到
#页面的基础类 -->为后续类调用
class HomePage():
'''构造方法'''
def __init__(self,url,dr):
self.url = url
self.dr = dr
#封装元素定位方式
def find_element(self,*loc):
try:
#入参本身就是元组 不需要加*
WebDriverWait(self.dr,10).until(EC.visibility_of_element_located(loc))
return self.dr.find_element(*loc)
except:
print(*loc + '元素定位在页面中无法找到')
三、page 包封装登录页面的类如下:
from selenium.webdriver.common.by import By #定位方式
from time import sleep
from TestCase.Gjs_Po.basepage.HomePage import *
#登录页面的类
class GjsLoginPage(HomePage):
#定位器
#输入账号
username_loc = (By.ID,"mobilePhone")
# 输入密码
password_loc = (By.ID,"password")
# 点击登录按钮
loginButton_loc = (By.CSS_SELECTOR,"#loginBtn")
# 登录后验证信息
loginInfo_loc = (By.CSS_SELECTOR,'#realName')
# 点击安全登录
logout_loc = (By.CSS_SELECTOR,"a.fc-blue.mr-5")
#用户名为空 --获取错误信息
userNull_loc = (By.CSS_SELECTOR, "span.error")
#密码为空 --获取错误信息
passwordNull_loc = (By.CSS_SELECTOR, "span.error")
#用户名输入非法字符--获取错误信息
usernameFeifa_loc = (By.CSS_SELECTOR, "span.error")
#打开登录页面
def openLoginPage(self):
self.dr.get(self.url)
self.dr.refresh()
self.dr.maximize_window()
sleep(0.5)
#输入用户名
def input_username(self,username):
#注意 self前面加上 *
self.find_element(*self.username_loc).send_keys(username)
#输入密码
def input_password(self,password):
self.find_element(*self.password_loc).send_keys(password)
#点击登录按钮
def click_btn(self):
self.find_element(*self.loginButton_loc).click()
##登录后验证信息
def getInfo(self):
return self.find_element(*self.loginInfo_loc).text
#点击安全退出
def logout_btn(self):
self.find_element(*self.logout_loc).click()
#用户名为空
def usernameNull(self):
return self.find_element(*self.userNull_loc).text
#密码为空
def passwordNull(self):
return self.find_element(*self.passwordNull_loc).text
#用户名输入非法字符--获取错误信息
def userFeiFa(self):
return self.find_element(*self.usernameFeifa_loc).text
四、common 登录用到的数据封装Helper类 如下:
import xlrd
import os
import logging
import time
class Helper(object):
def readExcels(self,nrow):
# 读取Excel数据 nrow是输入的行数
table = xlrd.open_workbook('D:\Project\TestCase\Gjs_Po\data\Gjsinfo.xlsx', 'r')
sheet = table.sheet_by_index(0)
return sheet.row_values(nrow)
def readusername(self,nrow):
# 读取用户名
return str(self.readExcels(nrow)[0]) # 强制转换为str
def readpassword(self,nrow):
# 读取密码
return str(self.readExcels(nrow)[1])
def readAssertText(self,nrow):
# 读取预期结果
return str(self.readExcels(nrow)[2])
def dirName(self,filename=None,filePath=None):
#定义日志文件 filename = log.md 为存储日志
return os.path.join(os.path.dirname(os.path.dirname(__file__)),filePath,filename)
def log(self,log_content):
'''日志定义级别'''
# 定义文件
logFile = logging.FileHandler(self.dirName('logInfo.md','log'), 'a',encoding='utf-8')
# log格式
fmt = logging.Formatter(fmt='%(asctime)s-%(name)s-%(levelname)s-%(module)s:%(message)s')
logFile.setFormatter(fmt)
# 定义日志
logger1 = logging.Logger('logTest', level=logging.DEBUG)
logger1.addHandler(logFile)
logger1.info(log_content)
logFile.close()
def SaveImage(self,driver,Filename):
"""用例失败截图"""
Rawpath = os.path.join(os.path.dirname(os.path.dirname(__file__)),"Image")
NewPicture = Rawpath + "\\" + time.strftime("%Y_%m_%d_%H_%M_%S") + "_" + Filename
driver.get_screenshot_as_file(NewPicture)
测试固件分离:
from selenium import webdriver
from TestCase.Gjs_Po.page.GjsLoginpage import *
import unittest
class MyunitTests(unittest.TestCase):
def setUp(self)-> None:
self.url = 'https://www.gjfax.com/toLogin'
self.dr = webdriver.Chrome()
self.dr.implicitly_wait(10)
#实例化一个对象
self.loginpage = GjsLoginPage(self.url,self.dr)
def tearDown(self)-> None:
self.dr.quit()
五、testCases 测试用例封装,继承unittest、Helper类,如下:
from TestCase.Gjs_Po.common.helper import *
from TestCase.Gjs_Po.common.ownUnit import *
import unittest
#类的继承
class GjsTestLogin(MyunitTests,Helper):
#测试正常的登录
def test_login_success(self):
#打开登录页面
self.loginpage.openLoginPage()
self.log('测试正常:自动化测试 -->打开登录页面')
#输入用户名
self.loginpage.input_username(self.readusername(1))
self.log('测试正常:自动化测试 -->输入用户名')
#输入密码
self.loginpage.input_password(self.readpassword(1))
self.log('测试正常:自动化测试 -->输入密码')
#点击登录
self.loginpage.click_btn()
self.log('测试正常:自动化测试 -->点击登录')
#断言
self.assertEqual(self.loginpage.getInfo(),self.readAssertText(1))
self.log('测试正常:自动化测试 -->断言登录后信息是否符合预期')
self.SaveImage(self.dr,"login_success.png")
#点击退出
self.loginpage.logout_btn()
self.log('测试正常:自动化测试 -->点击安全退出')
self.log('第一条用例执行结束')
#测试密码为空
def test_password_null(self):
# 打开登录页面
self.loginpage.openLoginPage()
self.log('测试密码为空:自动化测试 -->点击登录页面')
# 输入用户名
self.loginpage.input_username(self.readusername(2))
self.log('测试密码为空:自动化测试 -->输入用户名')
# 不输入密码
self.loginpage.input_password(self.readpassword(2))
self.log('测试密码为空:自动化测试 -->不输入密码')
# 点击登录
self.loginpage.click_btn()
self.log('测试密码为空:自动化测试 -->点击登录')
# 断言
self.assertEqual(self.loginpage.passwordNull(), self.readAssertText(2))
self.log('测试密码为空:自动化测试 -->断言密码为空信息是否符合预期')
self.SaveImage(self.dr,"login_passwordNull.png")
self.log('第二条用例执行结束')
#测试用户名为空
def test_username_null(self):
# 打开登录页面
self.loginpage.openLoginPage()
self.log('测试用户名为空:自动化测试 -->点击登录页面')
# 输入用户名
self.loginpage.input_username(self.readusername(3))
self.log('测试用户名为空:自动化测试 -->不输入用户名')
# 输入密码
self.loginpage.input_password(self.readpassword(3))
self.log('测试用户名为空:自动化测试 -->输入密码')
# 点击登录
self.loginpage.click_btn()
self.log('测试用户名为空:自动化测试 -->点击登录')
# 断言
self.assertEqual(self.loginpage.usernameNull(), self.readAssertText(3))
self.log('测试用户名为空:自动化测试 -->断言用户名为空信息是否符合预期')
self.SaveImage(self.dr,"login_usernameNull.png")
self.log('第三条用例执行结束')
#测试用户名输入非法字符
def test_username_Feifa(self):
# 打开登录页面
self.loginpage.openLoginPage()
self.log('测试用户名输入非法:自动化测试 -->点击登录页面')
# 输入非法用户名
self.loginpage.input_username(self.readusername(4))
self.log('测试用户名输入非法:自动化测试 -->输入非法用户名')
# 输入密码
self.loginpage.input_password(self.readpassword(4))
self.log('测试用户名输入非法:自动化测试 -->输入密码')
# 点击登录
self.loginpage.click_btn()
self.log('测试用户名输入非法:自动化测试 -->点击登录')
# 断言
self.assertEqual(self.loginpage.userFeiFa(), self.readAssertText(2))
self.log('测试用户名输入非法:自动化测试 -->断言用户名输入非法信息是否符合预期')
self.SaveImage(self.dr,"login_usernameFeifa.png")
self.log('第四条用例执行结束')
if __name__ == '__main__':
unittest.main(verbosity=2)
六、mail邮件的类封装如下:
import smtplib
import os
from email.mime.multipart import MIMEMultipart #邮件附件类
from email.mime.text import MIMEText #邮件模板类
from email.header import Header #邮件头部模板
#发送带附件的函数
def semd_mail(file_new):
with open(file_new, "rb") as fp:
mail_body = fp.read()
#基本信息
smtpserver = "smtp.163.com"
port = 25
sender = "1879781xxxx@163.com"
psw = "qqqxxx" #163邮箱密码
receiver = "1512500xxx@qq.com"
#定义邮箱主题
msg = MIMEMultipart()
msg['subject'] = Header(u"自动化测试报告","utf-8")
msg['from'] = sender
msg["to"] = receiver
#不加msg['from'] msg["to"]会报错,是因为"收件人和发件人没有定义"
#HTML 邮件正文,直接发送附件的代码
body = MIMEText(mail_body,"html","utf-8")
msg.attach(body)
# 附件
att = MIMEText(mail_body,"base64","utf-8")
att["Content-Type"] = "application/octet-stream"
att["Content-Disposition"] = 'attachment; filename="test_report.html'
msg.attach(att)
#链接邮件服务器发送邮件
try:
smtp = smtplib.SMTP()
smtp.connect(smtpserver) # 连服务器
smtp.login(sender, psw)
except:
smtp = smtplib.SMTP_SSL(smtpserver, port)
smtp.login(sender, psw) # 登录
smtp.sendmail(sender, receiver, msg.as_string()) # 发送
print("邮件发送成功")
smtp.quit()
#查找最新的邮件
def new_file(report_path):
result_path = report_path
lists = os.listdir(result_path)
lists.sort() #从小到大排序
file = [x for x in lists if x.endswith(".html")]
file_new_name = os.path.join(result_path,file[-1])
return file_new_name
七、runAllcase.py 一键执行测试用例 Main()执行
from TestCase.Gjs_Po.common.HTMLTestRunner import *
from TestCase.Gjs_Po.mail.sendmail163 import *
#实现的逻辑
#先生成测试报告
#查找最新的测试报告文件,通过new_file函数找到最新的测试报告,把返回的结果return file_new_name
#把new_file函数,file_new_name文件传入到send_mail 读取出来,然后以邮件的附件形式加载到邮件模板中,设置参数,链接服务器发送最新的测试报告#
if __name__ == '__main__':
report = os.path.dirname(__file__) #D:/Project/TestCase/Gjs_Po
test_path = os.path.join(report,"testcase") #测试用例文件夹
suite = unittest.defaultTestLoader.discover(
start_dir=test_path,pattern="Gjs_login*.py",top_level_dir=None)
report_path = os.path.join(report,"report") #测试报告文件夹
if not os.path.exists(report_path):
os.mkdir(report_path)
else:
print('存在report报告文件夹')
now = time.strftime("%Y-%m-%d %H_%M_%S") #时间戳
file_name = report_path + '\\' + now + "report_test.html" #测试报告文件名
fp = open(file_name,"wb")
runner = HTMLTestRunner(
stream = fp,
title = 'GJs自动化测试报告',
description = 'u"系统环境:Windows7 浏览器:Chrome 用例执行情况:"'
)
runner.run(suite) #执行测试用例
fp.close()
new_report = new_file(report_path) #获取最新的报告文件
semd_mail(new_report) #发送最新的测试报告
PO封装设计模式 -- Web页面端测试的更多相关文章
- PO封装设计模式 -- App移动端测试
前言: 一.App_Po 封装 (用互联网上随便一个app进行) base 存放的是页面基础类,后续的类需继承基础类 common 存放的是公共部分,测试固件分离部分,新增截图功能部分 Data 存放 ...
- Web页面速度测试工具
开发框架的时间,想测试单例和多例下对性能的影响,找了下没有特别简单易用的测试工具. 估摸着搞了一个小工具. 针对.net Framework的2.0,3.5,4.0版本. WebHttpTest2.0 ...
- [转]移动端web页面使用字体的思考
一直不知道手机端用的什么字体,只是觉得类似雅黑,直到有一次设计师问到设计移动web页面该用什么字体才严肃地想起这个问题. 前人已栽树,后人我就直接转来吧…… 回想2年前刚开始接触手机项目,接到PSD稿 ...
- web端测试和移动端测试的区别小记
转:http://qa.blog.163.com/blog/static/19014700220157128345318/ 之前一直参与web端的测试,最近一个项目加入了移动端,本人有幸参与了移动端的 ...
- 移动端web页面滚动不流畅,卡顿闪烁解决方案
移动端web页面滚动不流畅,卡顿闪烁解决方案 1.ios端的-webkit-overflow-scrolling属性可控制页面滚动效果,设置如下实现惯性滚动和弹性效果: -webkit-overf ...
- Web端测试和移动端测试
之前参加的项目有涉及Web端测试和移动端测试,简单的记录下他们之间的区别: 1.记录bug 在Web端可以通过系统自带的截图和QQ截图等方式来截取bug的图片,对于错误的地方可以用工具自带的标识来 ...
- APP端测试与web端测试的区别
想要知道APP端测试与web端测试的区别 ,那么我们就要先来了解,web和app的区别. web项目,一般都是b/s架构,基于浏览器的,而app则是c/s的,必须要有客户端.那么在系统测试测试的时候就 ...
- web端,app端,小程序端测试差异详解
前置解释:1.单纯从功能测试的层面上来讲的话,APP 测试.web 测试和H5测试在流程和功能测试上是没有区别的2.Web项目或pc项目都是在电脑上进行测试的.常见的PC项目架构有BS架构和CS架构的 ...
- 移动端WEB页面
百度前端技术学院第一阶段任务十一,关于移动端WEB页面布局,参考资料如下(都是一些网页链接): MDN:手机网页开发 MDN:在移动浏览器中使用viewport元标签控制布局 移动前端开发和 Web ...
随机推荐
- ContOS8 使用yum安装MariaDB
首先全部删除MySQL/MariaDB(若是首次安装可根据需要跳过此步) 若不清楚MySQL和MariaDB的关系请移步至 Mariadb百科 1.查看系统版本(以下任一命令即可). # cat /p ...
- Python小白的数学建模课-06 固定费用问题
Python 实例介绍固定费用问题的建模与求解. 学习 PuLP工具包中处理复杂问题的快捷使用方式. 『Python小白的数学建模课 @ Youcans』带你从数模小白成为国赛达人. 前文讲到几种典型 ...
- 『无为则无心』Python基础 — 2、编译型语言和解释型语言的区别
目录 1.什么是计算机语言 2.高级语言中的编译型语言和解释型语言 (1)编译型语言 (2)解释型语言 (3)编译型语言和解释型语言执行流程 3.知识扩展: 4.关于Python 1.什么是计算机语言 ...
- Paxos 图解 (秒懂)
文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...
- 纯小白干货:Java import以及Java类的搜索路径
如果你希望使用Java包中的类,就必须先使用import语句导入.import语句与C语言中的 #include 有些类似,语法为:import package1[.package2-].classn ...
- WEB安全漏洞扫描与处理(上)——安全漏洞扫描工具AppScan的安装使用
很多公司对软件会有安全的要求,一般测试公司会使用安全漏洞扫描工具对软件进行漏扫,然后给出安全报告,然后软件开发人员会根据提供的安全报告进行漏洞的处理.我们接触到的测评公司,使用的是漏洞扫描工具AppS ...
- OO unit1 summary
Unit 1 summary 一.前言 三周左右的学习,OO第一单元顺利结束了,个人认为有必要写个blog来反思总结一下自己第一单元的学习情况,以便更好地进行后面的学习. 之前从来没有写blog的习惯 ...
- Qt之先用了再说系列-信号与槽
QT之信号与槽 简介:信号与槽可是Qt最大成功点,也是整个Qt基本核心机制,如果不会信号与槽,将无法领略Qt之美: 1.信号与槽函数原型: QObject::connect(const QObject ...
- 一QT获取当前时间和日期
获取日期和时间使用QDateTime类,该类中有一个静态成员函数可以返回当前的时间信息 我们可以直接调用这个静态函数获取当前时间 QDateTime time = QDateTime::current ...
- 详解C++中继承的基本内容
有些类与类之间存在特殊的关系,有共性也有特性,比如动物类可以细分为猫,狗等.下级别的成员除了拥有上一级的共性,还有自己的特性,这个时候就可以考虑继承的技术,减少重复代码. 一.继承中的对象模型 1.1 ...