先来一张图,看看整个Po架构的实现:

operatePages:操作页面,也就是把每一个操作页面,写成一个类。

pages:用来存放公共配置文件的一个目录。比如基础类,后续所有类都会用到基础类。

reports:用来存放生成的测试报告。

testCases:用例存放目录。用来存放测试用例的目录。

1.我们先看page类的实现

from selenium.webdriver.support.wait import WebDriverWait
#from selenium.webdriver.support import expected_conditions as EC
#页面基类
class HomePage():
#初始化页面属性
def __init__(self,url,driver):
self.url = url
self.dr = driver #封装元素定位方式
def find_element(self,*loc):
###----- 确保元素是可见的。
try:
#以下入参本身是元组,不需要加*
#WebDriverWait(self.dr,).until(EC.visibility_of_element_located(loc))
#以下入参为元组的元素,需要加*
WebDriverWait(self.dr,).until(lambda dr:dr.find_element(*loc).is_displayed())
return self.dr.find_element(*loc)
except:
print(*loc+"元素在页面中未找到!")

整个page类中,我们队浏览器的驱动和地址进行了初始化动作,因为后续的用例在执行时都会使用该方法。

在基础类Homepage类中,我们把元素定位的方法进行了改写,后续的所有元素定位都可以使用基础类中的find_element方法。

二、我们针对登陆页面写一个类,该类继承继承类的一些属性和方法,下面我们来看整个类的实现:

from selenium.webdriver.common.by import By
from time import sleep
import sys sys.path.append("../pages/")
from homePage import * class LoginPage(HomePage):
#元素定位器,定位页面的元素
#用户名
username_loc = (By.ID,"mobilePhone")
#密码
passwd_loc = (By.ID,"password")
#登陆按钮
loginBtn_loc = (By.CSS_SELECTOR,"a.btn.btn-block.fs-16")
#退出链接
logoutBtn_loc = (By.CSS_SELECTOR,"a.fc-blue.mr-5")
#用户名为空的提示信息
userNull_loc = (By.CSS_SELECTOR,"#error > span")
#密码为空的提示信息
passWordNull_loc = (By.CSS_SELECTOR,"#error > span") #打开登陆页面
def openLoginPage(self):
self.dr.get(self.url)
sleep(0.5)
self.dr.refresh()
self.dr.maximize_window()
sleep(0.05)
#操作元素
#输入用户名
def input_userName(self,userName):
self.find_element(*self.username_loc).send_keys(userName)
#输入密码
def input_passWord(self,passWord):
self.find_element(*self.passwd_loc).send_keys(passWord)
#点击登陆按钮
def click_loginBtn(self):
self.find_element(*self.loginBtn_loc).click()
#获取登陆成功后的提示信息
def get_assertText(self):
return self.find_element(*self.logoutBtn_loc).text
#用户名为空的提示信息
def get_userNullText(self):
return self.find_element(*self.userNull_loc).text
#密码为空的提示信息
def get_passWordNullText(self):
return self.find_element(*self.passWordNull_loc).text

1.operatepages类继承的是Homepage基础类;

2.我们在登陆页面,我们把所有的登陆页面需要操作的方法都封装成方法,好处是可以方便用例层去调用。类似模块的作业,当调用时可以直接传递对应的参数就好了。。

3.封装断言文本信息方法 比如  登陆成功后的信息、用户名为空的信息、密码为空的情况

三、testLogin.py文件实现代码:

from selenium import webdriver
from time import sleep
import unittest,sys sys.path.append("../operatePages/")
sys.path.append("../pages/")
sys.path.append("./")
from operateLoginPage import *
from homePage import * #导入xlrd模块
import xlrd
#、打开excel
data = xlrd.open_workbook(r"E:\untitled\testCases\参数化数据.xlsx")
#读取用户名和密码所在的页面的数据
sheet1 = data.sheet_by_index()
#获取用户名
userNames = sheet1.col_values()
#获取密码
passWords = sheet1.col_values()
#获取预期结果
exceptResults = sheet1.col_values() class TestLogin(unittest.TestCase):
def setUp(self):
self.url = "https://www.gjfax.com/toLogin"
self.dr = webdriver.Chrome()
self.dr.implicitly_wait()
#实例化一个operateLoginPage类的对象
self.loginPage = LoginPage(self.url,self.dr) #测试正常登陆
def testLogin(self):
#打开登陆页面
self.loginPage.openLoginPage()
#输入用户名
self.loginPage.input_userName(userNames[])
#输入密码
self.loginPage.input_passWord(passWords[])
#点击登陆
self.loginPage.click_loginBtn()
#断言
self.assertEqual(exceptResults[],self.loginPage.get_assertText()) #测试用户名为空
def test_user_null(self):
#打开登陆页面
self.loginPage.openLoginPage()
#输入用户名
self.loginPage.input_userName(userNames[])
#输入密码
self.loginPage.input_passWord(passWords[])
#点击登陆
self.loginPage.click_loginBtn()
#断言
self.assertEqual(exceptResults[],self.loginPage.get_userNullText()) #测试密码为空
def test_password_null(self):
#打开登陆页面
self.loginPage.openLoginPage()
#输入用户名
self.loginPage.input_userName(userNames[])
#输入密码
self.loginPage.input_passWord(passWords[])
#点击登陆
self.loginPage.click_loginBtn()
#断言
self.assertEqual(exceptResults[],self.loginPage.get_passWordNullText()) def tearDown(self):
self.dr.quit() if __name__=="__main__":
unittest.main()

四、总执行文件:

import unittest
from HTMLTestRunner import HTMLTestRunner
import time import sys
#临时改变工作路径
sys.path.append("./operatePages/")
sys.path.append("./pages/")
from operateLoginPage import *
from homePage import * if __name__ == "__main__":
#定义测试用例所在的路径
casesPath = "./testCases/"
#定义测试报告所在的路径
reportPath = "./reports/"
#定义测试报告的名称
reportName = time.strftime("%Y-%m-%d %H%M%S",time.localtime()) + '.html'
#定义测试报告所在的路径和名称
reportPathName = reportPath + reportName
#把测试用例组装到unittest的discover容器
discover = unittest.defaultTestLoader.discover(casesPath,"*.py")
#打开测试报告,并赋予读写权限
fp = open(reportPathName,"wb")
#把测试结果写进测试报告,并装载到HTHMLTestRunner模块
run = HTMLTestRunner(stream=fp,title="ecshop自动化测试报告",description="用例执行情况")
#运行脚本
run.run(discover)
#关闭打开的测试报告
fp.close()

纯文本邮件:

#!/usr/bin/python3

import smtplib
from email.mime.text import MIMEText
from email.header import Header # 第三方 SMTP 服务
mail_host="smtp.qq.com" #设置服务器
mail_user="xxxxx@qq.com" #用户名
mail_pass="ctludyhhtzecbggg" #口令 sender = 'xxxxx@qq.com'
receivers = ['xxxx@163.com'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱 message = MIMEText('Python 邮件发送测试...', 'plain', 'utf-8')
message['From'] = Header("xxx自动化提升班", 'utf-8')
message['To'] = Header("测试", 'utf-8') subject = 'xxxx自动化提升班 -- 邮件发送测试'
message['Subject'] = Header(subject, 'utf-8') try:
smtpObj = smtplib.SMTP()
smtpObj.connect(mail_host)
smtpObj.login(mail_user,mail_pass)
smtpObj.sendmail(sender, receivers, message.as_string())
print ("邮件发送成功")
except smtplib.SMTPException:
print ("无法发送邮件")

带附件邮件:

from HTMLTestRunner import HTMLTestRunner
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
import smtplib
import unittest
import time
import os import sys
sys.path.append("./operatePages/")
sys.path.append("./pages/") #定义发送邮件
def send_mail(file_new,fileName):
f = open(file_new, 'rb').read()
att = MIMEText(f, 'base64', 'utf-8')
#att = MIMEText(f, 'plain', 'utf-8')
att["Content-Type"] = 'application/octet-stream'
#附件名称
att["Content-Disposition"] = 'attachment;filename='+fileName
msgRoot = MIMEMultipart("related")
#邮件标题
msgRoot['Subject'] = Header('ECSHOP自动化测试报告', 'utf-8')
msgRoot['from'] = 'xxxx@qq.com'
msgRoot['to'] = 'xxxxx@163.com'
#msgRoot['from'] = '发送邮件的邮箱用户名'
#msgRoot['to'] = '接收邮件的邮箱用户名'
msgRoot.attach(att) #使用QQ邮箱进行邮件发送
try:
smtp = smtplib.SMTP()
smtp.connect('smtp.qq.com',)
smtp.login('xxxxx@qq.com', 'ctludyhhtzecbggg')
smtp.sendmail('xxxxxxxxxx@qq.com', 'xxxxx@163.com', msgRoot.as_string())
#smtp.login('发送邮件的邮箱用户名', '邮箱的登录密码')
#smtp.sendmail('发送邮件的邮箱用户名', '接收邮件的邮箱用户名', msgRoot.as_string())
smtp.quit()
print("邮件发送成功!")
except:
print("邮件发送失败!") #查找目录
def new_report(testreport):
lists = os.listdir(testreport)
lists.sort(key=lambda fn : os.path.getmtime(testreport + "\\" + fn))
file_new = os.path.join(testreport,lists[-])
print(file_new)
return file_new if __name__ == '__main__':
#定义测试用例的存放路径
test_dir = "./testCases/"
#把测试用例加入 discover 容器
discover = unittest.defaultTestLoader.discover(start_dir=test_dir,pattern='*.py') #定义测试报告的存放路径
testReportDir = "./reports/"
#定义测试报告的名字
nowTime = time.strftime("%Y-%m-%d%H%M%S", time.localtime())
fileName = nowTime+".html"
#定义测试路径和测试报告名字
testReportDir_FileName = testReportDir + fileName #打开文件,并赋予可写权限
fp = open(testReportDir_FileName,"wb")
#把测试结果写进测试报告,并装载到HTHMLTestRunner模块
runner = HTMLTestRunner(stream = fp ,title = "ERP自动化测试报告",description="用例执行情况:")
#运行测试用例
runner.run(discover)
#关闭文件
fp.close() #发送邮件
new_report = new_report(testReportDir)
send_mail(new_report,fileName)

整个架构图:

operatePages:操作页面,也就是把每一个操作页面,写成一个类。

pages:用来存放公共配置文件的一个目录。比如基础类,后续所有类都会用到基础类。

reports:用来存放生成的测试报告。

testCases:用例存放目录。用来存放测试用例的目录。

Selenium-PO设计模式的更多相关文章

  1. 基于Python Selenium Unittest PO设计模式详解

    本文章会讲述以下几个内容: 1.什么是PO设计模式(Page Object Model) 2.为什么要使用PO设计模式 3.使用PO设计模式要点 4.PO设计模式实例 1.什么是PO设计模式 (Pag ...

  2. Python Selenium设计模式 - PO设计模式

    整理一下python selenium自动化测试实践中使用较多的po设计模式. 为什么要用PO 基于python selenium2开始开始ui自动化测试脚本的编写不是多么艰巨的任务.只需要定位到元素 ...

  3. selenium自动化测试框架之PO设计模式

    面向对象的特性:封装.继承.多态.在自动化中一样适用,Selenium自动化测试中有一个名字常常被提及PageObject(思想与面向对象的特性相同),通过PO模式可以大大提高测试用例的维护效率. 传 ...

  4. 我所理解的selenium之PO设计模式

    下午,花了点时间来整理UI自动化设计,就把我所理解的PO设计模式项目结构脑图整理如下,有不对的地方还望多多包涵.谢谢

  5. (Python)PO设计模式

    无规矩不成方圆.编写代码也是,如果没有大概的框架,管理代码将会是一件很头疼的事. 先看看笔者以前写的python脚本: 如果只有一个用例,这样看着好像挺整洁的.但是当用例越来越多后,如果元素定位发生了 ...

  6. UI自动化实战进阶PO设计模式

    前言 经过前面的实战我们已经编写了几个测试用例,下面我们要用PO设计模式来调整我们的代码,让页面元素和测试业务进行分离,这样看起来直观而且后期的维护也方便. python有一个第三方的PO设计的库,既 ...

  7. Web自动化测试—PO设计模式(二)

    PO设计模式要点一:页面类都继承于BasePage 目录结构 ui_auto_test --src --pages --__init__.py --base_page.py --login_page. ...

  8. Python selenium PO By.XPATH定位元素报错

    Python selenium PO  By.XPATH定位元素报错 如下代码经常报错: # 首页的“新建投放计划”按钮 new_ads_plan = (By.XPATH, "//*[tex ...

  9. Selenium Page Object(PO)设计模式

    Webdriver UI自动化测试火了好几年了,具体怎么设计自动化测试测试工程,组织测试用例完全凭借着自己的经验和习惯. 最近忽然听说了Page Object(简称PO)火了起来,也有面试的时候被问到 ...

  10. Python&Selenium自动化测试之PO设计模式

    一.摘要 Page Object模式,后面简称PO,他是一种设计思想,在上一章节中,曾经列举了一些在编写自动化测试过程中随着代码量的增加导致的大量代码难以维护.难以扩展.可读性极差等灾难性的事件:那么 ...

随机推荐

  1. HDU3338 Kakuro Extension(最大流+思维构图)

    这道题一定要写一下,卡了好久. 题意: 有黑白两种方格,最上边一行和最左边一列一定是黑色,然后其余的地方有可能是黑色,有可能是白色,和白色相邻的黑色方格里有数字(1个或2个), 现在要求在白色方格里填 ...

  2. Beta冲刺(3/7)——2019.5.24

    所属课程 软件工程1916|W(福州大学) 作业要求 Beta冲刺(3/7)--2019.5.24 团队名称 待就业六人组 1.团队信息 团队名称:待就业六人组 团队描述:同舟共济扬帆起,乘风破浪万里 ...

  3. The Best Open Source Game Engine: In Search Of Perfection

    https://www.greatsoftline.com/the-best-open-source-game-engine-in-search-of-perfection/ The game eng ...

  4. Java检查异常、非检查异常、运行时异常、非运行时异常的区别

    Java把所有的非正常情况分为两种:异常(Exception)和错误(Error),它们都继承Throwable父类. Java的异常(Exception和Error)分为检查异常和非检查的异常. 其 ...

  5. (14)树莓派 - 修改pi账号密码,开启root账号

    https://blog.csdn.net/yoie01/article/details/45115067 1.修改PI账号的密码 password pi 2.开启root账号树莓派使用的linux是 ...

  6. 使用overnightjs typescript 注解开发expressjs 应用

    overnightjs 提供了基于注解的expressjs应用开发,包含了比较全的express 开发支持,使用简单,以下是一个简单的试用 项目准备 项目使用pkg 进行了打包处理 初始化 yarn ...

  7. jupyter的补充

    目录 jupyter 的使用 常用命令模式快捷键: 常用编辑模式快捷键: jupyter 的使用 Cells状态分为命令模式和编辑模式,Enter进入编辑模式,ESC进入命令模式,命令模式和编辑模式下 ...

  8. hlt 与 llt 相关

    HLT:HIGH LEVEL TEST,通常指SDV/SIT/SVT等测试活动SDV : system design verification 系统设计验证 SIT : system integrat ...

  9. ELK实时日志分析平台环境部署,以及可视化展示

    ELK是三个开源软件的缩写,分别表示:Elasticsearch , Logstash, Kibana , 它们都是开源软件.新增了一个FileBeat,它是一个轻量级的日志收集处理工具(Agent) ...

  10. Spring Boot 怎么打一个可执行 Jar 包?

    传统的 Java 应用程序都需要打一个 war 包,并到到 Tomcat webapps 目录下运行. Java 支持打 Jar 包,但没有提供一个标准的方式在一个 Jar 包内再加载嵌入别的 Jar ...