APP自动化之PO

前言

我所在的公司是做保险业务的,每个保险产品在进行购买时都会有登录账号,输入付款的银行卡号,选择保险产品,填写个人信息,被保人信息、受益人信息等等,如果将每个产品的购买流程都写成自动化的线性脚本会很冗余,于是学习了PO思想,来改进框架

什么是PO模式

官网:https://martinfowler.com/bliki/PageObject.html
全称:page object model 简称:POM/PO

PO模式最核心的思想是分层,实现松耦合!实现脚本重复使用,实现脚本易维护性!
将每个页面封装成单独的类,讲具体的操作步骤封装成函数,从而实现高内聚、低耦合的理念。
作者
作者:马丁·福勒
在这里插入图片描述

PageObject 原则

在这里插入图片描述
PageObject的核心思想是六大原则,掌握六大原则才可以进行 PageObject 实战演练,这是 PageObject的精髓所在。

selenium官方凝聚出六大原则,后面的PageObject使用都将围绕六大原则开展:

  • 公共方法代表页面提供的服务
  • 不要暴露页面细节
  • 不要把断言和操作细节混用
  • 方法可以return到新打开的页面
  • 不要把整页内容都放到PO中
  • 相同的行为会产生不同的结果,可以封装不同结果

个人理解:

  • 将每个页面封装一个类,将重要的内容以函数的形式封装到这个类中
  • 将细节封装在方法或者类中,调用也是通过类和方法进行调用
  • 在一个流程中,页面之间要能够跳转
  • 不要再页面对象层中进行断言,所有的断言操作都放到测试用例中去进行
  • 不重要的内容不要封装,要尽量保证代码的简洁
  • 相同的行为,但是由于传入的数据不同从而导致不同的结果,这个要封装成不同的结果

PO模式的框架结构

在这里插入图片描述
在这里插入图片描述

  • base_class : selenium、appium等原生框架的二次封装
  • log :放置日志信息
  • PNG :放置截图信息
  • result2 : allure的报告源码
  • test_case : 表示测试用例
  • test data:表示测试数据
  • pytest.ini : 配置文件

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生成完美的测试报告

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值