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')