appium简单的demo元素定位
Posted IT界的测试混子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了appium简单的demo元素定位相关的知识,希望对你有一定的参考价值。
appium-录制用例
录制步骤
(1)启动appium客户端,默认启动地址 http://127.0.0.1:4723/wd/hub
(2)file>New Session Window
(3)配置设备信息、包名等,点【Start Session】
{
“platformName”: “android”,
“deviceName”: “Huawei Mate30”,
“appPackage”: “com.xueqiu.android”,
“appActivity”: “.view.WelcomeActivityAlias”,
“noReset”: “True”
}
(4)录制脚本
- 点【录制】
- 点【选择元素】
- 选择元素:点左边的输入框
- 点右边的【Tap】即点击输入框操作
- 选择元素:点坐标的输入框
- 点右边的【Send Keys】,输入文本,即向左边的输入框输入搜索关键词
- Recoder选择【Python】语言
- 结束【录制】
- 复制录制脚本
动图
获取包名和activity
windows系统
adb shell dumpsys activity |find “mFocusedActivity” 获取当前activity
C:\\Users\\Administrator>adb shell dumpsys activity |find "mFocusedActivity"
mFocusedActivity: ActivityRecord{10828b7 u0 com.xueqiu.android/.common.MainActivity t11}
adb shell dumpsys window | findstr mCurrentFocus 获取当前activity
C:\\Users\\Administrator>adb shell dumpsys window | findstr mCurrentFocus
mCurrentFocus=Window{26c290 u0 com.xueqiu.android/com.xueqiu.android.common.MainActivity}
代码
# pip install appium-python-client
from appium import webdriver
import time
descrip_cap = {
"platformName": "android",
"deviceName": "Huawei Mate30",
"appPackage": "com.xueqiu.android",
"appActivity": ".view.WelcomeActivityAlias",
"noReset": "True"
}
driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub",descrip_cap)
driver.implicitly_wait(10)
#####################复制录制的脚本#############################
el1 = driver.find_element_by_id("com.xueqiu.android:id/tv_search")
el1.click()
el2 = driver.find_element_by_id("com.xueqiu.android:id/search_input_text")
el2.send_keys("alibaba")
el3 = driver.find_element_by_xpath("/hierarchy/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.RelativeLayout/android.widget.FrameLayout/android.widget.LinearLayout/androidx.recyclerview.widget.RecyclerView/android.widget.RelativeLayout[1]/android.widget.LinearLayout/android.widget.TextView[1]")
el3.click()
el4 = driver.find_element_by_xpath("/hierarchy/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.RelativeLayout/android.widget.LinearLayout/androidx.viewpager.widget.ViewPager/android.widget.RelativeLayout/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.widget.LinearLayout[1]/android.widget.LinearLayout/android.widget.LinearLayout/android.widget.LinearLayout/android.widget.FrameLayout[1]/android.widget.RelativeLayout/android.widget.LinearLayout[1]/android.widget.TextView")
el4.click()
#####################复制录制的脚本#############################
time.sleep(5)
driver.quit()
运行效果:
报错
An unknown server-side error occurred while processing the command. Original error: Error executing adbExec. Original error: 'Command 'D\\:\\\\adt-bundle-windows-x86_64-20140702\\\\sdk\\\\platform-tools\\\\adb.exe -P 5037 -s d270ac3a shell pm clear com.xueqiu.android' exited with code 255'; Stderr: 'Security exception: PID 26038 does not have permission android.permission.CLEAR_APP_USER_DATA to clear data of package com.xueqiu.android java.lang.SecurityException: PID 26038 does not have permission android.permission.CLEAR_APP_USER_DATA to clear data of package com.xueqiu.android at com.android.server.am.ActivityManagerService.clearApplicationUserData(ActivityManagerService.java:7695) at com.android.server.pm.PackageManagerShellCommand.runClear(PackageManagerShellCommand.java:1632) at com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:204) at android.os.ShellCommand.exec(ShellCommand.java:103) at com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:24667) at android.os.Binder.shellCommand(Binder.java:634) at android.os.Binder.onTransact(Binder.java:532) at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:3152) at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:4970) at android.os.Binder.execTransact(Binder.java:731)'; Code: '255'
Security exception: PID 26038 does not have permission android.permission.CLEAR_APP_USER_DATA to clear data of package com.xueqiu.android
原因:
安卓手机未开启OEM解锁
解决:
设置>开发者选项>OEM解锁,改为开启
Capability设置
https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md
Capability | Description | Values |
---|---|---|
automationName | automation引擎 | Appium (default), or UiAutomator2, Espresso, or UiAutomator1 for Android, or XCUITest or Instruments for ios, or YouiEngine for application built with You.i Engine |
app | app地址 | /abs/path/to/my.apk or http://myapp.com/app.ipa |
platformName | 手机使用的操作系统 | iOS, Android, or FirefoxOS |
platformVersion | 操作系统版本 | e.g., 7.1, 4.4 |
deviceName | 设备名称 | iPhone Simulator, iPad Simulator, iPhone Retina 4-inch, Android Emulator, Galaxy S4 |
udid | 设备唯一标识符 | e.g. 1ae203187fc012g |
noReset | 不重置app状态 | true, false |
appActivity【安卓】 | 启动的Android活动(页面)的活动(页面)名 | MainActivity, .Settings |
appPackage【安卓】 | apk包名 | com.example.android.myApp, com.android.settings |
dontStopAppOnReset【安卓】 | 在adb启动应用程序之前,不会停止测试应用程序的进程 | true or false |
skipDeviceInitialization【安卓】 | 跳过设备初始化,包括.安装和运行设置应用程序或设置权限。可用于提高启动性能 | true or false |
unicodeKeyboard【安卓】 | 支持Unicode 输入, 默认为false;切换非英文输入 | true or false |
resetKeyboard【安卓】 | 将键盘重置为其原始状态为false | true or false |
元素定位
手机设置
开启开发者模式
(1)设置>关于手机>连续点击版本号5次以上
(2)设置中,已经出现【开发者选项】
开启指针位置
开发者选项—>指针位置,设为开启状态。开启后,顶部会有指针移动坐标,可定位屏幕上的元素的坐标。
定位工具:
uiautomatorviewer.bat
常用定位方式
driver.find_element_by_id(resource-id)
driver.find_element_by_accessibility_id(content-desc)
driver.find_element_by_xpath("//*")
- id定位取 resource-id的值
- accessibility_id定位取 content-desc的值
- xpath定位建议组合定位
元素常用方法
方法 | 释义 |
---|---|
element.click() | 点击 |
element.send_keys(text) | 输入文本 |
element.se_value(value) | 设置元素的值 |
element.clear() | 清除操作 |
element.is_displayed() | 判断元素是否可见,返回true或false |
element.is_enabled() | 判断元素是否可用,返回true或false |
element.is_selected() | 判断元素是否被选中,返回true或false |
element.get_attribute(name) | 获取属性值 |
element.text | 获取元素文本 |
element.location | 获取元素坐标.e.g.{“y”:19,“x”:20} |
element.size | 获取元素尺寸(高和宽)e.g.{“width”:50,“height”:42} |
代码示例
# pip install appium-python-client
from appium import webdriver
import time
class TestXueQiu:
def setup(self):
descrip_cap = {
"platformName": "android",
"deviceName": "Huawei Mate30",
"appPackage": "com.xueqiu.android",
"appActivity": ".view.WelcomeActivityAlias",
"noReset": "True",
"unicodeKeyboard":"True",
"resetKeyboard":"True",
}
self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", descrip_cap)
self.driver.implicitly_wait(10)
def teardown(self):
time.sleep(3)
self.driver.quit()
def test_xueqiu(self):
# 定位、点击搜索框
el1 = self.driver.find_element_by_id("com.xueqiu.android:id/tv_search")
el1.click()
# 输入搜索关键词
el2 = self.driver.find_element_by_id("com.xueqiu.android:id/search_input_text")
el2.send_keys("阿里巴巴")
#点击搜索到的词条
el3 = self.driver.find_element_by_xpath("//*[@resource-id='com.xueqiu.android:id/name' and @text='阿里巴巴']")
el3.click()
# 点击阿里巴巴,进入股票页面
el4 = self.driver.find_element_by_xpath("//*[@resource-id='com.xueqiu.android:id/stockName' and @text='阿里巴巴']")
el4.click()
# 获取当前股价
el5 = self.driver.find_element_by_id("com.xueqiu.android:id/stock_current_price")
print("阿里巴巴当前股价为:%s"% str(el5.text))
# 判断阿里巴巴股价是否大于200
assert float(el5.text) > 200
TouchActions
文档:
https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/touch-actions.md
常用方法:
方法 | 释义 |
---|---|
press | 按住 |
release | 释放 |
moveTo | 移动至 |
tap | 点击 |
wait | 等待,单位为ms |
longPress | 长按 |
perform | 执行 |
TouchAction
TouchAction().press(el0).moveTo(el1).release()
MultiTouch同时按住多个元素
action0 = TouchAction().tap(el)
action1 = TouchAction().tap(el)
MultiAction().add(action0).add(action1).perform()
滚动
driver.execute_script("mobile: scroll", {"direction": "down"})
代码
# pip install appium-python-client
from appium import webdriver
import time
from appium.webdriver.common.touch_action import TouchAction
class TestTouchAction:
def setup(self):
descrip_cap = {
"platformName": "android",
"deviceName": "Huawei Mate30",
"appPackage": "cn.kmob.screenfingermovelock",
"appActivity": "com.samsung.ui.FlashActivity",
"noReset": "True",
}
self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", descrip_cap)
self.driver.implicitly_wait(10)
def teardown(self):
time.sleep(3)
self.driver.quit()
def test_xueqiu(self):
#点击开启手势密码
el1 = self.driver.find_element_by_accessibility_id("手势密码锁")
el1.click()
# 绘制手势密码
# 以下坐标试用 手机分辨率为540*960
coordinate1 = (90,128)
coordinate2 = (272,128)
coordinate3 = (450,128)
coordinate4 = (272,350)
wait_time = 220 #单位为ms毫秒
TouchAction(self.driver).press(x=coordinate1[0],y=coordinate1[1]).wait(wait_time)\\
.move_to(x=coordinate2[0],y=coordinate2[1]).wait(wait_time)\\
.move_to(x=coordinate3[0],y=coordinate3[1]).wait(wait_time)\\
.move_to(x=coordinate4[0],y=coordinate4[1]).wait(wait_time)\\
.release().perform()
# 点击继续
el2 = self.driver.find_element_by_id("cn.kmob.screenfingermovelock:id/btnTwo")
el2.click()
# 再次绘制绘制手势密码
TouchAction(self.driver).press(x=coordinate1[0], y=coordinate1[1]).wait(wait_time) \\
.move_to(x=coordinate2[0], y=coordinate2[1]).wait(wait_time) \\
.move_to(x=coordinate3[0], y=coordinate3[1]).wait(wait_time) \\
.move_to(x=coordinate4[0], y=coordinate4[1]).wait(wait_time) \\
.release().perform()
# 点击确认
el3 = self.driver.find_element_by_id("cn.kmob.screenfingermovelock:id/btnTwo")
el3.click()
特殊控件toast定位
toast
- 简短消息提示框
- 根据设置的显示时间后自动消失
- 系统级别控件。归属于系统settings。不在app内。
例如下图的“验证码已发送”提示语
定位
通过打印页面元素,可以看到toast元素
<android.widget.Toast index="1" package="com.android.settings" class="android.widget.Toast" text="验证码已发送" checkable="false" checked="false" clickable="false" enabled="false" focusable="false" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[0,0][0,0]" displayed="true" />
但是通过class="android.widget.Toast"无法定位到,因此使用Xpath通过文本定位
driver.find_element_by_xpath('//*[@text="验证码已发送"]')
注意:Capability设置需加上automationName,才可以定位到
“automationName”:“uiautomator2”
代码
# pip install appium-python-client
from appium import webdriver
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions
from appium.webdriver.common.mobileby import MobileBy
class TestXueQiu:
def setup(self):
des_caps = {
"platformName": "android",
"deviceName": "Huawei Mate30",
"appPackage": "com.xueqiu.android",
"appActivity": ".view.WelcomeActivityAlias",
"noReset": "True",
"unicodeKeyboard":"True",
"resetKeyboard":"True",
"automationName":"uiautomator2"
}
self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", des_caps)
self.driver.implicitly_wait(10)
def teardown(self):
time.sleep(3)
self.driver.quit()
def test_toast(self):
# 点击【我的】
self.driver.find_element_by_xpath("//*[@resource-id='com.xueqiu.android:id/tab_name' and @text='我的']").click()
# 点击【手机号】登录
self.driver.find_element_by_id('com.xueqiu.android:id/tv_login_phone').click()
# 输入手机号码
self.driver.find_element_by_id('com.xueqiu.android:id/register_phone_number').send_keys("18000000000")#任意填个手机号码
# 点击【发送验证码】
self.driver.find_element_by_id('com.xueqiu.android:id/register_code_text').click()
# 等待toast元素加载
locator = (MobileBy.XPATH,'//*[@text="验证码已发送"]')
WebDriverWait(self.driver,30).until(expected_conditions.presence_of_element_located(locator))
# # 打印当前页面元素树
print(self.driver.page_source)
# toast元素
# <android.widget.Toast index="1" package="com.android.settings" class="android.widget.Toast" text="验证码已发送" checkable="false" checked="false" clickable="false" enabled="false" focusable="false" focused="false" long-clickable="false" password="false" scrollable="false" selected="false" bounds="[0,0][0,0]" displayed="true" />
# 等待toast元素消失
WebDriverWait(self.driver, 30).until_not(expected_conditions.presence_of_element_located(locator))
# 定位"重新获取"验证码按钮,获取文案
text = self.driver.find_element_by_id('com.xueqiu.android:id/register_code_text').text
assert "重新获取" in text
uiautomator定位
https://developer.android.com/reference/android/support/test/uiautomator/UiSelector.html
uiautomator是安卓的工作引擎,速度快,但表达式书写复杂。
常用表达式
表达式 | |
---|---|
new UiSelector().reaourceId(“id”) | 通过id定位 |
new UiSelector().className(“className”) | 通过className定位 |
new UiSelector().descriptioon(“content-desc”) | 通过content-desc定位 |
new UiSelector().text(“text”) | 通过文本定位 |
new UiSelector().textContains(“包含文本”) | 通过包含文本定位 |
new UiSelector().textStartsWith(“以text开头”) | 匹配以text开头的元素 |
new UiSelector().textMatches(“正则表达式”) | 通过正则表达式匹配文本 |
childSelector() | 父子关系定位 |
fromParent() | 兄弟关系定位 |
组合定位:
driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/name").text("阿里巴巴")')
父子关系定位:
driver.find_element_by_android_uiautomator(
'new UiSelector().resourceId("com.xueqiu.android:id/ll_stock_result_view").childSelector(text("阿里巴巴"))')
滚动页面查找元素
self.driver.find_element_by_android_uiautomator(
'new UiScrollable(new UiSelector().scrollable(true).'
'instance(0)).scrollIntoView(new UiSelector().textContains("财经").'
'instance(0))').click()
代码
# pip install appium-python-client
from appium import webdriver
import time
class TestXueQiu:
def setup(self):
descrip_cap = {
"platformName": "android",
"deviceName": "Huawei Mate30",
"appPackage": "com.xueqiu.android",
"appActivity": ".view.WelcomeActivityAlias",
"noReset": "True",
"unicodeKeyboard":"True",
"resetKeyboard":"True"
}
self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", descrip_cap)
self.driver.implicitly_wait(10)
def teardown(self):
time.sleep(3)
self.driver.quit()
def test_check_alibaba(self):
# 定位、点击搜索框
# el1 = self.driver.find_element_by_id("com.xueqiu.android:id/tv_search")
# resourceId("com.xueqiu.android:id/tv_search")
el1 = self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/tv_search")')
el1.click()
# 输入搜索关键词
# el2 = self.driver.find_element_by_id("com.xueqiu.android:id/search_input_text")
el2 = self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/search_input_text")')
el2.send_keys("阿里巴巴")
#点击搜索到的词条
# Xpath定位
# el3 = self.driver.find_element_by_xpath("//*[@resource-id='com.xueqiu.android:id/name' and @text='阿里巴巴']")
el3 = self关于appium的简单理解
appium+python自动化50-生成定位对象模板templet(jinja2)