App-UI自动化测试-PO模式/组件化封装

1.PO模式

具体什么是PO模式就不用详细介绍了,web自动化测试已经介绍过了,详细内容可参考此篇文章中的4.3.2UI自动化测试介绍_晒不黑的黑煤球的博客-CSDN博客_ui自动化测试

我这里新建了三个模块home_page.py(首页),login_page.py(登录页),user_page.py(用户页),也可以把登录页的内容放到用户页面中,具体编写代码如下

home_page.py代码如下:

from pages.native_page import NativePage


class HomePage(NativePage):
    # 点击我的柠檬
    locator_my = ('id', 'com.lemon.lemonban:id/navigation_my')

    def enter_userpage(self):
        """进入用户界面"""
        self.click(self.locator_my)

login_page.py代码如下:

from pages.native_page import NativePage


class LoginPage(NativePage):
    locator_mobile = ('id', 'com.lemon.lemonban:id/et_mobile')
    locator_pwd = ('id', 'com.lemon.lemonban:id/et_password')
    locator_login = ('id', 'com.lemon.lemonban:id/btn_login')

    def login(self, mobile, password):
        """登录"""
        self.type(self.locator_mobile, mobile)
        self.type(self.locator_pwd, password)
        self.click(self.locator_login)

    def get_error_info(self):
        """获取登录失败错误信息"""
        return self.get_toast_text()

user_page.py代码如下:

from pages.native_page import NativePage


class UserPage(NativePage):
    # 点击我的头像
    locator_avatar = ('id', 'com.lemon.lemonban:id/fragment_my_lemon_avatar_title')

    def click_login(self):
        """点击登录头像"""
        self.click(self.locator_avatar)

    def get_uesrname(self):
        """获取登录后用户名称"""
        return self.get_avatar_title()

native_page.py代码如下:(内容还是之前写的,我粘贴到一块了)

from selenium.webdriver import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as when


class MobileKey:
    ENTER = 66
    VOLUME_UP = 24
    VOLUME_DOWN = 25
    BACK = 4


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

    def click(self, locator):
        """点击"""
        wait = WebDriverWait(self.driver, timeout=5)
        condition = when.element_to_be_clickable(locator)
        element = wait.until(condition)
        ActionChains(self.driver).click(element).perform()

    def type(self, locator, words):
        """输入"""
        el = self.driver.find_element(*locator)
        el.send_keys(words)

    def get_toast_text(self):
        """获取错误信息"""
        toast = self.driver.find_element('xpath', '//android.widget.Toast')
        return toast.text

    def get_avatar_title(self):
        """获取登录后的头像名称"""
        title = self.driver.find_element('id', 'com.lemon.lemonban:id/fragment_my_lemon_avatar_title')
        return title.text

    def width(self):
        """获取app的宽度"""
        return self.driver.get_window_size()['width']

    def height(self):
        """获取app的高度"""
        return self.driver.get_window_size()['height']

    def swipe_left(self):
        """从右往左滑动"""
        self.driver.swipe(start_x=self.width() * 0.9, end_x=self.width() * 0.1,
                          start_y=self.height() * 0.5, end_y=self.height() * 0.5)

    def swipe_right(self):
        """从左往右滑动"""
        self.driver.swipe(start_x=self.width() * 0.1, end_x=self.width() * 0.9,
                          start_y=self.height() * 0.5, end_y=self.height() * 0.5)

    def swipe_up(self):
        """从下往上滑动"""
        self.driver.swipe(start_x=self.width() * 0.5, end_x=self.width() * 0.5,
                          start_y=self.height() * 0.9, end_y=self.height() * 0.1)

    def swipe_down(self):
        """从上往下滑动"""
        self.driver.swipe(start_x=self.width() * 0.5, end_x=self.width() * 0.5,
                          start_y=self.height() * 0.1, end_y=self.height() * 0.9)

    def enter(self):
        """回车"""
        self.driver.press_keycode(MobileKey.ENTER)

    def volume_up(self):
        """音量加"""
        self.driver.press_keycode(MobileKey.VOLUME_UP)

    def volume_down(self):
        """音量减"""
        self.driver.press_keycode(MobileKey.VOLUME_DOWN)

    def back(self):
        """返回"""
        self.driver.press_keycode(MobileKey.BACK)

conftest.py代码如下:

import pytest
from appium.webdriver import Remote

from pages.home_page import HomePage
from pages.login_page import LoginPage
from pages.user_page import UserPage


def get_driver():
    """"启动app"""
    caps = {"platformName": "Android",
            "udid": "emulator-5554",
            "appPackage": "com.lemon.lemonban",
            "appActivity": ".activity.WelcomeActivity",
            "chromedriverExecutableDir": "E:\driver"
            }
    driver = Remote(command_executor='http://127.0.0.1:4723/wd/hub',
                    desired_capabilities=caps)
    # 设置隐性等待
    driver.implicitly_wait(10)
    return driver


@pytest.fixture(name='app')  # 设置别名代替init_app
def init_app():
    """启动app"""
    d = get_driver()
    yield d
    d.quit()


@pytest.fixture()
def homepage(app):
    """初始化homepage"""
    return HomePage(app)


@pytest.fixture()
def userpage(app):
    """初始化userpage"""
    return UserPage(app)


@pytest.fixture()
def loginpage(app):
    """初始化loginpage"""
    return LoginPage(app)

测试用例代码如下:

from pages.home_page import HomePage
from pages.user_page import UserPage
from pages.login_page import LoginPage


class TestLogin:
    def test_login_failed(self, homepage: HomePage,
                          userpage: UserPage,
                          loginpage: LoginPage):
        """登录失败"""
        homepage.enter_userpage()
        userpage.click_login()
        loginpage.login('1817317991', '179913')
        assert loginpage.get_error_info() == '手机号码格式不正确'

    def test_login_success(self, homepage: HomePage,
                           userpage: UserPage,
                           loginpage: LoginPage):
        """登录成功"""
        homepage.enter_userpage()
        userpage.click_login()
        loginpage.login('18173179913', '179913')
        assert userpage.get_uesrname() == '雨泽'

运行结果:

App-UI自动化测试-PO模式/组件化封装_第1张图片

注意:

  1. 因为之前web端的自动化测试用例中,写过home_page,login_page,所以今天写的同名时,一直报错,所以我把conftest.py中的初始化home_page,login_page改了个名字
  2. 注意home_page.py,login_page.py,user_page.py中的代码,因为继承了NativePage类,所以不要再写self.driver的字眼了

2.组件化封装(分层设计) 

在app中的PO模式还是有所不同,因为好多app底部都是菜单栏,现在很多代码都被组件化了,所以我们可以把底部的菜单栏进行一下封装,这样 home_page,user_page中的类直接继承即可

新建menu.py代码如下:

from pages.native_page import NativePage


class Menu(NativePage):
    """底部菜单栏"""
    locator_homepage = ('id', 'com.lemon.lemonban:id/navigation_home')
    locator_tiku = ('id', 'com.lemon.lemonban:id/navigation_tiku')
    locator_userpage = ('id', 'com.lemon.lemonban:id/navigation_my')

    def enter_homepage(self):
        self.click(self.locator_homepage)

    def enter_tiku(self):
        self.click(self.locator_tiku)

    def enter_userpage(self):
        self.click(self.locator_userpage)

user_page.py中的其他代码无需修改,只要把继承的类修改成Menu即可

App-UI自动化测试-PO模式/组件化封装_第2张图片

home_page.py中代码可以全部删除掉,继承Menu类

App-UI自动化测试-PO模式/组件化封装_第3张图片

login_page.py代码不用修改,因为登录页面没有底部菜单栏

当然,看自己的选择,也可以不进行组件化封装,但这是一种思路,如果太多类存在的话,维护起来也是比较麻烦的 

你可能感兴趣的:(手机端,自动化,python,ui,测试用例)