目录
Po模式封装
V1-V6
V1:不采用任何模式(线性模型)
V2:采用测试框架 unittest
V3:业务代码和页面对象进行
V4:实际中的po模式编写
V5:对PO分层之后的代码继续优化
V6:把共同操作提取封装到父类中,子类直接调用父类的方法,避免代码冗余
案例:
百度账号登陆
1、账号不存在
2、密码错误
V1模式执行代码
#导包
from selenium import webdriver
from time import sleep
#获取driver对象
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
#最大化浏览器
driver.maximize_window()
#隐式等待
driver.implicitly_wait(30)
#获取url
driver.get("http://www.baidu.com")
"""
账号错误
"""
#定位登陆元素点击
driver.find_element(By.CSS_SELECTOR,"#s-top-loginbtn").click()
#输入用户名
sleep(2)
driver.find_element(By.CSS_SELECTOR,"#TANGRAM__PSP_11__userName").clear()
driver.find_element(By.CSS_SELECTOR,"#TANGRAM__PSP_11__userName").send_keys("1596263494")
#输入密码
sleep(2)
driver.find_element(By.CSS_SELECTOR,"#TANGRAM__PSP_11__password").clear()
driver.find_element(By.CSS_SELECTOR,"#TANGRAM__PSP_11__password").send_keys("234567")
#点击登陆
driver.find_element(By.CSS_SELECTOR,"#TANGRAM__PSP_11__submit").click()
sleep(2)
#获取错误信息
text = driver.find_element(By.CSS_SELECTOR,"#TANGRAM__PSP_11__error").text
print(text)
"""
手机号码为空
"""
# 清空手机号码
sleep(2)
driver.find_element(By.CSS_SELECTOR,"#TANGRAM__PSP_11__userName").clear()
#输入密码
sleep(2)
driver.find_element(By.CSS_SELECTOR,"#TANGRAM__PSP_11__password").clear()
driver.find_element(By.CSS_SELECTOR,"#TANGRAM__PSP_11__password").send_keys("234567")
#点击登陆
driver.find_element(By.CSS_SELECTOR,"#TANGRAM__PSP_11__submit").click()
sleep(2)
#获取错误信息
text = driver.find_element(By.CSS_SELECTOR,"#TANGRAM__PSP_11__error").text
print(text)
#退出浏览器
driver.quit()执行结果:
用户名或密码有误,请重新输入或找回密码
请您输入手机号/用户名/邮箱
V2执行代码
# 导包
import time
from selenium import webdriver
import unittest
# 创建测试类
from selenium.webdriver.common.by import By
class TestLogin(unittest.TestCase):
driver = None
# 创建单元测试方法
# 使用fixture装置函数
@classmethod
def setUpClass(cls):
"""
创建driver对象
最大化浏览器
设置隐式等待
:return:
"""
cls.driver = webdriver.Chrome()
cls.driver.maximize_window()
cls.driver.implicitly_wait(30)
# 获取网页URL
cls.driver.get("http://www.baidu.com")
# 定位登陆元素点击
cls.driver.find_element(By.CSS_SELECTOR, "#s-top-loginbtn").click()
@classmethod
def tearDownClass(cls):
"""
关闭浏览器
:return:
"""
cls.driver.quit()
def testLogin(self):
"""
密码错误
:return:
"""
driver = self.driver
# 输入用户名
driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__userName").clear()
driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__userName").send_keys("1596263494")
# 输入密码
driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__password").clear()
driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__password").send_keys("234567")
# 点击登陆
time.sleep(3)
driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__submit").click()
# 获取错误信息
msg = driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__error").text
print("msg:", msg)
# 断言错误信息
try:
assert msg == "用户名或密码有误,请重新输入或"
except AssertionError:
# 断言错误截图
driver.get_screenshot_as_file("./image/{}.png".format(time.strftime("%Y_%m_%d_%H_%M_%S")))
def testLoginNotExist(self):
"""
账号为空
:return:
"""
driver = self.driver
# 清空用户名
driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__userName").clear()
# 清空密码
driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__password").clear()
# 输入密码
driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__password").send_keys("234567")
# 点击登陆
time.sleep(3)
driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__submit").click()
# 获取错误信息
msg = driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__error").text
print("msg:", msg)
try:
assert msg == "请您输入手机号/用户名/邮箱"
except AssertionError:
# 断言错误截图
driver.get_screenshot_as_file("./image/{}.png".format(time.strftime("%Y_%m_%d_%H_%M_%S")))
执行结果:
msg: 用户名或密码有误,请重新输入或
msg: 请您输入手机号/用户名/邮箱
V3版本
V1问题:无法批量运行
V2问题:业务脚本与页面对象没有分开
V3问题:代码冗余量太大
PO介绍:
PO:page(页面)| object(对象)
页面对象层:
页面对象编写技巧:
类名:使用大驼峰将模块名称抄进来,有下划线去掉下划线
方法:根据业务需求每个操作步骤单独封装一个方法
方法名:page_XXX
组装业务方法:
V3po封装:

页面层执行代码:
# 导包
from selenium import webdriver
# 创建页面类
from selenium.webdriver.common.by import By
class PageLogin():
# 初始化对象
def __init__(self):
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.implicitly_wait(30)
self.driver.get("http://www.baidu.com")
# 点击登陆链接按钮
def page_login(self):
self.driver.find_element(By.CSS_SELECTOR, "#s-top-loginbtn").click()
# 输入用户名
def page_username(self,username):
self.driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__userName").clear()
self.driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__userName").send_keys(username)
# 输入密码
def page_password(self,password):
self.driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__password").clear()
self.driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__password").send_keys(password)
# 点击登陆按钮
def page_login_ok(self):
self.driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__submit").click()
# 获取错误信息
def page_msg_info(self):
return self.driver.find_element(By.CSS_SELECTOR, "#TANGRAM__PSP_11__error").text
# 封装页面方法
def pageLoginWays(self,username,password):
self.page_login()
self.page_username(username)
self.page_password(password)
self.page_login_ok()业务层执行代码:
import time
import unittest
from parameterized import parameterized
from base_page.page_login import PageLogin
# 创建测试类
class TestLogin(unittest.TestCase):
# 创建fixture内置函数
def setUp(cls):
cls.login = PageLogin()
def tearDown(cls):
cls.login.driver.quit()
# 创建测试方法
@parameterized.expand([('1596263494','123123',"用户名或密码有误,请重新输入或"),('','123123',"请您输入手机号/用户名/邮箱")])
def testMsg(self,username,password,msg):
self.login.pageLoginWays(username,password)
text = self.login.page_msg_info()
try:
self.assertEqual(text,msg)
except AssertionError:
self.login.driver.get_screenshot_as_file("../image/{}.png".format(time.strftime("%Y_%m_%d_%H_%M_%S")))V4版本
结构:
1、base(基类):page界面一些公共的方法;
#Base类:
初始化方法
查找元素方法
点击元素方法
输入框方法
获取文本方法
截图方法
注意:
1、以上方法封装的时候,解包只需1次,在查找元素解包
2、driver为虚拟,谁调用base时,谁传入,无需关注从哪里来;
3、loc:真正使用loc的方法只有查找元素方法使用
2、page(页面对象):一个页面封装成一个对象;
应用:继承base
实现:
1、模块名:page+实际操作模块名称 如:page_login.py
2、页面对象名:以大驼峰方法将模块名抄进来,有下划线去掉下划线
3、方法:涉及元素,将每个元素操作单独封装一个操作方法
4、组装:根据需求组装以上操作步骤
3、scripts/cases(业务层):导包调用page页面,
实现:
1、模块:test+实际操作模块名称 如:test.login.py
2、页面对象名:以大驼峰方法将模块名抄进来,有下划线去掉下划线
3、方法:
1、初始化方法setUp() 注:在unittest框架中不能使用def __init__()初始化方法;
#实例化页面对象
#前置操作 如打开等等
2、结束方法teardown
#关闭驱动
3、测试方法
#根据操作的业务来实现
扩展:
loc变量:类型为元祖:*loc为解包
代码包结构:

base类代码:
import time
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
class Base():
# 初始化driver
def __init__(self):
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get("https://www.baidu.com")
# 查找元素方法
def base_find_element(self,loc,time=30,poll = 1):
return WebDriverWait(self.driver,timeout=time,poll_frequency=poll).until(lambda x: x.find_element(*loc))
# 点击方法
def base_click(self,loc):
self.base_find_element(loc).click()
# 输入文本框方法
def base_send_keys(self,loc,value):
el = self.base_find_element(loc)
# 清除元素输入框
el.clear()
el.send_keys(value)
# 获取文本方法
def base_error_text(self,loc):
return self.base_find_element(loc).text
# 截图方法
def base_screenshot_as_file(self):
self.driver.get_screenshot_as_file("../image/{}.png".format(time.strftime("%Y_%m_%d_%H_%M_%S")))page中__init__代码:(做数据)
from selenium.webdriver.common.by import By
login_link = By.CSS_SELECTOR,"#s-top-loginbtn"
login_username = By.CSS_SELECTOR, "#TANGRAM__PSP_11__userName"
login_pwd = By.CSS_SELECTOR, "#TANGRAM__PSP_11__password"
login_btn_ok = By.CSS_SELECTOR, "#TANGRAM__PSP_11__submit"
login_error_text = By.CSS_SELECTOR, "#TANGRAM__PSP_11__error"
pagelogin中代码:
import time
import page
from base.base import Base
class PageLogin(Base):
# 点击首页登陆按钮
def page_click(self):
self.base_click(page.login_link)
# 输入用户名
def page_username(self,username):
self.base_send_keys(page.login_username,username)
# 输入密码
def page_pwd(self,pwd):
self.base_send_keys(page.login_pwd,pwd)
# 点击登陆
def page_login_ok_btn(self):
self.base_click(page.login_btn_ok)
# 错误信息
def page_error_text(self):
return self.base_error_text(page.login_error_text)
# 封装登陆方法
def page_login_ways(self,value,pwd):
time.sleep(2)
self.page_username(value)
time.sleep(2)
self.page_pwd(pwd)
time.sleep(2)
self.page_login_ok_btn()scripts中run.py代码(运行test代码):
import time
import unittest
from tool.HTMLTestRunner import HTMLTestRunner
suite = unittest.defaultTestLoader.discover("./")
# 报告生成目录及文件名称
dir_path = "../report/{}.html".format(time.strftime("%Y_%m_%d %H_%M_%S"))
# 获取文件流并调用run运行
with open(dir_path, "wb") as f:
HTMLTestRunner(stream=f, title="Tpshop商城自动化测试报告", description="操作系统:win10").run(suite)scripts中TestLogin.py代码:
import unittest
from parameterized import parameterized
from page.pageLogin import PageLogin
def get_date():
return [('1596263494','123123',"用户名或密码有误,请重新输入或"),(' ','123123',"请您输入手机号/用户名/邮箱")]
class TestLogin(unittest.TestCase):
login = None
@classmethod
def setUpClass(cls):
cls.login = PageLogin()
cls.login.page_click()
@classmethod
def tearDownClass(cls):
cls.login.driver.quit()
@parameterized.expand(get_date())
def testLogin(self,value,pwd,expand):
self.login.page_login_ways(value,pwd)
msg = self.login.page_error_text()
try:
self.assertEqual(msg, expand)
except AssertionError:
self.login.base_screenshot_as_file()tool包中HTMLTestRunner.py文件获取方式:
链接:https://pan.baidu.com/s/1QjZwdKvXhXNk9KYTBsm9hw
提取码:f9zq