一、PO模式
PO:Page Object(页面对象),将自动化涉及的页面或模块封装成对象。
PO能解决什么问题?
- 代码复用性
- 便于维护(脚本层与业务分离)--如果元素信息发生变化了,也不用去修改脚本。
PO如何做?
Base层:存放所有页面公共方法
Page层:基于页面或模块单独封装当前页面要操作的对象
Script层:脚本层+unittest
非PO模式的代码实现
import unittest
from selenium import webdriver
from time import sleepclass 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 WebDriverWaitclass 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 PageLoginclass 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 jsondef read_json(filename,key):filepath = os.path.dirname(os.path.dirname(__file__)) + os.sep + "data" + os.sep + filenamearr = []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_jsonclass 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)