{
“platformName”: “android”,
“deviceName”: “Huawei Mate30”,
“appPackage”: “com.xueqiu.android”,
“appActivity”: “.view.WelcomeActivityAlias”,
“noReset”: “True”
}
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解锁,改为开启
https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md
Capability | Description | Values |
---|---|---|
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次以上
开发者选项—>指针位置,设为开启状态。开启后,顶部会有指针移动坐标,可定位屏幕上的元素的坐标。
driver.find_element_by_id(resource-id)
driver.find_element_by_accessibility_id(content-desc)
driver.find_element_by_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
文档:
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()
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.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/name").text("阿里巴巴")')
el3.click()
# 点击阿里巴巴,进入股票页面
# Xpath定位
# el4 = self.driver.find_element_by_xpath("//*[@resource-id='com.xueqiu.android:id/stockName' and @text='阿里巴巴']")
# el4 = self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/stockName").text("阿里巴巴")')
# 通过搜索结果列表框定位其儿子节点中text为“阿里巴巴”的元素
el4 = self.driver.find_element_by_android_uiautomator(
'new UiSelector().resourceId("com.xueqiu.android:id/ll_stock_result_view").childSelector(text("阿里巴巴"))')
el4.click()
# 获取当前股价
# el5 = self.driver.find_element_by_id("com.xueqiu.android:id/stock_current_price")
el5 = self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("com.xueqiu.android:id/stock_current_price")')
print("阿里巴巴当前股价为:%s"% str(el5.text))
# 判断阿里巴巴股价是否大于200
assert float(el5.text) > 200
def test_scroll_to_article(self):
time.sleep(1)
# 滚动匹配包含"财经"的文本,并点击
self.driver.find_element_by_android_uiautomator(
'new UiScrollable(new UiSelector().scrollable(true).'
'instance(0)).scrollIntoView(new UiSelector().textContains("财经").'
'instance(0))').click()
原因:
ui automator识别通过分辨率识别为横屏
Call to ‘10’ failed
[elements("-android uiautomator",“new UiSelector().resourceId(‘com.xueqiu.android:id/tv_search’)”)] Error response status: 9, , UnknownCommand - The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource. Selenium error: Could not parse UiSelector argument: ‘com.xueqiu.android:id/tv_search’ is not a string
原因:
定位表达式中使用了单引号
new UiSelector().resourceId(‘com.xueqiu.android:id/tv_search’)
解决:
定位表达式中使用了双引号
new UiSelector().resourceId(“com.xueqiu.android:id/tv_search”)