appium学习总结19 - PO设计模式

摘要

  1. PageObject设计模式
  2. PageObject六大设计原则
  3. PageObject第一个例子
  4. BasePage封装改进
  5. PO自动化测试实战内容

1、PageObject的历史及发展

1、https://martinfowler.com/bliki/PageObject.html
2、https://github.com/SeleiumHQ/selenium/wiki/PageObjects
3、https://selenium-python.readthedocs.io/page-objects.html
4、https://pypom.readthedocs.io/en/latest/

2、Page Object Model的基本原则

2.1 方法

  1. 用公共方法代表UI所提供的功能
  2. 方法应该返回其他的Page Object 或者 返回哦那个与断言的数据
  3. 同样的行为不同的结果可以建模不同的方法
  4. 不要在方法内加断言

2.2 字段

  1. 不要暴露页面内容的元素给外部
  2. 不需要建模UI内的所有元素

3、第一个例子

page目录下的 search_page.py:

class SearchPage():
    def __init__(self, driver):
        self.driver = driver

    def search(self, key):
        self.driver.find_element(key).click()
        return self

    def get_current_price(self):
        return float(self.driver.find_element().text)

测试用例py文件:

from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from page.search_page import SearchPage

class TestDemo:

    def setup(self):
        caps = {
            "platformName": "android",
            "deviceName": "008640dd0804",
            "automationName": "uiautomator2",
            "appPackage": "com.xueqiu.android",
            "appActivity": ".view.WelcomeActivityAlias",
            "autoGrantPermissions": "true"
        }

        self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
        self.driver.find_element(AppiumBy.ID, "com.xueqiu.android:id/tv_agree").click()
        self.driver.implicitly_wait(20)

    def test_search_page(self):
        search_page = SearchPage(self.driver)
        search_page.search("alibaba")
        assert search_page.get_current_price() > 10

    def teardown(self):
        self.driver.quit()

4、进一步封装basepage.py

basepage.py:

  1. 实现通用的page方法,对常用的自动化行为做封装

1、异常弹框处理:广告、好评、升级、tips等弹框
2、通用自动化能力封装

  1. 管理各种driver
  2. 减少每个page对Appium、Selenium等库的太多依赖
from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait


class BasePage:
    def __init__(self, driver: WebDriver):
        self.driver = driver

    def click(self, element):
        self.__wait(element)
        self.driver.find_element(AppiumBy.XPATH, element).click()

    def type(self, element, sendvalue):
        self.__wait(element)
        self.driver.find_element(AppiumBy.XPATH, element).send_keys(sendvalue)

    def __wait(self, element):
        WebDriverWait(self.driver, 20).until(lambda x: self.driver.find_element(AppiumBy.XPATH, element))

业务层封装:

from page.basepage import BasePage


class SearchPage(BasePage):

    def search(self, key):
        self.click("某元素的值")
        return self.type("element", "sendvalue")

    def get_current_price(self):
        return float(self.driver.find_element().text)

用例层封装:

from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from page.search_page import SearchPage

class TestDemo:

    def setup(self):
        caps = {
            "platformName": "android",
            "deviceName": "008640dd0804",
            "automationName": "uiautomator2",
            "appPackage": "com.xueqiu.android",
            "appActivity": ".view.WelcomeActivityAlias",
            "autoGrantPermissions": "true"
        }

        self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
        self.driver.find_element(AppiumBy.ID, "com.xueqiu.android:id/tv_agree").click()
        self.driver.implicitly_wait(20)

    def test_search_page(self):
        search_page = SearchPage()
        search_page.search("alibaba")
        assert search_page.get_current_price() > 10

    def teardown(self):
        self.driver.quit()

5、完整版本的框架例子

5.1、测试用例管理:

  • 使用package管理业务模块
  • 使用class管理业务对象、使用method完成业务具体行为
  • 数据驱动:测试数据、测试步骤、测试断言
  • 测试用例:使用testcase完成测试步骤的定位,使用assertion完成业务正确性校验
  • 持续集成:使用jenkins完成持续集成

5.2、基于POM的用例组织结构

  • page:完成对页面的封装
  • driver:完成对web、android、ios、接口的驱动
  • testcase:调用各类page完成业务流程并进行断言
  • data:配置文件和数据驱动
  • until:其他便捷的功能封装,可选

5.3、代码示例

在这里插入图片描述
app.py

from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.webdriver import WebDriver
from page.main_page import MainPage


class App:
    driver: WebDriver = None

    @classmethod  # 类方法,不需要实例化就可以被调用,比如:App.start()
    def start(cls):
        caps = {
            "platformName": "android",
            "deviceName": "008640dd0804",
            "automationName": "uiautomator2",
            "appPackage": "com.xueqiu.android",
            "appActivity": ".view.WelcomeActivityAlias",
            "autoGrantPermissions": "true"
        }
        cls.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
        cls.driver.find_element(AppiumBy.ID, "com.xueqiu.android:id/tv_agree").click()
        cls.driver.implicitly_wait(20)
        return MainPage(cls.driver)

    @classmethod
    def quit(cls):
        cls.driver.quit()

basepage.py

from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait


class BasePage:
    _black_list = ["image_cancel", "tips"]

    def __init__(self, driver: WebDriver):
        self.driver = driver

    def click(self, element):
        self.__handle_exception()
        self.__wait(element)
        self.driver.find_element(AppiumBy.XPATH, element).click()

    def type(self, element, sendvalue):
        self.__wait(element)
        self.driver.find_element(AppiumBy.XPATH, element).send_keys(sendvalue)

    def __wait(self, element):
        WebDriverWait(self.driver, 20).until(lambda x: self.driver.find_element(AppiumBy.XPATH, element))

    # 自动处理广告、好评、升级、tips弹框等
    def __handle_exception(self):
        self.driver.implicitly_wait(0)
        for locator in self._black_list:
            elements = self.driver.find_elements(AppiumBy.XPATH, locator)
            if elements[0]:
                elements[0].click()
            else:
                print(f"没有找到{locator}")
            # page_source = self.driver.page_source
            # if "image_cancel" in page_source:
            #     self.driver.find_element(AppiumBy.XPATH, locator).click()
            # elif "tips" in page_source:
            #     pass
        self.driver.implicitly_wait(6)

main_page.py

from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.webdriver import WebDriver
from page.basepage import BasePage
from page.search_page import SearchPage


# 基础封装
class MainPage:
    def __init__(self, driver: WebDriver):
        self.driver = driver

    def search_page(self):
        self.driver.find_element(AppiumBy.XPATH, "xxx").click()
        return SearchPage(self.driver)


# 继承了basepage的封装
class MainPage1(BasePage):

    def search_page(self):
        self.driver.find_element(AppiumBy.XPATH, "xxx").click()
        return SearchPage(self.driver)

    def search_page2(self):
        self.click("xxx")
        self.driver.find_element(AppiumBy.XPATH, "xxx").click()

search_page.py

from appium.webdriver.common.appiumby import AppiumBy
from appium.webdriver.webdriver import WebDriver

from page.basepage import BasePage


class SearchPage:

    def __init__(self, driver: WebDriver):
        self.driver = driver

    def search(self, key):
        self.driver.find_element(AppiumBy.XPATH, key).click()

    def get_current_price(self):
        return float(self.driver.find_element().text)


# 继承了basepage的封装
class SearchPage1(BasePage):

    def search(self, key):
        self.click("xxx")
        self.driver.find_element(AppiumBy.XPATH, key).click()

    def get_current_price(self):
        return float(self.driver.find_element("xxx").text)

test.py

from page.app import App
import time


class TestDemo:

    def setup(self):
        self.search_page = App.start().search_page()

    def test_search_page(self):
        self.search_page.search("alibaba")
        assert self.search_page.get_current_price() > 10

    def teardown(self):
        time.sleep(10)
        App.quit()


  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿_焦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值