安卓python UI自动化 升级之代码进阶篇

安装及简易操作代码都在 这里

1. 等待机制:

查看代码
 import time
from appium import webdriver
# 强制等待: 系统的等待机制
time.sleep(10)    # 系统等待10s后继续执行
driver = webdriver.Remote('http://localhost:4723/wd/hub', {"自己配置dict"})
# 隐式等待: 全局的等待,每过一段事件就会去查看元素是否存在,最多等待10s后,找不到在抛出异常
driver.implicitly_wait(10)        
# 显示等待
from selenium.webdriver.support.wait import WebDriverWait
"""详细格式如下:
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
driver - WebDriver 的驱动程序(Ie, Firefox, Chrome 或远程)
timeout - 最长超时时间,默认以秒为单位
poll_frequency - 休眠时间的间隔(步长)时间,默认为 0.5 秒
ignored_exceptions - 超时后的异常信息,默认情况下抛 NoSuchElementException 异常。
WebDriverWai()一般由 until()或 until_not()方法配合使用,下面是 until()和 until_not()方法的说明。
until(method, message=’’)
调用该方法提供的驱动程序作为一个参数,直到返回值不为 False。
until_not(method, message=’’)
调用该方法提供的驱动程序作为一个参数,直到返回值为 False。
lambda 提供了一个运行时动态创建函数的方法。
"""
# 对 negative ID 等待最多20s
WebDriverWait(driver, 20).until(lambda x: x.find_element(By.ID, "negative"))
driver.find_element(By.ID, "negative").click()

# 下面就是代码的try处理
try:
    WebDriverWait(driver, 20).until(lambda x: x.find_element(By.ID, "negative"))
    driver.find_element(By.ID, "negative").click()
except TimeoutException:
    print("等待negative元素超时")
except NoSuchElementException as e:
    print(e)
    
# 退出apium
driver.quit()

2. xpath详细解释

查看代码
 # 如果元素text是唯一的,可以通过text文本定位
# //*[@text=‘text文本属性’]
driver.find_element(By.XPATH, "//*[@text='扫一扫']").click()
# 如果元素id是唯一的,也可以id属性定位
# //*[@resource-id=’id属性’]
driver.find_element(By.XPATH, "//*[@resource-id='com.taobao.taobao:id/tv_scan_text']").click()
# 也可以联合@resource-id属性和@text文本属性来下定位
driver.find_element(By.XPATH, "//*[@resource-id='com.taobao.taobao:id/tv_scan_text'][@text='扫一扫']").click()
# class属性唯一的话,同样可以通过class属性定位,有两种方法
driver.find_element(By.XPATH, "//android.widget.EditText").click()
driver.find_element(By.XPATH, "//*[@class='android.widget.EditText']").click()
# 通过content-desc属性定位
# //*[@content-desc=’desc的文本’]
driver.find_element(By.XPATH, "//*[@content-desc='帮助']").click()

""" 模糊定位 """
# contains模糊定位,对于一个元素的id或者text不是固定的,但有一部分是固定的,这种就可以模糊匹配。
# //*[contains(@content-desc, ‘帮助’)]
driver.find_element(By.XPATH, '//*[contains(@text, "注册/登录")]').click()
driver.find_element(By.XPATH, "//*[contains(@content-desc, '帮助')]").click()
driver.find_element(By.XPATH, "//*[contains(@class, 'EditText')]").click()
driver.find_element(By.XPATH, "//*[contains(@resource-id, 'id/home_searchedit')]").click()

"""组合定位"""
# id和class属性   定位搜索框
id_class = '//android.widget.EditText[@resource-id="com.taobao.taobao:id/home_searchedit"]'
driver.find_element(By.XPATH, id_class).click()
# text和index属性  定位登录/注册
desc_class = '//*[@text="注册/登录" and @index="1"]'
driver.find_element(By.XPATH, desc_class).click()
# class和text属性  定位输入手机号
class_text = '//android.widget.EditText[@text="请输入手机号码"]'
driver.find_element(By.XPATH, class_text).send_keys("512200893")
# class和desc  定位帮助
id_desc = '//*[contains(@resource-id, "aliuser_menu_item_help") and @content-desc="帮助"]'
driver.find_element(By.XPATH, id_desc).click()

""" 层级定位 """
# 如果一个元素,它除了class属性(class属性肯定会有),其它属性啥都没有,这种情况用上面方法就不适用了,这个时候可以找他父元素,通过父亲定位儿子
fa_sun = '//*[@resoure-id="com.taobao.taobao:id/home_searchbar"]/android.widget.EditText'
t = driver.find_element_by_xpath(fa_sun).click()
# 如果一个父元素下,有多个相同class的儿子时候,可以通过xpath的索引去取对应第几个,xpath是从1开始数的
fu_sun2 = '//*[@resource-id="com.taobao.taobao:id/ll_navigation_tab_layout"]/android.widget.FrameLayout[2]'
driver.find_element_by_xpath(fu_sun2).click()

# 相反的,可以通过儿子定位父亲
# 方法一: ..
sun_fa1 = '//*[@resource-id="com.taobao.taobao:id/tv_scan_text"]/..'
c = driver.find_element_by_xpath(sun_fa1).tag_name
print(c)
# 方法二  parent::*
sun_fa2 = '//*[@resource-id="com.taobao.taobao:id/tv_scan_text"]/parent::*'
d = driver.find_element_by_xpath(sun_fa1).tag_name
print(d)
# 方法三 parent::android.widget.LinearLayout
sun_fa3 = '//*[@resource-id="com.taobao.taobao:id/tv_scan_text"]/parent::android.widget.LinearLayout'
e = driver.find_element_by_xpath(sun_fa1).tag_name
print(e)

# 通过子元素,先找到父元素,再找父元素下的子元素,同样可以进行兄弟元素定位
# 兄弟元素
xiongdi = '//*[@resource-id="com.taobao.taobao:id/bar_search"]/../android.widget.RelativeLayout'
x = driver.find_element_by_xpath(xiongdi).tag_name
print(x)

"""通过层级关系,一层一层的往下找,同样可以通过爷爷元素,定位到孙子元素"""
# 自己研究以下吧,差不多的东西了

 3.  安卓的手机按键,查看全部代码  可以完成键盘输入

查看代码
# 连接Appium服务器
driver = webdriver.Remote('http://localhost:4723/wd/hub', {"自己准备字典"})
# 模拟按下home键
driver.press_keycode(3)
# 按下返回键。
driver.press_keycode(4)
# 按下多任务键。
driver.press_keycode(187)
# 按下电源键。
driver.press_keycode(26)
# 按下音量加键。
driver.press_keycode(24)
# 按下音量减键。
driver.press_keycode(25)
# 截图键
driver.press_keycode(120)
# 设置输入法
driver.press_keycode(63)
# 手机自带浏览器
driver.press_keycode(64)
""" 联合操作 """
# 同时按下音量加键和电源键:
driver.press_keycode(24, 26)
# 同时按下音量减键和电源键
driver.press_keycode(25, 26)

def find_key():
    """ 我按下一个键,去找按下后界面的元素是否存在,存在即 找到了,不存在即没找到,继续下一次按键 """
    for i in range(200):
        # 模拟按下0~200的键
        driver.press_keycode(i)
        print(i)
        # 准备一个定位器
        string = "com.coloros.recents:id/progress_bar"
        try:
            # 查找当前页面3s内是否存在 string 这个定位元素 这里用的是ID定位器
            WebDriverWait(driver, 3).until(lambda x: x.find_element(By.ID, string))
            # 找到这个元素后就退出
            break
        except:
            # 未找到元素,先按下返回键,再按home键,返回桌面,继续找下一个键
            driver.press_keycode(4)
            driver.press_keycode(3)
            time.sleep(1)
            pass

# 执行返回操作
driver.back()
# 退出appium
driver.quit()

3. 多启动

查看代码
dic = {
    'platformName': 'Android',
    'platformVersion': '11',
    'deviceName': 'myAndroid'
}
driver = webdriver.Remote('http://localhost:4723/wd/hub',dic)
# 打开APP1
driver.start_activity('cn.hyh.u3dproject', '.MainActivity')
time.sleep(2)
driver.find_element(MobileBy.ID,'cn.hyh.u3dproject:id/btnLogin').click()
# 打开APP2
driver.start_activity('com.jmar.xahl.ar.project', '.ui.activity.webview.WebViewActivity')

# 关闭当前操作的app,不会关闭驱动对象,只是把应用关闭,不会关闭驱动对象driver,当打印包名时,会有下面的结果
driver.close_app()
# 进入后台,5秒后再回到前台
driver.background_app(5)

 

posted @ 2023-12-08 18:51  奎哥_saint  阅读(22)  评论(0编辑  收藏  举报