环境准备
安装appium
官方文档的安装方式(基本安装不上):
npm install -g appium
淘宝cnpm (最稳定的方法)
npm install -g cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install -g appium
android sdk: https://developer.android.com/studio#downloads
安装完成的几个关键
- adb放在了PATH变量下
- ANDROID_HOME变量为设为sdk的路径
- java在PATH变量下,可以直接执行
真机或者模拟器
- 模拟器使用Android Studio或者sdk中的sdkmanager进行创建
- 真机需要自备
- 网易mumu模拟器 https://mumu.163.com/
avdmanager list
avdmanager create avd -n test -k "system-images;android-27;google_apis_playstore;x86"
emulator -list-avds
appium python client
第11期——Appium Desktop⽤例录制
演练app:雪球官方新版本-安卓iOS版下载-应用宝官网
app信息
获取当前界面元素:adb shell dumpsys activity top
获取任务列表:adb shell dumpsys activity activities
app入口
adb logcat |grep -i displayed
aapt dump badging mobike.apk | grep launchable-activity
apkanalyzer 最新版本的sdk中才有
启动应用
adb shell am start -W -n com.xueqiu.android/.view.WelcomeActivityAlias -S
adb install -r ~/Downloads/com.xueqiu.android_12.3.2_247.apk
雪球app的入口
com.xueqiu.android/.view.WelcomeActivityAlias
第11期——元素定位⽅法与隐式等待 (ID/AID/XPath)
- xpath定位符 XPath Syntax
#绝对定位不推荐:
/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.view.ViewGroup/android.widget.LinearLayout/android.widget.RelativeLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.HorizontalScrollView/android.widget.FrameLayout/android.widget.LinearLayout[1]/android.widget.FrameLayout[3]/android.widget.LinearLayout/android.widget.FrameLayout[1]/android.widget.TextView
#相对定位(推荐):
//*[@text='热门' and contains(@resource-id, 'title')]
第11期——常⽤⾃动化api
第11期——⻓按/滑动等TouchAction的应⽤
第11期——⾼级定位 (XPath/UISelector)
class MobileBy(By):
IOS_PREDICATE = '-ios predicate string'
IOS_UIAUTOMATION = '-ios uiautomation'
IOS_CLASS_CHAIN = '-ios class chain'
ANDROID_UIAUTOMATOR = '-android uiautomator'
ANDROID_VIEWTAG = '-android viewtag'
ANDROID_DATA_MATCHER = '-android datamatcher'
ANDROID_VIEW_MATCHER = '-android viewmatcher'
WINDOWS_UI_AUTOMATION = '-windows uiautomation'
ACCESSIBILITY_ID = 'accessibility id'
IMAGE = '-image'
CUSTOM = '-custom'
第11期——显式等待机制
第11期——Android Toast识别
- 演练app https://github.com/appium/sample-code/raw/master/sample-code/apps/ApiDemos/bin/ApiDemos-debug.apk
def test_toast(self):
scroll_to_element = (
MobileBy.ANDROID_UIAUTOMATOR,
'new UiScrollable('
'new UiSelector().scrollable(true).instance(0))'
'.scrollIntoView('
'new UiSelector().text("Views").instance(0));')
self.driver.find_element(*scroll_to_element).click()
scroll_to_element = (
MobileBy.ANDROID_UIAUTOMATOR,
'new UiScrollable('
'new UiSelector().scrollable(true).instance(0))'
'.scrollIntoView('
'new UiSelector().text("Popup Menu").instance(0));')
self.driver.find_element(*scroll_to_element).click()
# self.driver.find_element(By.XPATH, "//*[@text='MAKE A POPUP!']").click()
self.driver.find_element(MobileBy.ACCESSIBILITY_ID, "Make a Popup!").click()
self.driver.find_element(By.XPATH, "//*[@text='Search']").click()
toast=self.driver.find_element(By.XPATH, "//*[@class='android.widget.Toast']").text
assert "Search" in toast
assert "Clicked" in toast
第11期——UI属性断⾔与hamcrest断⾔
public enum Attribute {
CHECKABLE(new String[]{"checkable"}),
CHECKED(new String[]{"checked"}),
CLASS(new String[]{"class", "className"}),
CLICKABLE(new String[]{"clickable"}),
CONTENT_DESC(new String[]{"content-desc", "contentDescription"}),
ENABLED(new String[]{"enabled"}),
FOCUSABLE(new String[]{"focusable"}),
FOCUSED(new String[]{"focused"}),
LONG_CLICKABLE(new String[]{"long-clickable", "longClickable"}),
PACKAGE(new String[]{"package"}),
PASSWORD(new String[]{"password"}),
RESOURCE_ID(new String[]{"resource-id", "resourceId"}),
SCROLLABLE(new String[]{"scrollable"}),
SELECTION_START(new String[]{"selection-start"}),
SELECTION_END(new String[]{"selection-end"}),
SELECTED(new String[]{"selected"}),
TEXT(new String[]{"text", "name"}),
// The main difference of this attribute from the preceding one is that
// it does not replace null values with empty strings
ORIGINAL_TEXT(new String[]{"original-text"}, false, false),
BOUNDS(new String[]{"bounds"}),
INDEX(new String[]{"index"}, false, true),
DISPLAYED(new String[]{"displayed"}),
CONTENT_SIZE(new String[]{"contentSize"}, true, false);
第11期——参数化与数据驱动应⽤ CSV/Excel/Json/Yaml
作业1
分析appium的log,提取所有的appium调用的命令,对每个命令,分析他的用途。
拔高部分:把每个命令的执行时间也打印下
作业2
搜索股票,点击股票分类,选择香港上市的阿里巴巴股票(根据xpath,而不是顺序),断言股价大于200
作业3
添加某只股票到自选,然后再次搜索并验证,股票已经加入自选。(不要使用文字内容判断,使用get attribute)