PO设计模式(企业微信添加联系人)---7

PO原则:
方法意义:
  • 用公共方法代表UI所提供的服务;
  • 方法应该返回其他的PageObject或者返回用于断言的数据;
  • 同样的行为不同的结果可以建模不同的方法;
  • 不要在方法内加断言;
字段意义:
  • 不要暴露页面内部元素给外部;
  • 不需要建模UI内的所有元素。
主要组成元素
  1. Page对象:完成对页面的封装;
  2. Driver对象:完成对web、android、ios、接口的驱动;
  3. 测试用例:调用Page对象实现业务并断言;
  4. 数据封装:配置文件和数据驱动;
  5. Utils:其他功能封装,改变原生框架不足。
常用命令
adb shell "uiautomator dump && cat /sdcard/window_dump.xml"  #获取当前页面布局结构

针对循环导入的方式,采用局部导入

PO改造
  1. 搭建PO框架,对不同页面进行封装;
  2. 填充代码,后续只需要更改PO中的代码,业务逻辑不需要更改;
  3. 对公共方法进行封装;初始化封装,复用driver
举例

企业微信添加联系人的PO封装:
企业微信PO封装框架图

  1. 创建数据存储文件夹datas,页面Pages,测试用例testcases;
    page各个页面封装框架
  2. Page对各个页面进行封装,对于企业微信添加联系人来说,主要封装页面包括:app相关(启动、关闭、重启等),主页,联系人页面,联系人添加页面,添加页面,基本功能(driver find等)。
    配置相关数据,比如caps中的相关内容
  3. datas中可以创建yaml文件存放caps中devicesName、platformName、IP等内容;

各个Page页面实现代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from appium.webdriver.common.mobileby import MobileBy

from app.page.addresslist_page import AddressListPage
from app.page.base_page import BasePage


class MainPage(BasePage):

    """
    BasePage中封装,所以去除
    """
    # def __init__(self,driver):
    #     self.driver = driver

    ## 通讯录全局使用,所以定义为全局变量
    address_element = (MobileBy.XPATH, "//*[@text='通讯录']")

    """由于每次都要使用self.driver,所以需要对其进行init"""
    def goto_message(self):
        """
        进入到消息页
        :return:
        """
        pass

    def goto_address(self)->AddressListPage:
        """
        进入联系人页
        :return:
        """
        self.find_and_click(*self.address_element)
        return AddressListPage(self.driver)

    def goto_workspace(self):
        """
        进入工作台
        :return:
        """
        pass

    def goto_me(self):
        """
        进入个人信息
        :return:
        """
        pass

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 通讯录界面
from appium.webdriver.common.mobileby import MobileBy

from app.page.base_page import BasePage
from app.page.member_invite_menu_page import MemberInviteMenuPage


class AddressListPage(BasePage):

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

    def click_addmember(self)->MemberInviteMenuPage:
        """
        点击添加联系人页面:滚动查找【添加成员】
        :return:
        """
        self.driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,
                                 'new UiScrollable(new UiSelector()\
                                 .scrollable(true).instance(0))\
                                 .scrollIntoView(new UiSelector()\
                                 .text("添加成员").instance(0));').click()

        return MemberInviteMenuPage(self.driver)
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
app.py 模块,存放app相关的一些操作。
比如 启动应用,重启应用,停止应用,进入到首页
"""
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import yaml
from appium import webdriver

from app.page.base_page import BasePage
from app.page.main_page import MainPage

"""使用yaml方式传入caps所需要的相关值"""
with open('../datas/caps.yml') as f:
    myconfig = yaml.safe_load(f)
    caps = myconfig['desirecaps']
    ip = myconfig['server']['ip']
    port = myconfig['server']['port']

class AppPage:

    def start(self):
        """为了避免第二次安装服务影响时间,对driver进行判断,如果已经存在,不再重复启动"""
        if self.driver == None:
            # 启动app
            # 定义了一个字典
            # caps = {}
            # caps["platformName"] = "Android"
            # caps["deviceName"] = "hogwarts"
            # caps["appPackage"] = "com.tencent.wework"
            # caps["appActivity"] = ".launch.LaunchSplashActivity"
            # # noReset 保留缓存, 比如登录状态
            # caps["noReset"] = "True"
            # # 不停止应用,直接运行测试用例
            # # caps["dontStopAppOnReset"] = "true"
            # caps['skipDeviceInitialization'] = 'true'
            # caps['skipServerInstallation'] = 'true'
            # # caps["settings[waitForIdleTimeout]"] = 0
            # # 关键  localhost:4723  本机ip:server端口
            self.driver = webdriver.Remote(f"http://{ip}:{port}/wd/hub", caps)
            self.driver.implicitly_wait(5)
        else:
            self.driver.launch_app()
            # self.driver.start_activity(package,activity)

        return self

    def restart(self):
        # 重启 app
        self.driver.close_app()
        self.driver.launch_app()
        pass

    def stop(self):
        # 停止 app
        self.driver.quit()

    def goto_main(self) -> MainPage:
        # 进入到首页
        return MainPage(self.driver)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
base_page.py 基类模块:主要用于初始化driver, 定义find, 常用的最基本的方法
"""
import logging
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.webdriver import WebDriver

class BasePage:
    """
    log的打印,level=logging.INFO是可变的
    """
    root_logger = logging.getLogger()
    print(f"root_logger.handlers:{logging.getLogger().handlers}")
    for h in root_logger.handlers[:]:
        root_logger.removeHandler(h)
    logging.basicConfig(level=logging.INFO)

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

    def find(self, by, locator):
        """
        对find_element方法进行封装
        """
        # logging.info("aaaaa")
        logging.info(by)
        logging.info(locator)
        return self.driver.find_element(by, locator)

    def find_and_click(self, by, locator):
        """
        在find_element方法上对click方法进行封装
        """
        logging.info('click')
        self.find(by, locator).click()

    def find_by_scroll(self, text):
        """
        对滑动寻找方式进行封装
        """
        logging.info('find_by_scroll')
        logging.info(text)
        return self.driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,
                                        f'new UiScrollable(new UiSelector()\
                                 .scrollable(true).instance(0))\
                                 .scrollIntoView(new UiSelector()\
                                 .text("{text}").instance(0));')

    def get_toast_text(self):
        """
        对获取toast页面的text值进行封装
        """
        logging.info('get_toast_text')
        result = self.find(MobileBy.XPATH, "//*[@class='android.widget.Toast']").text
        logging.info(result)
        return result
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
编辑联系人页面
"""
from appium.webdriver.common.mobileby import MobileBy
from selenium.webdriver.support.wait import WebDriverWait

# from app.page.member_invite_menu_page import MemberInviteMenuPage
from app.page.base_page import BasePage


class ContactAddPage(BasePage):

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

    """需要将参数抽离出来"""
    def add_contact(self, name, gender, phonenum):
        # 设置 【用户名】【性别】【手机号】
        self.find(MobileBy.XPATH,
                  "//*[contains(@text, '姓名')]/../*[@text='必填']").send_keys(name)
        self.find(MobileBy.XPATH, "//*[contains(@text, '性别')]/..//*[@text='男']").click()

        if gender == "男":
            WebDriverWait(self.driver, 10).until(lambda x: x.find_element(MobileBy.XPATH, "//*[@text='女']"))
            self.find(MobileBy.XPATH, "//*[@text='男']").click()
        else:
            self.find(MobileBy.XPATH, "//*[@text='女']").click()

        self.find(MobileBy.XPATH,
                  '//*[contains(@text, "手机") and contains(@class, "TextView")]/..//android.widget.EditText').send_keys(
            phonenum)
        # 点击【保存】
        self.find(MobileBy.XPATH, "//*[@text='保存']").click()

        from app.page.member_invite_menu_page import MemberInviteMenuPage
        return MemberInviteMenuPage(self.driver)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
邀请页面
"""
from appium.webdriver.common.mobileby import MobileBy
# from app.page.contactadd_page import ContactAddPage
from app.page.base_page import BasePage


class MemberInviteMenuPage(BasePage):

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

    def add_member_menual(self):
        # 点击【手动输入添加】
        self.find(MobileBy.XPATH, "//*[@text='手动输入添加']").click()
        """由于ContactAddPage与MemberInviteMenuPage互相调用,所以会产生循环调用的问题,此时我们采用局部调用"""
        from app.page.contactadd_page import ContactAddPage
        return ContactAddPage(self.driver)

用例:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from app.page.app import AppPage


class TestContact:

    def setup(self):
        self.app = AppPage()
        self.main = self.app.start().goto_main()

    def teardown(self):
        self.app.stop()

    def test_addcontact(self):
        name = "hogwarts__004"
        gender = "男"
        phonenum = "13500000003"
        result = self.main.goto_address().\
            click_addmember().\
            add_member_menual().\
            add_contact(name, gender, phonenum).\
            get_toast()

        assert '添加成功' == result


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值