Python+selenium UI自动化一个小模式
本帖最后由 只有午安 于 2021-8-12 10:46 编辑来了这么久,看了很多帖子,都没有发现有UI自动化这个东西,本人测试行业,最近也自己在学习这个东西,就发出来到目前写的一起学习一下吧,最好有大佬提供一下框架的思路。
这个是模式是我在网上找的一个叫PO模式(Page Objects),找了很多,个人觉得这个模式还可以。有不对的地方请大佬指正。{:301_993:}
PO模式介绍
用官话说它是selenium中的一种页面对象设计模式(不是测试框架!是一种开展ui自动化测试的思想),把ui自动化测试中的每个页面抽象出来,将每个页面用到的业务逻辑(page类)和页面元素(locator类)各自封装起来,然后编写测试用例时只需要调用每个page中的业务逻辑方法即可。测试(用例)脚本不需要关注元素的定位情况,当元素位置发生变化时,只需修改对应页面元素的locator即可
使用页面对象模式的好处:
(1)创建可跨多个测试用例共享的可重用代码(每个测试用例只需调用page类中封装好的业务逻辑(操作)即可)。
(2)减少重复代码的数量。(如向输入框输入信息、单击操作等)
(3)如果用户界面发生变化,修改脚本只需要在一个地方进行更改。
BasePage页 (基类页,封装各种操作方法)
# coding: utf-8
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
class BasePage:
"""封装其他页面都会用到的方法"""
base_url = '某宝链接'
def __init__(self, driver):
self.driver = driver# 构造函数全局统一Driver
def open(self):
"""打开页面的方法"""
self.driver.get(self.base_url)# 启动浏览器打开链接
self.driver.maximize_window()# 最大化窗口
def find_element(self, locator):
"""定位元素的方法"""
try:
element = WebDriverWait(self.driver, 15).until(EC.presence_of_element_located(locator))
return element
except NoSuchElementException:
print('%s 页面无 %s 元素' % (self, locator))
def switch_frame(self, locator):
"""切换frame"""
return self.driver.swtich_to_frame(locator) # 切换frame后面暂未用到- -
def send_key(self, locator, value, clear_first=True):
"""输入方法"""
try:
if clear_first:
self.find_element(locator).clear() # 清空输入框
self.find_element(locator).send_keys(value) # 查找元素 send内容
except AttributeError:
print('%s 页面无 %s 元素' % (self, locator))
def click(self, locator):
"""点击方法"""
self.find_element(locator).click()
def get_current_url(self):
"""获取当前页面URL"""
return self.driver.current_url
def get_current_title(self):
"""获取当前页面标题"""
return self.driver.title
def switch_window(self):
"""
切换窗口
直接选择倒数第一个窗口
后续操作才会在新窗口继续执行
"""
nw = self.driver.window_handles
self.driver.switch_to.window(nw[-1])
return nw
locators页面 (存放页面内的元素位置)
from selenium.webdriver.common.by import By
class Locators():
"""元素定位器
元素位置改变
这里改"""
first_page_locators = {
'tblogo': (By.XPATH, '//div[@class="logo"]//h1/a'),
'search': (By.XPATH, '//*[@id="J_TSearchForm"]/div/button'),
'writer': (By.ID, 'q'), # '//input[@aria-label="请输入搜索文字"]'
'value' : "鸿星尔克"
}
if __name__ == "__main__":
t = Locators()
print(t.first_page_locators['writer'])
# print(t.first_page_locators['search'])
Page页 (需要操作业务的页面)
from papes.BasePage import BasePage
from locators.locators import Locators
# 此页面加操作
class Firstpage(BasePage):
value = Locators.first_page_locators["value"]
tblogo = Locators.first_page_locators['tblogo']
search = Locators.first_page_locators['search']
shuru = Locators.first_page_locators['writer']
def logo_click(self):
"""点击logo"""
self.click(self.tblogo)
def send_some(self):
"""输入框输入"""
self.send_key(self.shuru, self.value)
def search_click(self):
"""点击搜索"""
self.click(self.search)
if __name__ == "__main__":
t = Locators()
print(t.first_page_locators['writer'])
t01 页 (unittest页面,也就是用例页面,直接调用page页,看起来就不会太冗余)
import unittest
from time import sleep
from papes.Firstpage import Firstpage
from selenium import webdriver
from papes.BasePage import BasePage
class MyTestCase(unittest.TestCase):
@classmethod
def setUpClass(cls): # 只运行一次
print("开始测试")
def setUp(self): # 每运行一次用例前执行
# 实例化类 以及 赋值,方便调用
self.driver = webdriver.Chrome()
self.url = BasePage.base_url
self.page = Firstpage(self.driver)
self.page.open()
self.jilei = BasePage(self.driver)
def test_1(self): # 用例1
"""
加点等待时间等待页面元素加载
尽量少使用固定等待
- -我图方便才用这么多sleep
用多了会导致时间长点,影响效率
"""
self.driver.implicitly_wait(15)
sleep(3)
self.page.logo_click() # 调用Page页定义好的函数
sleep(3)
self.page.switch_window() # 切换窗口
print(self.driver.current_url) # 打印当前URL
sleep(3)
self.page.send_some() # 输入内容 :Send_keys:
sleep(3)
def tearDown(self): # 每运行一次用例后执行
sleep(2)
self.driver.quit()# 退出浏览器
if __name__ == '__main__':
unittest.main()
POM模式 这个设计的中心思想就是页面即对象。框架的话 也简单的 楼主其实已经实现了 整体框架 分为base、page、data、case、report 外加上ddt 和HTMLTestRunner 输出报告base 做为底层所有的动作,page将定位和操作步骤分开,data 测试数据的存储。 case 具体的页面用例。 report执行结果报告。
另外UI自动化成本太大。还是接口的比较实用。另外这个有个弊端就是一旦项目很大的情况下 整体的自动化项目会很臃肿因为页面变多了。每一个新页面就要写一个page文件,写一个case 文件。代码量还是偏高的。 Hangjau 发表于 2022-1-6 22:34
只做冒烟的话 还真不一定覆盖页面所有点击。冒烟是根据业务主流程走的,不用考虑页面其他控件。注意的话 ...
感谢您,我试试,我是第一次写ui自动化,领导并没有给出需要测试的项,按我的理解
这个系统主要作为查询使用,不同类型查询,例如,警告,黑名单,白名单。而且每一个查询的页面都是iframe,每次点击查询,都要进入和退出,并且查询项涉及到各种条件,例如时间、模糊查询、类型、型号。查询的结果是列表形式展示在页面,我之前的想法是点击一次查询(不添加任何条件)。然后判断返回的列表信息。
您看,我是不是走错了方向,
是否有更简单的方式? 本帖最后由 只有午安 于 2021-8-12 11:06 编辑
妥了,原来不能分页= = 额。我好像平时也是这样做。 谢谢分享啊 谢谢分享 那个啥 这种帖子可以描述的更普遍化一点 就是几乎到手把手给你解释那张 看的人懂了 就给评分了 syy 发表于 2021-8-13 09:47
那个啥 这种帖子可以描述的更普遍化一点 就是几乎到手把手给你解释那张 看的人懂了 就给评分了
代码里该注释的都注释了,好像没啥解释的了。。。{:301_979:}可能我就这拉跨水平吧 过来捧个场,,有所帮助{:301_978:} 很好的通用模板,将方法,元素定位+取值都封装好了,最后直接调用即可,稍微改改具体的值就是能用爬虫,挺适用于js头大的大站