#第一步:1.在base目录内建文件名base_page.py
封装【基类行为】和【驱动工具类】
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.wait import WebDriverWait
import config
#1#封装【驱动工具】
class Driver_Tools:
driver=None#用于保存driver数据初值None
@classmethod
def create(cls):
if cls.driver is None:#如果driver为None不存在执行
cls.driver = webdriver.Chrome()
cls.driver.maximize_window()
return cls.driver#返回drive值
@classmethod
def quit(cls):
if cls.driver is not None:#如果driver为not None存在执行
cls.driver.quit()
cls.driver=None#健壮性
# 为了满足create方法中if条件的is None
# 2#封装获取截图的函数
def get_screenshot(key):
filename = time.strftime("%Y%m%d-%H%M%S") + ".png"
filepath = config.D + "/screenshot/" + key +filename
Driver_Tools.create().get_screenshot_as_file(f"{filepath}")
#3#封装动作
class Base_Page:
def __init__(self):#创建驱动
self.driver=Driver_Tools.create()
# 1查找元素
# def find_el(self,loc):#loc元组(By.ID,XXX)形参定位元素
def find_el(self,loc,timeout=10):#loc元组(By.ID,XXX)形参定位元素
# loc = (By.ID, "userA")定位元素位置
try: # 显式等待#函数名=lambda 形参:函数体# 显式等待#函数名=lambda 形参:函数体*元组拆包
el = WebDriverWait(self.driver, timeout).until(lambda x: x.find_element(*loc))
return el
except Exception as e:
print(f"{loc}元素没有找到~!")
# return e
raise e # 注意 raise后不可以return了
# return False
# 2 输入内容方法
def input_text(self,loc,text,timeout=10):
#loc元组(By.ID,XXX)形参定位元素
# text形参loc元组定位元素后输入text数据
self.find_el(loc,timeout).clear()#清除loc元组文本数据
self.find_el(loc,timeout).send_keys(text)#输入文本数据
# 3 点击方法
def click_el(self,loc,timeout=10):#loc元组(By.ID,XXX)形参定位元素
self.find_el(loc,timeout).click()#点击数据
# 4 打开网页的方法
def open_url(self,url):#url形参用于传参网址
self.driver.get(url)#打开url网站
# 5.1切换iframe的方法
def switch_frame(self,loc,timeout=10):
# 定位iframe元素
iframe_el=self.find_el(loc,timeout)
# 切换iframe
self.driver.switch_to.frame(iframe_el)
# 5.2切回iframe的方法
def parent_frame(self):
self.driver.switch_to.parent_frame() # 返回上一级iframe并重新定位iframe位置
# 5.3 恢复原始iframe的方法
def default_content_frame(self):
self.driver.switch_to.default_content()#恢复默认iframe并重新定位iframe位置
# 6 获取弹出框文本的方法
def get_tips_msg(self,loc,timeout=10):
#调用显示等待查找元素find_el的文本text返回结果
tips=self.find_el(loc,timeout).text
return tips
#7封装下拉框
def select_option(self,loc,text):
select=Select(self.find_el(loc))
select.select_by_visible_text(text)
#第二步:2.在page目录内建文件名htlogin_page.py
#封装打开并【登录】
from selenium.webdriver.common.by import By
# 1分析登录页面>定义登录类>继承基类
from base.base_page import Base_Page, Driver_Tools
class Login_Page(Base_Page):
def __init__(self): # 2分析元素
super().__init__() # 重写扩展
# self.driver=DriverTools.create()#省略调用固定驱动
self.username = (By.NAME, 'username') # 2定位账号元素
self.password = (By.NAME, 'password') # 3定位密码元素
self.verify = (By.NAME, 'vertify') # 4定位验证码元素
self.sbtbutton = (By.NAME, 'submit') # 5定位登录按钮元素
# 6定位弹出框文本元素
self.i_loc = (By.CSS_SELECTOR, ".layui-layer-content")
# 3分析业务行为1打开网站#打开首页页面#定义行为函数【登录首页】
def open_index(self):
# 1)打开【首页】网站
self.open_url("http://hmshop-test.itheima.net/Admin")
# 3.1分析业务行为输入数据点击登录按钮#定义行为【登录】函数
def Iogin_data(self, username, password, verify):
# 1输入#账号
self.input_text(self.username, username)
# 2输入#密码
self.input_text(self.password, password)
# 3输入#验证码
self.input_text(self.verify, verify)
# 4点击【登录】按钮
self.click_el(self.sbtbutton)
# 3.2分析业务行为点击登录按钮后弹出框文本
def get_tips(self):#封装【弹出框】方法2
# 调用基类弹出框文本传弹出框文本元素返回值
te=self.get_tips_msg(self.i_loc)
return te
#第三步:3.在page目录内建文件名htindex_page.py
#封装【首页】点击商城
from selenium.webdriver.common.by import By
# from page.fzbase import Base_Page#导包基类
#1分析首页页面>定义首页类>继承基类
from base.base_page import Base_Page, Driver_Tools
from page.htlogin_page import Login_Page
class Index_Page(Base_Page):
def __init__(self):#2分析元素
# #__init__实例属性
super().__init__()#重写扩展
# self.driver=DriverTools.create()#省略调用固定驱动
# 1定位商城元素
self.shop_loc=(By.LINK_TEXT, "商城")
self.get_loc= (By.CSS_SELECTOR, "span.bgdopa-t")
def go_shop(self):
# 1)点击【商城】超链接
self.click_el(self.shop_loc)
def get_text(self):
# 1)点击【商城】超链接
return self.find_el(self.get_loc).text
#第四步:4.在page目录内建文件名htshopping_page.py
#进入新增商品页
from selenium.webdriver.common.by import By
#1分析商城页面>定义商城类>继承基类
from base.base_page import Base_Page, Driver_Tools
from page.htindex_page import Index_Page
from page.htlogin_page import Login_Page
class Shop_Page(Base_Page):
def __init__(self):#2分析元素
# #__init__实例属性htshopping_page.py
super().__init__()#重写扩展
# self.driver=DriverTools.create()#省略调用固定驱动
# 1定位商城元素
# 2)添加商品
self.add_goods_loc = By.XPATH, "//div[@title='添加商品']"
# 3)首个商品名称
self.first_goods_loc = By.XPATH, '//div[@id="flexigrid"]//td[4]/div'
# 4)frame元素
self.iframe_loc = By.ID, "workspace"
#显示登录用户文本
def get_shop_msg(self):
self.switch_frame(self.iframe_loc)
text= self.find_el(self.first_goods_loc).text
self.parent_frame()
return text
# 进入新增商品页
def add_shop_page(self):
self.switch_frame(self.iframe_loc)
self.click_el(self.add_goods_loc)
self.parent_frame()
#第五步:5.在page目录内建文件名htadd_product_page.py
#封装添加商品信息
from selenium.webdriver.common.by import By
#1分析添加商品页面>定义添加商品类>继承基类
from base.base_page import Base_Page, Driver_Tools
from page.htindex_page import Index_Page
from page.htlogin_page import Login_Page
from page.htshopping_page import Shop_Page
class Add_Page(Base_Page):
def __init__(self):
super().__init__()
# 新增商品frame
self.product_iframe_loc = By.ID, "workspace"
# 商品名称
self.product_name_loc = By.CSS_SELECTOR, "input[name='goods_name']"
# 商品一级分类select
self.cat_1_loc = By.CSS_SELECTOR, 'select[id="cat_id"]'
# 商品二级分类select
self.cat_2_loc = By.CSS_SELECTOR, 'select[id="cat_id_2"]'
# 商品三级分类select
self.cat_3_loc = By.CSS_SELECTOR, 'select[id="cat_id_3"]'
# 本店售价
self.shop_price_loc = By.CSS_SELECTOR, "input[name='shop_price']"
# 市场售价
self.market_price_loc = By.CSS_SELECTOR, "input[name='market_price']"
# 运费模版
self.template_loc = By.CSS_SELECTOR, "select[name='template_id']"
# 商品详情iframe
self.ueditor_iframe_Loc = By.CSS_SELECTOR, "iframe#ueditor_0"
# 商品详情编辑框
self.content_loc = By.CSS_SELECTOR, "body.view"
# 确认提交
self.submit_btn_loc = By.CSS_SELECTOR, "a#submit"
def add_product(self, product_name, cat_1_text, cat_2_text, cat_3_text, shop_price,
market_price, template_text, content_text):
# 切换frame
self.switch_frame(self.product_iframe_loc)
#隐式等待
self.driver.implicitly_wait(5)
# 输⼊商品名称
self.input_text(self.product_name_loc,product_name)
# 选择商品⼀级、⼆级、三级分类
self.select_option(self.cat_1_loc,cat_1_text)
self.select_option(self.cat_2_loc,cat_2_text)
self.select_option(self.cat_3_loc,cat_3_text)
# 输⼊本店售价
self.input_text(self.shop_price_loc,shop_price)
# 输⼊市场售价
self.input_text(self.market_price_loc,market_price)
# 选择运费模版
self.select_option(self.template_loc,template_text)
# 切换到编辑框所在到frame
self.switch_frame(self.ueditor_iframe_Loc)
# 填写商品详情信息# 返回⽗级frame
self.input_text(self.content_loc,content_text)
self.parent_frame()
# 点击确认
self.click_el(self.submit_btn_loc)
# 返回⾸次切⼊的frame的⽗级
self.parent_frame()
#普通test实现
import time
from base.base_page import Driver_Tools
from page.htadd_product_page import Add_Page
from page.htindex_page import Index_Page
from page.htlogin_page import Login_Page
from page.htshopping_page import Shop_Page
class Test_AddProduct():
def setup_class(self):
self.Iogin_page = Login_Page()
self.index_page = Index_Page()
self.shopping_page = Shop_Page()
self.add_page = Add_Page()
self.Iogin_page.open_index()
self.Iogin_page.Iogin_data("admin", "123456", "8888")
# # 点击商城
print(self.index_page.get_text())
self.index_page.go_shop()
# 点击新增商品页
def teardown_class(self):
Driver_Tools.quit()
def setup(self):
# 进新增商品页
self.shopping_page.add_shop_page()
def test_addshop(self):
# print(self.shopping_page.get_shop_msg())
# 新增商品
self.add_page.add_product("沐浴露awr3005", "个人化妆", "身体护肤", "沐浴",89, 129, "以件计算", "霸王沐浴露,最好的沐浴露~!")
time.sleep(5)
# 调用封装弹出框文本
text =self.shopping_page.get_shop_msg()
print(text) # 打印弹出框文本
assert '沐浴露awr3005' in text#断言实际结果的文本包含预期结果
#上述为前提添加
#1data文件夹中#add_goods.json文件
[
{
"desc": "以件计算发布商品成功",
"product_name": "欧莱雅7组00114",
"shop_price": "89",
"market_price": "129",
"goods_content": "欧莱雅2022新款石榴沐浴露0044",
"cat_1": "个人化妆",
"cat_2": "面部护肤",
"cat_3": "清洁",
"template": "以件计算"
},
{
"desc": "以体积计算发布商品成功",
"product_name": "欧莱雅7组00113",
"shop_price": "89",
"market_price": "129",
"goods_content": "欧莱雅2022新款石榴沐浴露0055",
"cat_1": "个人化妆",
"cat_2": "面部护肤",
"cat_3": "清洁",
"template": "以体积计算"
}
]
#2#config.py绝对路径
import os
D=os.path.dirname(__file__)
# D自定义根目录config.py
#3base文件夹中#read_file.py读取json
import json#导包json
from config import D#导包绝对路径D
#定义读取json的方法定义filename形参用于调用传参
def Read_Data(filename):
with open(filename, encoding='utf-8') as file:
data_list = json.load(file) # json默认r读取文件
# json.load读取加载的数据赋值给变量名data_list
new_list = []#创建空列表
for my_dict in data_list:#for循环遍历列表得到字典
# 字典.values()得到键值并转元组
my_tuple = tuple(my_dict.values())
new_list.append(my_tuple)#将得到数据的元组添加给新空列表
return new_list#返回得到数据的列表值
#4#scripts文件夹中#test_paramadd.py参数化
import time
import pytest
from base.base_page import Driver_Tools
from base.read_file import Read_Data
from config import D
from page.htadd_product_page import Add_Page
from page.htindex_page import Index_Page
from page.htlogin_page import Login_Page
from page.htshopping_page import Shop_Page
class Test_AddProduct():
def setup_class(self):
# 创建⻚⾯对象
self.Iogin_page = Login_Page()
self.index_page = Index_Page()
self.shopping_page = Shop_Page()
self.add_page = Add_Page()
# 登录后台
self.Iogin_page.open_index()
self.Iogin_page.Iogin_data("admin", "123456", "8888")
# # 点击商城# 进⼊商城⻚⾯
self.index_page.go_shop()
# 点击新增商品页
def teardown_class(self):
Driver_Tools.quit()
def setup(self):
# 进新增商品页
self.shopping_page.add_shop_page()
#读取json数据
read_json=Read_Data(D + '/data/add_goods.json')
@pytest.mark.parametrize('desc,product_name,shop_price,market_price,goods_content,'
'cat_1,cat_2,cat_3,template',read_json)
#编写测试用例并按需求顺序传参
def test_addshop(self,desc,product_name,cat_1,cat_2,cat_3,shop_price,market_price,template,goods_content):
# 新增商品填写信息
self.add_page.add_product(product_name,cat_1,cat_2,cat_3,shop_price,market_price,template,goods_content)
time.sleep(5)
# 添加商品成功后文本
text =self.shopping_page.get_shop_msg()
print(desc,text)
assert product_name in text#断言实际结果的文本包含预期结果
#5#base文件夹中#logging_use.py日志
import logging.handlers
import logging
from config import D
def init_log_config(filename, when='midnight', interval=1, backup_count=7):
# 1. 创建日志器对象
logger = logging.getLogger()
# 2. 设置日志打印级别
logger.setLevel(logging.INFO)
# 3. 创建处理器对象
# 控制台对象
st = logging.StreamHandler()
# 日志文件对象
fh = logging.handlers.TimedRotatingFileHandler(filename,
when=when,
interval=interval,
backupCount=backup_count,
encoding='utf-8')
# 4. 日志信息格式
fmt = "%(asctime)s %(levelname)s [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s"
formatter = logging.Formatter(fmt)
# 5. 给处理器设置日志信息格式
st.setFormatter(formatter)
fh.setFormatter(formatter)
# 6. 给日志器添加处理器
logger.addHandler(st)
logger.addHandler(fh)
#6#scripts文件夹中#test_logadd.py参数化日志
import logging
import time
import pytest
from base.base_page import Driver_Tools
from base.logging_use import init_log_config
from base.read_file import Read_Data
from config import D
from page.htadd_product_page import Add_Page
from page.htindex_page import Index_Page
from page.htlogin_page import Login_Page
from page.htshopping_page import Shop_Page
class Test_AddProduct():
def setup_class(self):
# 创建⻚⾯对象
self.Iogin_page = Login_Page()
self.index_page = Index_Page()
self.shopping_page = Shop_Page()
self.add_page = Add_Page()
# 登录后台
self.Iogin_page.open_index()
self.Iogin_page.Iogin_data("admin", "123456", "8888")
# # 点击商城# 进⼊商城⻚⾯
self.index_page.go_shop()
# 点击新增商品页
def teardown_class(self):
Driver_Tools.quit()
def setup(self):
# 进新增商品页
self.shopping_page.add_shop_page()
#读取json数据
read_json=Read_Data(D + '/data/add_goods.json')
@pytest.mark.parametrize('desc,product_name,shop_price,market_price,goods_content,'
'cat_1,cat_2,cat_3,template',read_json)
#编写测试用例并按需求顺序传参
def test_addshop(self,desc,product_name,cat_1,cat_2,cat_3,shop_price,market_price,template,goods_content):
# 新增商品填写信息
self.add_page.add_product(product_name,cat_1,cat_2,cat_3,shop_price,market_price,template,goods_content)
time.sleep(5)
# 日志生成路径
init_log_config(D + '/log/addshop') # 日志存储路径和生成的文件名
#日志文件内容
logging.info(f"desc={desc}, product_name={product_name},shop_price={shop_price},"
f""f"market_price={market_price}, goods_content={goods_content}, cat_1={cat_1}, cat_2={cat_2},"
f"cat_3={cat_3}, template={template}")
# 添加商品成功后文本
text =self.shopping_page.get_shop_msg()
print(desc,text)
assert product_name in text#断言实际结果的文本包含预期结果
#7##pytest.ini参数化日志pytest
[pytest]
addopts=-s --html=report/test01_report.html
testpaths=./scripts
python_files=test_logadd.py
python_classes=Test*
python_functions=test*