学习笔记-BasePage封装

1. 如何封装page

  • 实现通用的page方法,对常用自动化做封装
  • 管理各种driver
  • 减少每个page对appium,selenium等库的依赖

2. 自动化行为封装

  • 异常弹框处理
  • 通过自动化能力封装

3. BasePage构成

  • 类的属性:各个元素的定位
  • 类的方法:各个元素的操作方法

4. 优点

  • 当某页面元素发生变化,只需要修改页面中的元素的定位,不需修改测试用例
  • 提高代码重用性,结构更加清晰
  • 测试用例发生变化,只需修改少数页面对象

5. BasePage示例

# -*- coding: utf-8 -*-#
# -----------------------
# Name: demo
# Description:  封装所有页面的公共方法
# Author: sofi
# Date: 2019-11-05
# -----------------------
import os
import time
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from Common.read_yaml_tool import ReadYamlTool
from Common.path_tool import screenshot_path
from Common.read_config_tool import ReadConfigTool


class BasePage:
    def __init__(self, apk_name):
        # 初始化webdriver
        if apk_name == 'client':
            self.readConf = ReadConfigTool('apk_client_info.ini')
            self.host = self.readConf.get_option_value('Client_DeviceConf', 'remoteHost')
            self.desired_cap = self.readConf.get_conf_dump_dict()['Client_DeviceConf']

        elif apk_name == 'launcher':
            self.readConf = ReadConfigTool('apk_launcher_info.ini')
            self.host = self.readConf.get_option_value('Launcher_DeviceConf', 'remoteHost')
            self.desired_cap = self.readConf.get_conf_dump_dict()['Launcher_DeviceConf']

        try:
            self.driver = webdriver.Remote(self.host, self.desired_cap)

            # 隐式等待10秒
            self.driver.implicitly_wait(10)
            print('当前activity:{}'.format(self.driver.current_activity))
            self.driver.wait_activity('com.sudiyi.apps.launcher.IndexActivity',10)
            # 返回driver
            # return self.driver

        except Exception as e:
            print('[ERROR]-生成DRIVER失败..原因:{}'.format(e))

    '''====================================元素定位函数===================================='''

    def find_element(self, pagename, elename):
        '''
        查找元素
        :param pagename:页面名称
        :param elename:  元素名称
        :return:
        '''
        #读取元素信息
        ele_info = self.get_ele_info(pagename,elename)
        # print(ele_info[0])
        if ele_info[0] == 'By.ID':
            BY_KEY = By.ID
        elif ele_info[0] == 'By.XPATH':
            BY_KEY = By.XPATH
        elif ele_info[0] == 'By.NAME':
            BY_KEY = By.NAME
        elif ele_info[0] == 'By.CLASS_NAME':
            BY_KEY = By.CLASS_NAME
        elif ele_info[0] == 'By.CSS_SELECTOR':
            BY_KEY = By.CSS_SELECTOR

        BY_VALUE = ele_info[1]
        ele_info = (BY_KEY,BY_VALUE)

        try:
            # if 'id' in elename:
            #     ele = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_id(ele_info))
            #
            #
            # elif 'name' in elename:
            #     ele = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_name(ele_info))
            #
            # elif 'class_name' in elename:
            #     ele = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_class_name(ele_info))
            #
            # elif 'xpath' in elename:
            #     ele = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_xpath(ele_info))
            #
            # elif 'accessbility' in elename:
            #     ele = WebDriverWait(self.driver, 10).until(lambda x: x.find_element_by_accessibility_id(ele_info))
            WebDriverWait(self.driver, 10,1).until(EC.presence_of_element_located(ele_info))
            loc = self.driver.find_element(*ele_info)
            print(loc)

            return loc

        except Exception as e:
            print('[ERROR]-查找元素{}失败,具体原因:{}'.format(elename, e))

    def check_ele_is_show(self,pagename,elename):
        '''
        检查元素是否显示
        :param page: 页面名称
        :param elename: 元素名称
        :return:
        '''
        if self.find_element(pagename,elename):
            return True
        else:
            return False

    '''====================================元素操作函数===================================='''
    def click_element(self,pagename,elename):
        try:
            #点击页面元素
            ele = self.find_element(pagename,elename)
            ele.click()

        except Exception as e:
            print('[ERROR]-点击页面元素{}失败,原因:{}'.format(elename,e))

    def click_one_of_elements(self,pagename,elename,index):
        '''
        点击元素集中的某一个元素
        :param pagename:
        :param elename:
        :param index: 元素下标
        :return:
        '''
        try:
            elements = self.find_elements(pagename,elename)
            ele = elements[index]
            ele.click()

        except Exception as e:

            print('[ERROR]-点击页面元素{}失败,原因:{}'.format(elename, e))


    def long_press_element(self,pagename,elename,duration=1000):
        '''
        长按元素
        :param pagename:
        :param elename:
        :return:
        '''
        try:
            ele = self.find_element(pagename,elename)
            TouchAction(self.driver).long_press(ele,duration).perform()


        except Exception as e:

            print('[ERROR]-长按页面元素{}失败,原因:{}'.format(elename, e))

    def clear_element(self,pagename,elename):
        try:
            #元素清空
            ele = self.find_element(pagename,elename)
            ele.clear()

        except Exception as e:
            print('[ERROR]-清空页面元素{}失败,原因:{}'.format(elename,e))


    def sendkeys(self,pagename,elename,content, clear_first=True, click_first=True):
        try:
            #输入元素信息
            ele = self.find_element(pagename,elename)
            if click_first:
                ele.click()
            if clear_first:
                ele.clear()
                ele.send_keys(content)

        except Exception as e:
            print('[ERROR]-输入信息失败,原因:{}'.format(elename,e))

    def is_toast_exist(self, text):
        '''is toast exist, return True or False
        :Agrs:
         - driver - 传driver
         - text   - 页面上看到的文本内容
         - timeout - 最大超时时间,默认30s
         - poll_frequency  - 间隔查询时间,默认0.5s查询一次
        :Usage:
         is_toast_exist(driver, "看到的内容")
        '''
        try:
            toast_loc = (By.XPATH, ".//*[contains(@text,'%s')]" % text)
            WebDriverWait(self.driver, 20, 0.01).until(EC.presence_of_element_located(toast_loc))
            return True
        except Exception as e:
            print(e)
            return False




    def tap_element(self,pagename,elename_x,elename_y,msec):
        '''

        :param pagename:
        :param elename_x: 横坐标
        :param elename_y: 纵坐标
        :param msec:点击频率
        :return:
        '''
        x = self.get_ele_info(pagename,elename_x)
        y = self.get_ele_info(pagename, elename_y)
        self.driver.tap([x, y], msec)

    def get_element_size(self,pagename,elename):
        '''
        获取元素的大小
        :param pagename:
        :param elename:
        :return:
        '''
        element_size = self.find_element(pagename,elename).size
        element_width = element_size.get('width')
        element_height = element_size.get('height')
        return element_width, element_height

    def get_window_size(self):
        size = self.driver.get_window_size()
        width = size['width']
        height = size['height']

        return width,height


    def swipe_screen(self,start_x,start_y,end_x,end_y,msec):
        '''
        滑动屏幕
        :param start_x: 元素左上方的x坐标
        :param start_y: 元素左上方的y坐标
        :param end_x: 元素右下方的x坐标
        :param end_y: 元素右下方的y坐标
        :param msec: 滑动频率,毫秒为单位,一般设置500-1000毫秒比较合适。
        '''
        self.driver.swipe(start_x,start_y,end_x,end_y,duration=msec)

    def swipe_right(self,start_x=0.1,end_x=0.9,duration=2000):
        '''向右滑动'''
        x = self.get_window_size()[0]
        y = self.get_window_size()[1]
        x1 = int(x*start_x)
        x2 = int(x*end_x)
        y1 = int(y * 0.5)
        y2 = int(y * 0.5)
        self.swipe_screen(x1,y1,x2,y2,duration)

    def swipe_left(self,start_x=0.9,end_x=0.1,duration=2000):
        '''向左滑动'''
        x = self.get_window_size()[0]
        y = self.get_window_size()[1]
        x1 = int(x * start_x)
        x2 = int(x * end_x)
        y1 = int(y * 0.5)
        y2 = int(y * 0.5)
        self.swipe_screen(x1, y1, x2, y2, duration)

    def swipe_up(self,start_y=0.9,end_y=0.1,duration=2000):
        '''向上滑动'''
        x = self.get_window_size()[0]
        y = self.get_window_size()[1]
        x1 = int(x * 0.5)
        x2 = int(x * 0.5)
        y1 = int(y * start_y)
        y2 = int(y * end_y)
        self.swipe_screen(x1, y1, x2, y2, duration)

    def swipe_down(self,start_y=0.1,end_y=0.9,duration=2000):
        '''向下滑动'''
        x = self.get_window_size()[0]
        y = self.get_window_size()[1]
        x1 = int(x * 0.5)
        x2 = int(x * 0.5)
        y1 = int(y * start_y)
        y2 = int(y * end_y)
        self.swipe_screen(x1, y1, x2, y2, duration)

    def get_element_location(self,pagename,elename):
        '''
        获取元素位置
        :param pagename:
        :param elename:
        :return:
        '''
        element_pos = self.find_element(pagename,elename).location
        element_x = element_pos.get('x')
        element_y = element_pos.get('y')
        return element_x, element_y

    '''====================================模拟按键函数===================================='''
    def press_HomeButton(self):
        '''按下Home键'''
        self.driver.press_keycode('3')

    def press_BackButton(self):
        '''按下返回键'''
        self.driver.press_keycode('4')

    def press_SearchButton(self):
        '''按下搜索键'''
        self.driver.press_keycode('84')

    def press_EnterButton(self):
        '''按下回车键'''
        self.driver.press_keycode('66')

    def press_DelButton(self):
        '''按下删除键'''
        self.driver.press_keycode('67')


    '''====================================截图操作函数===================================='''
    def _nowtime(self):
        nowtime = time.strftime('%Y%m%d_%H%M%S')
        return nowtime


    def take_screenshot(self,filename):
        '''

        :param filename:文件名
        :return:
        '''
        try:
            nowtime = self._nowtime()
            file_path = os.path.join(screenshot_path,'{}_{}.png'.format(filename,nowtime))
            self.driver.get_screenshot_as_file(file_path)


        except Exception as e:

            print('[ERROR]-截图失败,原因:{}'.format(e))


    '''====================================页面操作函数===================================='''

    def switch_to_webview(self):
        '''切换到webview'''
        for i in range(1):
            print(self.driver.contexts)
            time.sleep(1)
            # WebDriverWait(self.driver,20).until(expected_conditions.visibility_of_element_located((By.ID)))
        webview = self.driver.contexts[-1]
        # print(webview)

        # #切换到webview
        self.driver.switch_to.context(webview)

    def switch_to_native_view(self):
        # 切换到nativeview
        self.driver.switch_to.context(self.driver.contexts[0])

    def get_ele_info(self,pagename,elename):
        '''
        读取元素信息
        :param page: 页面名称
        :param elename: 元素名称
        :return:
        '''
        read_yaml = ReadYamlTool('ElementsData', pagename)
        ele_info = read_yaml.get_yaml_all_items(elename)

        return ele_info

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


if __name__ == '__main__':
    tool = BasePage('launcher')
    # print(tool.find_element('HomePage.yaml', 'ele_btn1_id'))
    # tool.find_elements('HomePage.yaml', 'ele_btn1_id','ele_btn2_id')
    # tool.find_element('HomePage.yaml', 'ele_btn1_id')

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容