import unittest
import cv2
from selenium.common.exceptions import NoSuchElementException, TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from appium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from Android_Topsap_Library.elements_config import *
from Android_Topsap_Library.logger import log
import time
import sys, os
from PIL import Image
# 将默认编码设置为utf-8
# reload(sys)
# sys.setdefaultencoding('utf-8')
'''
页面基类,封装各个界面的通用方法
'''
# 创建pictures文件夹
cur_path = os.path.dirname(os.path.realpath(__file__))
pic_path = os.path.join(cur_path, 'pictures')
# 如果不存在这个logs文件夹,就自动创建一个
if not os.path.exists(pic_path): os.mkdir(pic_path)
class BasePage(unittest.TestCase):
def __init__(self):
pass
exit_button_id = common_page_element.get("exit_app_id")
popwindow_title_id = popwindow_element.get("popwindow_title_id")
def get_android_driver(self, platformVersion="4.2"):
'''
配置Android客户端的driver
:param platformVersion:
:return:返回客户端配置字典
'''
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '5.1.1'
desired_caps['deviceName'] = 'Android Emulator'
# desired_caps['platformVersion'] = '10'
# desired_caps['deviceName'] = 'test nova'
desired_caps['appPackage'] = '包名'
desired_caps['appActivity'] = '起始页activity'
# 'automationName':'Selendroid'
desired_caps['automationName'] = 'Uiautomator2'
desired_caps['noReset'] = "True"
return desired_caps
def open_driver(self):
'''
启动driver,建立appium与模拟器的session
:return:
'''
desired_caps = self.get_android_driver()
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
time.sleep(8)
return self.driver
def close_App(self):
'''
退出客户端
:return:
'''
self.driver.close_app()
def open_App(self):
'''
启动客户端
:return:
'''
self.driver.launch_app()
def close_driver(self):
'''
退出driver
:return:
'''
self.driver.quit()
def find_element(self, *loc):
'''
重写的定位元素方法
:param loc:查找元素的元组如 (By.ID,'com.topsec.topsap:id/ip')
:return:
'''
try:
WebDriverWait(self.driver, 10, 0.5).until(EC.visibility_of_element_located(loc))
return self.driver.find_element(*loc)
except:
self.take_screen_shot("find_element")
log.error("查找不到%s为%s的元素" % loc)
def find_elements(self, *loc):
'''
重写查找多个元素方法(多个元素具有相同属性)
:param loc:查找元素的元组如 (By.ID,'com.topsec.topsap:id/ip')
:return:
'''
try:
WebDriverWait(self.driver, 10, 0.5).until(EC.visibility_of_element_located(loc))
return self.driver.find_elements(*loc)
except:
log.error("查找不到%s为%s的元素列表" % loc)
def is_element_exits(self, *loc):
'''
判断元素是否存在
:param loc: 查找元素的元组如 (By.ID,'com.topsec.topsap:id/ip')
:return: True,元素存在,False元素不存在
'''
flag = None
try:
WebDriverWait(self.driver, 5, 0.5).until(EC.visibility_of_element_located(loc))
flag = True
return flag
except NoSuchElementException:
flag = False
return flag
except TimeoutException:
flag = False
return flag
finally:
print(flag)
return flag
def click_exit_button(self):
'''
点击退出按钮退出APP
:return:
'''
self.click_by_id(self.exit_button_id)
self.click_by_text("确定")
def page_switch(self, page_name):
'''
切换页面
:param page_name: 要切换的页面名称
:return:
'''
page_element = self.find_element(By.XPATH, "//*[@text='%s']" % page_name)
page_element.click()
def install_app(self, apk_name):
'''
安装app
:return:
'''
if self.is_app_installed():
self.uninstall_app()
app_path = os.path.dirname(os.path.realpath(__file__)) + "\\app\\" + apk_name + ".apk"
result_file = os.popen("adb install " + app_path)
result = result_file.read()
if "Success" in result:
log.info("应用安装成功")
elif "Failure" in result:
log.error("应用安装失败")
def uninstall_app(self):
"""
卸载应用
:return:
"""
result_file = os.popen("adb uninstall com.topsec.topsap")
result = result_file.read()
if "Success" in result:
log.info("应用卸载成功")
elif "Failure" in result:
log.error("应用卸载失败")
def is_app_installed(self):
'''
判断应用是否已经安装
:return: True,已经安装,False未安装
'''
result = os.popen("adb shell pm list package")
result = result.read().split("\r\n")
if "package:com.topsec.topsap" in result:
log.info("应用已安装")
return True
else:
log.info("应用未安装")
return False
def take_screen_shot(self, func_name):
'''
对页面进行截图
:param func_name:调用截图的方法的名字
:return:
'''
# timestr = time.strftime("%Y-%m-%d_%H_%M_%S")
self.driver.get_screenshot_as_file(pic_path + '\%s.png' % func_name)
def is_toast_exist(self, message, fuzzy="False"):
'''
判断toast是否存在
:param message: toast的文本
:param fuzzy: 是否模糊匹配,"False"精确匹配,"True"模糊匹配
:return: 返回True表示存在,False不存在
'''
try:
if fuzzy == "False":
element = WebDriverWait(self.driver, 10, 0.01).until(
EC.presence_of_all_elements_located((By.XPATH, '//*[@text=\'{}\']'.format(message))))
elif fuzzy == "True":
element = WebDriverWait(self.driver, 10, 0.01).until(
EC.presence_of_all_elements_located((By.XPATH, '//*[contains(@text,\'{}\')]'.format(message))))
print(element[0].text)
return True
except Exception as e:
log.error(e)
return False
def is_text_exits(self, text, except_value):
'''
判断文本是否存在
:param text:要检测的文本
:param except_value:期望值,如果期望文本存在填写"True",不期望"False"
eg:is_text_exits("登录","False"),期望登录文本不存在
:return:
'''
is_text_exits = self.is_element_exits(By.XPATH, "//*[@text='%s']" % text)
if except_value == "True" and is_text_exits:
return True
elif except_value == "False" and not is_text_exits:
return True
elif except_value == "True" and not is_text_exits:
return False
elif except_value == "False" and is_text_exits:
return False
def press_back(self):
'''
按手机返回按钮返回
:return:
'''
self.driver.press_keycode(keycode=4)
def click_by_text(self, text):
'''
通过文本点击
:param text:要点击的控件的文本,需要当前界面唯一
:return:
'''
self.find_element(By.XPATH, "//*[@text='%s']" % text).click()
def click_by_id(self, element_id):
'''
通过id点击
:param element_id: 要点击的控件的id,需要当前界面唯一
:return:
'''
self.find_element(By.ID, element_id).click()
def input_text_by_id(self, element_id, text):
'''
输入文本
:param element_id: 要输入文本的控件的id,需要当前界面唯一
:param text:要输入的文本
:return:
'''
self.find_element(By.ID, element_id).send_keys(text)
def choiceOptions(self, optionsname):
'''
处理弹窗选项点击事件
:param typename:选项名
:return:
'''
self.click_by_text(optionsname)
# options_list = self.find_elements(By.ID, self.options_list_id)
# for options in options_list:
# if options.text == optionsname:
# options.click()
# break
# else:
# continue
def check_by_text_contains(self, text1, text2):
'''
检测文本1是否在文本2中
:param text1: 要检测的文本
:param text2: 捕获到的文本
:return: True,文本1在文本2中存在,False,不存在
'''
if text1 in text2:
return True
else:
return False
def handle_popwindow(self, click_text):
'''
处理弹窗
:param click_text: 弹窗要点击的文本
:return:
'''
loc = ("xpath", "//*[@text='%s']" % click_text)
try:
e = WebDriverWait(self.driver, 5, 0.5).until(EC.presence_of_element_located(loc))
e.click()
except:
pass
def get_keynumber_location(self, secret_text):
'''
获取字母对应位置
:return:返回template在image中的的bound参数
'''
keynum = pic_path + "\keynum.png" # 键盘图片
image = cv2.imread(keynum)
key = cur_path + "\keyboard\%s.png" % secret_text # 数字键图片
template = cv2.imread(key)
h, w = template.shape[:2] # 字母图片尺寸
result = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED) # 图片对比
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) # 对比结果最大值最小值以及位置
br = (max_loc[0] + w, max_loc[1] + h)
return max_loc, br
def click_position(self, secret_text):
'''
确定点击位置
:param password: 口令密码
:return:返回点击位置position
'''
position = self.get_safekeyborad_letter_position(secret_text)
self.driver.tap(position) # 点击
def open_desk(self):
desired_caps = {}
desired_caps['platformName'] = 'Android'
# desired_caps['platformVersion'] = '5.1.1'
# desired_caps['deviceName'] = 'Android Emulator'
desired_caps['platformVersion'] = '10'
desired_caps['deviceName'] = 'test nova'
desired_caps['appPackage'] = 'com.huawei.android.launcher'
desired_caps['appActivity'] = '.unihome.UniHomeLauncher'
# desired_caps['appPackage'] = 'com.vphone.launcher'
# desired_caps['appActivity'] = '.Launcher'
desired_caps['automationName'] = 'Uiautomator2'
desired_caps['noReset'] = "True"
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
time.sleep(5)
return self.driver
def press_home(self):
'''
按home健将应用置于后台
:return:
'''
self.driver.press_keycode(keycode=3)
def get_safekeyborad_letter_position(self, letter):
'''
确定点击位置
:param password: 口令密码
:return:返回点击位置position
'''
time.sleep(3)
self.cut_safekeyboard_pic()
a, b = self.get_keynumber_location(letter) # template在image中的的bound参数
x = a[0] + b[0]
y = b[1] + a[1]
position = (x / 2, y / 2 + 1536)
return [position]
def click_screen_center(self):
'''
点击屏幕中心点坐标
:return:
'''
width = self.driver.get_window_size()['width']
height = self.driver.get_window_size()['height']
self.driver.tap([(width / 2, height / 2)])
def start_AndFTP(self):
'''
启动AndFtp
:return:
'''
self.driver.start_activity("lysesoft.andftp", "lysesoft.andftp.SettingsActivity")
def start_topsap(self):
'''
启动AndFtp
:return:
'''
self.driver.start_activity("com.topsec.topsap", "com.topsec.topsap.ui.WelcomeActivity")
def cut_safekeyboard_pic(self):
time.sleep(2)
# self.find_elements(By.CLASS_NAME,"android.widget.TableLayout")[0]
self.take_screen_shot("keynum1")
im = Image.open(os.path.join(pic_path + "\\keynum1.png"))
im = im.crop((0, 1536, 1080, 1920))
im.save(pic_path + "/keynum.png")
if __name__ == '__main__':
b = BasePage()
# b.install_app("TopSAP(3.4.2.20.0.4)")
# b.cut_safekeyboard_pic()
driver = b.open_desk()
b.start_topsap()
b.click_by_id("com.topsec.topsap:id/btn_login")
# print(b.is_element_exits(By.ID, "com.topsec.topsap:id/btn_login"))
# b.click_by_id("com.topsec.topsap:id/tv_other_login")
# print(b.is_element_exits(By.XPATH, "//*[@text='%s']" % "口令"))
# b.start_AndFTP()
# b.click_by_text("AndFTP")
# time.sleep(3)
# b.click_by_text("172.18.40.26")
# time.sleep(3)
# b.press_back()
# b.press_back()
# b.press_home()
# b.close_driver()
# driver.press_keycode(keycode=3)
# result_file = os.popen("adb uninstall com.topsec.topsap")
# result = result_file.read()
# print result