1.文件目录结构
2.POM进阶之logic封装实战应用
"""
变量统一管理文件,为了方便代码中识别,目录,文件,变量名全部大写
"""
CART_LOGIN_URL = "CART_LOGIN_URL"
USERNAME = "云纱璃英"
PASSWD = "xxx"
TAOBAO_URL = "http://www.taobao.com"
-
txt: 迈巴赫
import yaml
def load_yaml(path):
file = open(path,'r',encoding='utf-8')
data = yaml.load(file,Loader = yaml.Fullloader)
return data
chrome.exe --remote-debugging-port=9222
"""
使用编写的脚本以debug模式启动谷歌浏览器,脚本内容如下
chrome.exe --remote-debugging-port=9222
必须通过脚本执行,使用os.system执行命令无效
"""
from time import sleep
from class37.p07.VAR.TAOBAO_VAR import USERNAME, PASSWD
from class37.p07.key_world.keyword import WebKeys
from class37.p07.locate import allPages
from selenium import webdriver
options = webdriver.ChromeOptions()
options.debugger_address = '127.0.0.1:9222'
driver = webdriver.Chrome(options=options)
sleep(2)
wk = WebKeys(driver)
wk.locator(*allPages.page_goodsDetail_cartBtn).click()
sleep(1)
el = wk.locator(*allPages.page_goodsDetail_loginFrame)
wk.change_frame(el)
wk.locator(*allPages.page_indexLogin_user).send_keys(USERNAME)
wk.locator(*allPages.page_indexLogin_pwd).send_keys(PASSWD)
wk.locator(*allPages.page_indexLogin_loginBtn).click()
sleep(3)
el = wk.locator('xpath', "//div[@id='login']//iframe")
wk.change_frame(el)
wk.slider_by_step("//center//span[@id='nc_1_n1z']")
from time import sleep
import allure
from selenium import webdriver
from selenium.common import UnexpectedAlertPresentException
from selenium.webdriver import ActionChains
class WebKeys:
def __init__(self,driver):
self.driver = driver
def open(self,url):
self.driver.get(url)
def locator(self,name,value):
"""
:param name: 元素定位的方式
:param value: 元素定位的路径
:return:
"""
el = self.driver.find_element(name,value)
self.locate_station(el)
return el
def locate_station(self,element):
self.driver.execute_script(
"arguments[0].setAttribute('style',arguments[1]);",
element,
"border: 2px solid green"
)
def get_title(self):
return self.driver.title
def change_window(self, n):
handles = self.driver.window_handles
self.driver.switch_to.window(handles[n])
def close_window(self):
self.driver.close()
def mouse_hold(self, url):
btn = self.driver.find_elements_by_xpath(url)[0]
action = ActionChains(self.driver)
action.click_and_hold(btn).perform()
def change_frame(self, a):
self.driver.switch_to.frame(a)
def change_defaultFrame(self):
self.driver.switch_to.default_content()
@allure.step("网页title检查:{expect_title}")
def assert_title(self, expect_title):
result = self.driver.title
with allure.step("结果检查:(预期){1} in (实际){0}".format(result, expect_title)):
assert expect_title in result
sleep(2)
@allure.step("滑动解锁")
def slider(self, url):
slider = self.driver.find_elements_by_xpath(url)[0]
action = ActionChains(self.driver)
action.click_and_hold(slider).perform()
action.move_by_offset(350, 0).perform()
@allure.step("滑动解锁,慢滑版")
def slider_by_step(self, url):
slider = self.driver.find_elements_by_xpath(url)[0]
action = ActionChains(self.driver)
action.click_and_hold(slider).perform()
for index in range(300):
try:
action.move_by_offset(10, 0).perform()
except UnexpectedAlertPresentException:
break
sleep(0.1)
def locate_by_js(self):
js = "document.querySelector('center span#nc_1_n1z').scrollIntoView(true);"
self.driver.execute_script(js)
"""
淘宝首页登录
https://login.taobao.com/
page_indexLogin
"""
page_indexLogin_user = ['id','fm-login-id']
page_indexLogin_pwd = ['id','fm-login-password']
page_indexLogin_loginBtn = ['xpath', "//div[@class='fm-btn']"]
"""
淘宝首页
www.taobao.com
page_index
"""
page_index_search = ["xpath",'//div[@class="search-suggest-combobox"]/input']
page_index_searchBtn = ["xpath","//div[@class='search-button']"]
"""
购物车详情页
CART_LOGIN_URL
page_cartDetail
"""
page_cartDetail_selectAll = ["id","J_SelectAll1"]
page_cartDetail_payBtn = ["xpath","//div[@class='btn-area']"]
page_cartDetail_submitBtn = ["link text","提交订单"]
page_cartDetail_delBtn = ["link text","删除"]
page_cartDetail_closeBtn = ["partial link text","闭"]
page_cartDetail_confirmBtn = ["partial link text","确"]
page_cartDetail_colorClum = "//p[@class='sku-line']"
page_cartDetail_modifyBtn = ["xpath","//span[text()='修改']"]
page_cartDetail_colors = ["xpath","//div[@class='sku-edit-content']/div/dl/dd/ul/li[2]"]
page_cartDetail_colorsConfirmBtn = ["xpath","//div[@class='sku-edit-content']/div/p/a"]
page_cartDetail_favorites = ["link text","移入收藏夹"]
page_cartDetail_singleGoodsClum = "//div[@class='order-content']"
page_cartDetail_similarGoodsLink = ["link text","相似宝贝"]
page_cartDetail_simlarGoddsNext = ["xpath","//a[contains(@class,'J_fs_next')]"]
page_cartDetail_simlarGoods = ["xpath","//div[@class='find-similar-body']/div/div/div[2]"]
from time import sleep
import allure
from class37.p07.VAR.TAOBAO_VAR import PASSWD, USERNAME
from class37.p07.key_world.keyword import WebKeys
from class37.p07.locate import allPages
from class37.p07.logic.cartLogin_page import CatLoginPage
class CartPage(WebKeys):
@allure.step("商品结算")
def pay(self):
with allure.step("流程代码路径: %s" % __file__):
pass
loginPage = CatLoginPage(self.driver)
loginPage.login(USERNAME,PASSWD)
with allure.step("点击全选按钮"):
self.locator(*allPages.page_cartDetail_selectAll).click()
sleep(1)
with allure.step("点击结算按钮"):
self.locator(*allPages.page_cartDetail_payBtn).click()
sleep(1)
from time import sleep
import allure
from class37.p07.key_world.keyword import WebKeys
from class37.p07.locate import allPages
class CatLoginPage(WebKeys):
@allure.step("登录")
def login(self,username,password,expect_title):
"""
:param username:
:param password:
:param expect_title: 登录后断言,期望网页title包含字符串
:return:
"""
with allure.step("流程代码路径: %s"%__file__):
pass
with allure.step("打开网页"):
self.open("CART_LOGIN_URL")
with allure.step("输入账户"):
self.locator(*allPages.page_indexLogin_user).send_keys(username)
with allure.step("输入密码"):
self.locator(*allPages.page_indexLogin_pwd).send_keys(password)
with allure.step("点击登录"):
self.locator(*allPages.page_indexLogin_loginBtn).click()
sleep(2)
self.assert_title(expect_title)
from time import sleep
import allure
import pytest
from class37.p07.VAR.TAOBAO_VAR import USERNAME, PASSWD, TAOBAO_URL
from class37.p07.key_world.keyword import WebKeys
from class37.p07.logic.cartLogin_page import CatLoginPage
from class37.p07.logic.cart_page import CartPage
from class37.p07.data import yaml_driver
from class37.p07.locate import allPages
@allure.title("淘宝搜索")
@pytest.mark.parametrize('data',yaml_driver.load_yaml('./data/taobao_search.yaml'))
def test_taobao_search(browser,data):
wk = WebKeys(browser)
with allure.step("打开淘宝首页"):
wk.open(TAOBAO_URL)
sleep(2)
with allure.step("淘宝搜索: "+data["txt"]):
wk.locator(*allPages.page_index_search.send_keys(data["txt"]))
wk.locator(*allPages.page_index_searchBtn).click()
import os
from time import sleep
import allure
import pytest
from selenium import webdriver
@pytest.fixture(scope='function')
def browser():
"""
全局定义浏览器驱动,方便下面的hook函数引用driver
:return:
"""
global driver
os.popen("d:/chrome.bat")
sleep(3)
options = webdriver.ChromeOptions()
options.debugger_address = '127.0.0.1:9222'
driver = webdriver.Chrome(options=options)
sleep(2)
driver.implicitly_wait(10)
"""
yield之前的代码是用例前置
yield之后的代码是用例后置
"""
yield driver
"""
这种debug模式,下面的方法无法退出浏览器
driver.quit()
driver.close()
"""
os.system('taskkill /im chromedriver.exe /F')
os.system('taskkill /im chrome.exe /F')
"""
装饰器@pytest.hookimpl(hookwrapper=True)等价于@pytest.mark.hookwrapper的作用:
a.可以获取测试用例的信息,比如用例函数的描述
b.可以获取测试用例的结果,yield,返回一个result对象
"""
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport():
out = yield
"""
从返回一个result对象(out)获取调用结果的测试报告,返回一个report对象
report对象的属性
包括when(setup,call,teardown三个值)、nodeid(测试用例的名字)、
outcome(用例的执行结果:passed,failed)
"""
report = out.get_result()
if report.when == 'call':
xfail = hasattr(report,"wasfail")
if(report.skipped and xfail) or (report.failed and not xfail):
with allure.step("添加失败截图。。"):
allure.attach(driver.get_screenshot_as_png(),"失败截图",allure.attachment_type.PNG)
import os
import pytest
def run():
pytest.main(['-v','--alluredir','./report/result','--clean-alluredir'
])
os.system('allure generate ./report/result -o ./report/report_allure/ --clean')
if __name__ == '__main__':
run()
3.Web自动化用例编写
"""
变量统一管理文件,为了方便代码中识别,目录,文件,变量名全部大写
"""
CART_LOGIN_URL = "CART_LOGIN_URL"
USERNAME = "云纱璃英"
PASSWD = "xxx"
TAOBAO_URL = "http://www.taobao.com"
-
txt: 迈巴赫
import yaml
def load_yaml(path):
file = open(path,'r',encoding='utf-8')
data = yaml.load(file,Loader = yaml.Fullloader)
return data
chrome.exe --remote-debugging-port=9222
"""
使用编写的脚本以debug模式启动谷歌浏览器,脚本内容如下
chrome.exe --remote-debugging-port=9222
必须通过脚本执行,使用os.system执行命令无效
"""
from time import sleep
from class37.p08.VAR.TAOBAO_VAR import USERNAME, PASSWD
from class37.p08.key_world.keyword import WebKeys
from class37.p08.locate import allPages
from selenium import webdriver
options = webdriver.ChromeOptions()
options.debugger_address = '127.0.0.1:9222'
driver = webdriver.Chrome(options=options)
sleep(2)
wk = WebKeys(driver)
wk.locator(*allPages.page_goodsDetail_cartBtn).click()
sleep(1)
el = wk.locator(*allPages.page_goodsDetail_loginFrame)
wk.change_frame(el)
wk.locator(*allPages.page_indexLogin_user).send_keys(USERNAME)
wk.locator(*allPages.page_indexLogin_pwd).send_keys(PASSWD)
wk.locator(*allPages.page_indexLogin_loginBtn).click()
sleep(3)
el = wk.locator('xpath', "//div[@id='login']//iframe")
wk.change_frame(el)
wk.slider_by_step("//center//span[@id='nc_1_n1z']")
from time import sleep
import allure
from selenium import webdriver
from selenium.common import UnexpectedAlertPresentException
from selenium.webdriver import ActionChains
class WebKeys:
def __init__(self,driver):
self.driver = driver
def open(self,url):
self.driver.get(url)
def locator(self,name,value):
"""
:param name: 元素定位的方式
:param value: 元素定位的路径
:return:
"""
el = self.driver.find_element(name,value)
self.locate_station(el)
return el
def locate_station(self,element):
self.driver.execute_script(
"arguments[0].setAttribute('style',arguments[1]);",
element,
"border: 2px solid green"
)
def get_title(self):
return self.driver.title
def change_window(self, n):
handles = self.driver.window_handles
self.driver.switch_to.window(handles[n])
def close_window(self):
self.driver.close()
def mouse_hold(self, url):
btn = self.driver.find_elements_by_xpath(url)[0]
action = ActionChains(self.driver)
action.click_and_hold(btn).perform()
def change_frame(self, a):
self.driver.switch_to.frame(a)
def change_defaultFrame(self):
self.driver.switch_to.default_content()
@allure.step("网页title检查:{expect_title}")
def assert_title(self, expect_title):
result = self.driver.title
with allure.step("结果检查:(预期){1} in (实际){0}".format(result, expect_title)):
assert expect_title in result
sleep(2)
@allure.step("滑动解锁")
def slider(self, url):
slider = self.driver.find_elements_by_xpath(url)[0]
action = ActionChains(self.driver)
action.click_and_hold(slider).perform()
action.move_by_offset(350, 0).perform()
@allure.step("滑动解锁,慢滑版")
def slider_by_step(self, url):
slider = self.driver.find_elements_by_xpath(url)[0]
action = ActionChains(self.driver)
action.click_and_hold(slider).perform()
for index in range(300):
try:
action.move_by_offset(10, 0).perform()
except UnexpectedAlertPresentException:
break
sleep(0.1)
def locate_by_js(self):
js = "document.querySelector('center span#nc_1_n1z').scrollIntoView(true);"
self.driver.execute_script(js)
"""
淘宝首页登录
https://login.taobao.com/
page_indexLogin
"""
page_indexLogin_user = ['id','fm-login-id']
page_indexLogin_pwd = ['id','fm-login-password']
page_indexLogin_loginBtn = ['xpath', "//div[@class='fm-btn']"]
"""
淘宝首页
www.taobao.com
page_index
"""
page_index_search = ["xpath",'//div[@class="search-suggest-combobox"]/input']
page_index_searchBtn = ["xpath","//div[@class='search-button']"]
"""
搜索结果页
https://s.taobao.com/search
page_searchResults
"""
page_searchResults_good = ["xpath","//div[@class='items']/div[@data-index='0']"]
page_searchResults_old = ["link text","二手"]
"""
购物车详情页
CART_LOGIN_URL
page_cartDetail
"""
page_cartDetail_selectAll = ["id","J_SelectAll1"]
page_cartDetail_payBtn = ["xpath","//div[@class='btn-area']"]
page_cartDetail_submitBtn = ["link text","提交订单"]
page_cartDetail_delBtn = ["link text","删除"]
page_cartDetail_closeBtn = ["partial link text","闭"]
page_cartDetail_confirmBtn = ["partial link text","确"]
page_cartDetail_colorClum = "//p[@class='sku-line']"
page_cartDetail_modifyBtn = ["xpath","//span[text()='修改']"]
page_cartDetail_colors = ["xpath","//div[@class='sku-edit-content']/div/dl/dd/ul/li[2]"]
page_cartDetail_colorsConfirmBtn = ["xpath","//div[@class='sku-edit-content']/div/p/a"]
page_cartDetail_favorites = ["link text","移入收藏夹"]
page_cartDetail_singleGoodsClum = "//div[@class='order-content']"
page_cartDetail_similarGoodsLink = ["link text","相似宝贝"]
page_cartDetail_simlarGoddsNext = ["xpath","//a[contains(@class,'J_fs_next')]"]
page_cartDetail_simlarGoods = ["xpath","//div[@class='find-similar-body']/div/div/div[2]"]
"""
商品详情页
https://item.taobao.com/item.htm
page_goodsDetail
"""
page_goodsDetail_color = ["xpath","//div[@class='tb-skin']/dl/dd/ul/li"]
page_goodsDetail_num = ["xpath","//input[@title='请输入购买量']"]
page_goodsDetail_cartBtn = ["partial link text","加入购物"]
page_goodsDetail_loginFrame = ["xpath","//iframe[@class]"]
page_goodsDetail_loginUser = ["id","fm-login-id"]
page_goodsDetail_loginPwd = ["id","fm-login-password"]
page_goodsDetail_loginBtn = ["xpath","//div[@class='fm-btn']"]
page_goodsDetail_payBtn = ["partial link text","去购物车结算"]
from time import sleep
import allure
from class37.p08.VAR.TAOBAO_VAR import PASSWD, USERNAME
from class37.p08.key_world.keyword import WebKeys
from class37.p08.locate import allPages
from class37.p08.logic.cartLogin_page import CatLoginPage
class CartPage(WebKeys):
@allure.step("商品结算")
def pay(self):
with allure.step("流程代码路径: %s" % __file__):
pass
with allure.step("点击全选按钮"):
self.locator(*allPages.page_cartDetail_selectAll).click()
sleep(1)
with allure.step("点击结算按钮"):
self.locator(*allPages.page_cartDetail_payBtn).click()
sleep(1)
from time import sleep
import allure
from class37.p08.key_world.keyword import WebKeys
from class37.p08.locate import allPages
class CatLoginPage(WebKeys):
@allure.step("登录")
def login(self,username,password,expect_title):
"""
:param username:
:param password:
:param expect_title: 登录后断言,期望网页title包含字符串
:return:
"""
with allure.step("流程代码路径: %s"%__file__):
pass
with allure.step("打开网页"):
self.open("CART_LOGIN_URL")
with allure.step("输入账户"):
self.locator(*allPages.page_indexLogin_user).send_keys(username)
sleep(2)
with allure.step("输入密码"):
self.locator(*allPages.page_indexLogin_pwd).send_keys(password)
sleep(2)
with allure.step("点击登录"):
self.locator(*allPages.page_indexLogin_loginBtn).click()
sleep(3)
self.assert_title(expect_title)
from time import sleep
import allure
from class37.p08.VAR.TAOBAO_VAR import PASSWD, USERNAME
from class37.p08.key_world.keyword import WebKeys
from class37.p08.locate import allPages
from class37.p08.logic.cartLogin_page import CatLoginPage
from class37.p08.logic.cart_page import CartPage
class GoodsSale(WebKeys):
@allure.step("淘宝搜索商品:{goodsname}")
def goodsSearch(self,goodsname):
"""
:param goodsname:搜索商品名
:return:
"""
with allure.step("流程代码路径: %s" % __file__):
pass
with allure.step("搜索: "+goodsname):
self.locator(*allPages.page_index_search).send_keys(goodsname)
self.locator(*allPages.page_index_searchBtn).click()
sleep(2)
self.assert_title(goodsname)
@allure.step("登录框登录")
def login_frame(self,username,passwd,expect_title):
with allure.step("流程代码路径: %s" % __file__):
pass
el = self.locator(*allPages.page_goodsDetail_loginFrame)
with allure.step("切换到登录框frame"):
self.change_frame(el)
sleep(3)
with allure.step("调用登录流程"):
login = CatLoginPage(self.driver)
login.login(USERNAME, PASSWD)
with allure.step("切换回默认的frame"):
self.change_defaultFrame()
sleep(3)
self.assert_title(expect_title)
sleep(2)
@allure.step("淘宝购买商品")
def shopping(self):
with allure.step("流程代码路径: %s" % __file__):
pass
'''
找不到元素,也能继续运行
方法1:
try:
elem = driver.find_element_by_name('...')
except:
pass
方法2:
elems = driver.find_elements_by_name('...')
if len(elems)>0:
elem = elems[0]
'''
with allure.step("判断是否有登录页,有就登录"):
try:
login = CatLoginPage(self.driver)
login.login(USERNAME,PASSWD)
except:
with allure.step("未出现登录页,跳过"):
pass
with allure.step("选择二手"):
self.locator(*allPages.page_searchResults_old).click()
sleep(2)
with allure.step("选择商品"):
self.locator(*allPages.page_searchResults_good).click()
sleep(2)
with allure.step("窗口切换"):
self.change_window(1)
sleep(1)
with allure.step("点击加入购物车按钮"):
self.locator(*allPages.page_goodsDetail_cartBtn).click()
sleep(1)
with allure.step("判断是否有登录框,有就登录"):
try:
self.login_frame(USERNAME,PASSWD,'成功')
except:
with allure.step("未出现登录页,跳过"):
pass
with allure.step("点击购物车结算按钮"):
self.locator(*allPages.page_goodsDetail_payBtn).click()
sleep(3)
self.assert_title("我的购物车")
sleep(5)
cartPay = CartPage(self.driver)
cartPay.pay()
from time import sleep
import allure
import pytest
from class37.p08.VAR.TAOBAO_VAR import USERNAME, PASSWD, TAOBAO_URL
from class37.p08.key_world.keyword import WebKeys
from class37.p08.logic.cartLogin_page import CatLoginPage
from class37.p08.logic.cart_page import CartPage
from class37.p08.data import yaml_driver
from class37.p08.locate import allPages
@allure.title("淘宝搜索")
@pytest.mark.parametrize('data',yaml_driver.load_yaml('./data/taobao_search.yaml'))
def test_taobao_search(browser,data):
wk = WebKeys(browser)
with allure.step("打开淘宝首页"):
wk.open(TAOBAO_URL)
sleep(2)
with allure.step("淘宝搜索: "+data["txt"]):
wk.locator(*allPages.page_index_search.send_keys(data["txt"]))
wk.locator(*allPages.page_index_searchBtn).click()
from time import sleep
import allure
from class37.p08.VAR.TAOBAO_VAR import *
from class37.p08.logic.shopping_page import GoodsSale
from class37.p08.locate import allPages
@allure.title("淘宝商品订购")
def test_goodsSale(browser):
goodssale = GoodsSale(browser)
with allure.step("打开浏览器:"+TAOBAO_URL):
goodssale.open(TAOBAO_URL)
goodssale.goodsSearch("膳魔师")
goodssale.shopping()
@allure.title("删除全部购物车的商品"):
def test_del_goods(browser):
goodssale = GoodsSale(browser)
with allure.step("打开浏览器:" + TAOBAO_URL):
goodssale.open(TAOBAO_URL)
goodssale.goodsSearch("膳魔师")
goodssale.shopping()
with allure.step("打开购物车"):
goodssale.open(CART_LOGIN_URL)
with allure.step("全选商品"):
goodssale.locator(*allPages.page_cartDetail_selectAll).click()
sleep(3)
with allure.step("点击删除按钮"):
goodssale.locator(*allPages.page_cartDetail_delBtn).click()
sleep(3)
with allure.step("点击确认按钮"):
goodssale.locator(*allPages.page_cartDetail_colorsConfirmBtn).click()
sleep(3)
import os
from time import sleep
import allure
import pytest
from selenium import webdriver
@pytest.fixture(scope='function')
def browser():
"""
全局定义浏览器驱动,方便下面的hook函数引用driver
:return:
"""
global driver
os.popen("d:/chrome.bat")
sleep(3)
options = webdriver.ChromeOptions()
options.debugger_address = '127.0.0.1:9222'
driver = webdriver.Chrome(options=options)
sleep(2)
driver.implicitly_wait(10)
"""
yield之前的代码是用例前置
yield之后的代码是用例后置
"""
yield driver
"""
这种debug模式,下面的方法无法退出浏览器
driver.quit()
driver.close()
"""
os.system('taskkill /im chromedriver.exe /F')
os.system('taskkill /im chrome.exe /F')
"""
装饰器@pytest.hookimpl(hookwrapper=True)等价于@pytest.mark.hookwrapper的作用:
a.可以获取测试用例的信息,比如用例函数的描述
b.可以获取测试用例的结果,yield,返回一个result对象
"""
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport():
out = yield
"""
从返回一个result对象(out)获取调用结果的测试报告,返回一个report对象
report对象的属性
包括when(setup,call,teardown三个值)、nodeid(测试用例的名字)、
outcome(用例的执行结果:passed,failed)
"""
report = out.get_result()
if report.when == 'call':
xfail = hasattr(report,"wasfail")
if(report.skipped and xfail) or (report.failed and not xfail):
with allure.step("添加失败截图。。"):
allure.attach(driver.get_screenshot_as_png(),"失败截图",allure.attachment_type.PNG)
import os
import pytest
def run():
pytest.main(['-v','--alluredir','./report/result','--clean-alluredir','./test_case/test_taobao2.py'
])
os.system('allure generate ./report/result -o ./report/report_allure/ --clean')
if __name__ == '__main__':
run()