一、PO模式
PO:Page Object(页面对象),将自动化涉及的页面或模块封装成对象。
PO能解决什么问题?
- 代码复用性
- 便于维护(脚本层与业务分离)--如果元素信息发生变化了,也不用去修改脚本。
PO如何做?
Base层:存放所有页面公共方法
Page层:基于页面或模块单独封装当前页面要操作的对象
Script层:脚本层+unittest
非PO模式的代码实现
import unittest
from selenium import webdriver
from time import sleep
class TestLogin(unittest.TestCase):
def setUp(self) -> None:
self.driver = webdriver.Chrome("/usr/local/bin/chromedriver")
self.driver.maximize_window()
self.driver.get("http://hmshop-test.itheima.net/Home/user/login.html")
self.driver.implicitly_wait(10)
def tearDown(self) -> None:
sleep(5)
self.driver.quit()
def test01_login(self):
self.driver.find_element_by_css_selector("#username").send_keys("13600001111")
self.driver.find_element_by_css_selector("#password").send_keys("123456")
self.driver.find_element_by_css_selector("#verify_code").send_keys("8888")
self.driver.find_element_by_css_selector(".J-login-submit").click()
PO设计结构:
base:存放所有page页面公共方法
page:将页面封装为对象
script:测试脚本
案例:
base.py
"""
base类,存放所有page页面公共操作方法
"""
from selenium.webdriver.support.wait import WebDriverWait
class Base:
def __init__(self,driver):
self.driver = driver
# 查找元素
def base_find(self,loc,timeout=10,poll_frequency=0.5):
# 显示等待->查找元素 loc=(By.ID,"#userA")
return WebDriverWait(self.driver,timeout,poll_frequency).\
until(lambda x:x.find_element(loc[0],loc[1]))
# 输入方法
def base_input(self,loc,value):
# 获取元素
el = self.base_find(loc)
# 清空操作
el.clear()
# 输入内容
el.send_keys(value)
# 点击方法
def base_click(self,loc):
self.base_find(loc).click()
# 获取文本值方法
def base_get_text(self,loc):
return self.base_find(loc).text
page_login.py
"""
模块名:page_模块
类名:大驼峰将模块移植进来,去掉下划线和数字。
方法:自动化测试当前页面要操作哪些元素,就封装哪些方法
"""
from po.base.base import Base
from selenium.webdriver.common.by import By
# 用户名
username = (By.CSS_SELECTOR,"#username")
# 密码
pwd = (By.CSS_SELECTOR,"#password")
# 验证码
verify_code = (By.CSS_SELECTOR,"#verify_code")
# 登录按钮
login_btn = (By.CSS_SELECTOR,".J-login-submit")
# 昵称
nick_name = (By.CSS_SELECTOR,".userinfo")
class PageLogin(Base):
# 输入用户名
def __page_username(self,value):
self.base_input(username,value)
# 输入密码
def __page_pwd(self,value):
self.base_input(pwd,value)
# 输入验证码
def __page_verify_code(self,value):
self.base_input(verify_code,value)
# 点击登录按钮
def __page_click_login_btn(self):
self.base_click(login_btn)
# 获取昵称
def page_get_nickname(self):
return self.base_get_text(nick_name)
# 组合业务方法(测试业务层调用此方法,便捷)
def page_login(self,phone,password,code):
self.__page_username(phone)
self.__page_pwd(password)
self.__page_verify_code(code)
self.__page_click_login_btn()
test_login.py
import unittest
from selenium import webdriver
from po.page.page_login import PageLogin
class TestLogin(unittest.TestCase):
def setUp(self) -> None:
self.driver = webdriver.Chrome("/usr/local/bin/chromedriver")
self.driver.maximize_window()
self.driver.get("http://hmshop-test.itheima.net/Home/user/login.html")
self.login = PageLogin(self.driver)
def tearDown(self) -> None:
self.driver.quit()
def test_login(self,phone="13600001111",password="123456",code="8888"):
# 调用登录业务
self.login.page_login(phone,password,code)
# 断言
nickname = self.login.page_get_nickname()
print("nickname:",nickname)
二、数据驱动
什么是数据驱动?
- 以测试数据驱动用例执行(测试数据和代码分离)
为什么要数据驱动?
- 便于维护(维护的焦点从代码转到测试数据)
数据驱动如何操作?
- 编写数据存储文件
- 编写读取数据工具
- 使用参数化引用
编写数据存储文件
- 新建json文件,在文件中编写一个{}
- 有几个模块,写几个key,值为列表
- 列表中参数化数据有几组,就写几个{}
- 每个{}中组成: 说明+参数数据+预期结果
{
"login":[
{
"desc":"登录成功",
"phone":"13600001111",
"password":"123456",
"code":"8888",
"except_text":"13600001111"
}
]
}
具体的代码:
json_test.json
{
"login":[
{
"desc":"登录成功",
"phone":"13600001111",
"Password":"123456",
"Code":"8888"
}
]
}
read_json.py
import os
import json
def read_json(filename,key):
filepath = os.path.dirname(os.path.dirname(__file__)) + os.sep + "data" + os.sep + filename
arr = []
with open(filepath,"r",encoding="utf-8") as f:
for data in json.load(f).get(key):
arr.append(tuple(data.values())[1:])
return arr
test_login.py
import unittest
from po_test.page.page_login import PageLogin
from selenium import webdriver
from time import sleep
from parameterized import parameterized
from po_test.util.read_json import read_json
class TestLogin(unittest.TestCase):
def setUp(self) -> None:
self.driver = webdriver.Chrome("/usr/local/bin/chromedriver")
self.driver.get("http://hmshop-test.itheima.net/Home/user/login.html")
self.driver.maximize_window()
self.pagelogin = PageLogin(self.driver)
def tearDown(self) -> None:
sleep(5)
self.driver.quit()
@parameterized.expand(read_json("json_test.json","login"))
def test_login(self,phone,password,code):
self.pagelogin.login(phone,password,code)