赞
踩
我所在的公司是做保险业务的,每个保险产品在进行购买时都会有登录账号,输入付款的银行卡号,选择保险产品,填写个人信息,被保人信息、受益人信息等等,如果将每个产品的购买流程都写成自动化的线性脚本会很冗余,于是学习了PO思想,来改进框架
官网:https://martinfowler.com/bliki/PageObject.html
全称:page object model 简称:POM/PO
PO模式最核心的思想是分层,实现松耦合!实现脚本重复使用,实现脚本易维护性!
将每个页面封装成单独的类,讲具体的操作步骤封装成函数,从而实现高内聚、低耦合的理念。
作者:马丁·福勒
PageObject的核心思想是六大原则,掌握六大原则才可以进行 PageObject 实战演练,这是 PageObject的精髓所在。
selenium官方凝聚出六大原则,后面的PageObject使用都将围绕六大原则开展:
个人理解:
base_class 层用来放置一些对selenium、appium等原生框架的二次封装,如driver的实例、定位元素、点击事件等等。
class BaseClassAppium: # 打开手机APP def __init__(self, driver_base: WebDriver = None): desired_caps = { "settings[waitForIdleTimeout]": 0, # 等待应用闲置时间 'platformName': 'Android', # 被测手机是安卓 'platformVersion': '9', # 手机安卓版本 'deviceName': 'Mi9', # 设备名,安卓手机可以随意填写 'appPackage': 'com.tencent.wework', # 启动APP Package名称 'appActivity': '.launch.LaunchSplashActivity', # 启动Activity名称 'unicodeKeyboard': True, # 使用自带输入法,输入中文时填True 'resetKeyboard': True, # 执行完程序恢复原来输入法 'noReset': True, # 不要重置App "skipDeviceInitialization": True, # 跳过设备初始化 'newCommandTimeout': 6000, # 在假定客户端退出并结束会话之前,Appium将等待来自客户端的新命令(以秒为单位) 'automationName': 'UiAutomator2' # 使用哪个自动化引擎 # 'app': r'd:\apk\bili.apk', } if driver_base is None: info("driver 为 None, 实例化一个新的driver") # appium server和手机建立连接,并向appium server传递字典对象(包含手机与APP信息) self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", desired_capabilities=desired_caps) else: info("driver 不为 None, 复用之前的driver") # self.driver.launch_app() # 启用参数中的应用 self.driver = driver_base self.driver.implicitly_wait(12) def goto_home(self): from page_object.home_page import HomePage return HomePage(self.driver) # appium的二次封装 def find_element(self, location): try: element = self.driver.find_element(*location) except Exception as e: error("元素定位失败:", e) else: return element def find_elements(self, location): try: elements = self.driver.find_elements(*location) except Exception as e: error("元素定位失败:", e) else: return elements # 传值 def send_keys(self, location, value): self.find_element(location).send_keys(value)
page_object 表示页面对象层,以企业微信为例子,我们需要添加一个成员,会有主页、添加成员等页面,
我们将主页看成一个类,去通讯录页面看成一个方法
""" 企业微信:主页相关操作 1.主页->通讯录 2.主页->工作台 """ import time from logging import info import allure from base_class.base_class_appium import BaseClassAppium from appium.webdriver.common.mobileby import MobileBy @allure.feature("主页面") class HomePage(BaseClassAppium): # 通讯录 __txl = (MobileBy.XPATH, '//*[@text="通讯录"]') @allure.title("进入通讯录页面") def goto_address(self): """ 主页->通讯录 :return: AddressPage(self.driver) """ from page_object.address_page import AddressPage with allure.step("主页"): info("当前页面:企业微信主页") time.sleep(1) with allure.step("点击通讯录"): info("点击通讯录") self.find_element(self.__txl).click() with allure.step("进入通讯录页面"): info("进入通讯录页面") return AddressPage(self.driver)
我们在通讯录页面需要点击添加成员、删除成员、获取当前成员列表
""" 企业微信:主页相关操作 1.通讯录->添加成员 """ import time from logging import info import allure from appium.webdriver.common.mobileby import MobileBy from base_class.base_class_appium import BaseClassAppium @allure.feature("通讯录页面") class AddressPage(BaseClassAppium): __users = (MobileBy.CLASS_NAME, "android.widget.TextView") @allure.title("进入增加成员页面") def goto_add_user(self): from page_object.hand_add import HandAdd with allure.step("全局滑动点击添加成员"): info("全局滑动点击添加成员") self.qjhd_search("添加成员") info("进入添加成员页面") return HandAdd(self.driver) @allure.title("获取通讯录所有成员信息") def get_user(self): # com.tencent.wework:id/df9 with allure.step("获取所有的人员名单"): info("获取所有的人员名单") elements = self.find_elements(self.__users) users = [ele.text for ele in elements if ele.text != "添加成员"] time.sleep(3) info(f"所有成员和部门信息为{users}") return users @allure.title("删除成员") def remove_user(self, name): from page_object.personal_Information import PersonalInformation """ 删除联系人 :return: """ # 滑动查找,删除name with allure.step(f"滑动查找,删除{name}"): self.qjhd_search(name) return PersonalInformation(self.driver)
…
搭建PO框架:
一、搭建骨架(搭建链式调用)
二、完成基础封装:selenium的二次封装、pytest.ini、yaml文件的读取方法、conftest.py
三、丰富骨肉:继承base,将页面进行封装,一个页面一个类,函数为最小单元,一个函数为一个完整的流程,明确return的页面
四、在链式调用的基础上,实现数据驱动参数化,结合allure生成完美的测试报告
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。