appium操作介绍
1.获取driver属性
- current_package:获取包名
- current_activity:获取当前活动页面 ==>url
- context:上下文 web窗口切换,H5测试获取上下文 driver.switch_to.context
- contexts:所有的上下文 ==>window_handers
- current_context:获取现在的上下文 获取当前窗口current_window_hander
- page_source:获取源码 XML
- capabilities:获取设置的capabilities
- device_time:设备时间
- location:定位
import time
from appium.webdriver import Remote
# 启动一次请求
caps = {"platformName": "Android",
"udid": "emulator-5554",
"appPackage": "com.lemon.lemonban",
"appActivity": ".activity.WelcomeActivity"
}
driver = Remote(command_executor='http://127.0.0.1:4723/wd/hub',
desired_capabilities=caps)
# 设置隐性等待
driver.implicitly_wait(10)
# 获取app当前活动页面名称
print(driver.current_activity)
# 获取源代码XML
driver.page_source
# 获取定位
print(driver.location)
# 获取设置的capabilities
print(driver.capabilities)
driver.quit()
运行结果:
2.获取元素属性
- text:获取元素的文本
- rect:获取元素的尺寸
import time
from appium.webdriver import Remote
# 启动一次请求
# 1.指明需要连接的服务地址和端口号
# 2.You must include a platformName capability
caps = {"platformName": "Android",
"udid": "emulator-5554",
"appPackage": "com.lemon.lemonban",
"appActivity": ".activity.WelcomeActivity"
}
driver = Remote(command_executor='http://127.0.0.1:4723/wd/hub',
desired_capabilities=caps)
# 设置隐性等待
driver.implicitly_wait(10)
el = driver.find_element('xpath', '(//*[@resource-id="com.lemon.lemonban:id/category_description"])[8]')
# 获取元素的文本
print(el.text)
# 获取元素的尺寸
print(el.rect)
time.sleep(3)
driver.quit()
运行结果:

3.用户操作
- click() 点击
- send_keys() 输入
用法跟selenium中的用法是一样的,但有个注意点:如果想输入中文,必须要设置两个参数
4.触屏操作
- tap:相当于全局的click,适合封装在basepage中
- move_to
- press
- long_press
- release
- wait
- flick
5.滑动操作
- driver.swipe()
在现在的手机中,滑动操作是常见的操作,如果引导页的滑动,刷新,向上一直滑动加载新内容等
如引导页是一个元素,所以只能通过滑动操作来控制元素
driver.swipe(start_x=700, end_x=10, start_y=500, end_y=10)
这种固定的写法不可取,为什么呢?因为我们现在的手机尺寸有大有小,这样就会造成在这个手机上能执行,在那个手机上不能执行,所以我们要想一种不同尺寸的手机都可以执行的写法,因此我们可以使用比例控制
第一步:我们要得到屏幕的尺寸,使用到get_window_size()方法得到width与height的值,看源码可知返回值是个字典,因此可以取出key的value
print(driver.get_window_size())运行结果:{'width': 900, 'height': 1600}
第二步:使用屏幕的比例来进行滑动,如从右往左滑动,从屏幕宽度的90%滑动到10%的位置,高度不变
driver.swipe(start_x=width * 0.9, end_x=width * 0.1, start_y=height * 0.5, end_y=height * 0.5)
具体代码如下:
import time
from appium.webdriver import Remote
# 启动一次请求
caps = {"platformName": "Android",
"udid": "emulator-5554",
"appPackage": "com.xxzb.fenwoo",
"appActivity": ".activity.addition.SplashActivity",
"unicodeKeyboard": True,
"resetKeyboard": True
}
driver = Remote(command_executor='http://127.0.0.1:4723/wd/hub',
desired_capabilities=caps)
# 设置隐性等待
driver.implicitly_wait(10)
# 滑动操作
# 1.获取屏幕的宽度和高度
# 2.从右到左滑动
width = driver.get_window_size()['width']
height = driver.get_window_size()['height']
driver.swipe(start_x=width * 0.9, end_x=width * 0.1, start_y=height * 0.5, end_y=height * 0.5)
driver.swipe(start_x=width * 0.9, end_x=width * 0.1, start_y=height * 0.5, end_y=height * 0.5)
driver.swipe(start_x=width * 0.9, end_x=width * 0.1, start_y=height * 0.5, end_y=height * 0.5)
driver.quit()
这种方法有没有觉得太重复了,因此我们可以进行封装,这样就可以调用了,所以我们可以封装到basepage类中
basepage.py代码如下:
class BasePage:
def __init__(self, driver):
self.driver = driver
def width(self):
"""获取app的宽度"""
return self.driver.get_window_size()['width']
def height(self):
"""获取app的高度"""
return self.driver.get_window_size()['height']
def swipe_left(self):
"""从右往左滑动"""
self.driver.swipe(start_x=self.width() * 0.9, end_x=self.width() * 0.1,
start_y=self.height() * 0.5, end_y=self.height() * 0.5)
def swipe_right(self):
"""从左往右滑动"""
self.driver.swipe(start_x=self.width() * 0.1, end_x=self.width() * 0.9,
start_y=self.height() * 0.5, end_y=self.height() * 0.5)
def swipe_up(self):
"""从下往上滑动"""
self.driver.swipe(start_x=self.width() * 0.5, end_x=self.width() * 0.5,
start_y=self.height() * 0.9, end_y=self.height() * 0.1)
def swipe_down(self):
"""从上往下滑动"""
self.driver.swipe(start_x=self.width() * 0.5, end_x=self.width() * 0.5,
start_y=self.height() * 0.1, end_y=self.height() * 0.9)
调用代码如下:
from basepage import BasePage
from appium.webdriver import Remote
# 启动一次请求
caps = {"platformName": "Android",
"udid": "emulator-5554",
"appPackage": "com.xxzb.fenwoo",
"appActivity": ".activity.addition.SplashActivity",
"unicodeKeyboard": True,
"resetKeyboard": True
}
driver = Remote(command_executor='http://127.0.0.1:4723/wd/hub',
desired_capabilities=caps)
# 设置隐性等待
driver.implicitly_wait(10)
# 滑动操作
# 直接调用BasePage类中的方法即可
BasePage(driver).swipe_left()
BasePage(driver).swipe_left()
BasePage(driver).swipe_left()
driver.quit()
运行结果是一样的,虽然封装的过程麻烦,但之后再调用就会很方便,而且也方便代码维护
6.start_activity进入页面
app的路径依赖是很严重的,如果需要测试某个单独的页面,但是进入这个页面有很长的路径,则会严重影响效率,而且路径过长,会让测试程序不稳定
start_activity可以快速进入指定页面,只需要指定activity的名称即可
获取当前页面的名称:
adb shell -s 设备名称 dumpsys activity | find "mResumedActivity" (如果有多台设备加上-s)

注意:要获取哪个页面名称,一定要打开app的那个页面
代码如下:
driver.start_activity('com.lemon.lemonban', '.activity.LoginActActivity')
在不同的app中都可以使用,直接跳转到设置的页面
7.按键操作
# 按键操作
# 1.选通过功能查对应的事件数字
# 2.通过press_keycode()方法发送
driver.press_keycode(24)
具体的按键对应的事件数字可参考此网站:https://www.jianshu.com/p/f7ec856ff56f
注意:相机键模拟器是无法进行操作的,只能真机操作
上面的代码可读性太差,时间长了肯定就不记得24代表什么了,因此我们进行封装,增强可读性,封装的代码也可以放到basepage.py中
class MobileKey:
ENTER = 66
VOLUME_UP = 24
VOLUME_DOWN = 25
调用MobileKey中的类属性
driver.press_keycode(MobileKey.VOLUME_UP)
还可以把常用的方法进行二次封装,代码如下:
class MobileKey:
ENTER = 66
VOLUME_UP = 24
VOLUME_DOWN = 25
BACK = 4
class BasePage:
def __init__(self, driver):
self.driver = driver
def enter(self):
"""回车"""
self.driver.press_keycode(MobileKey.ENTER)
def volume_up(self):
"""音量加"""
self.driver.press_keycode(MobileKey.VOLUME_UP)
def volume_down(self):
"""音量减"""
self.driver.press_keycode(MobileKey.VOLUME_DOWN)
def back(self):
"""返回"""
self.driver.press_keycode(MobileKey.BACK)
调用BasePage类中的方法即可
BasePage(driver).volume_up()
8.Toast弹框
前提:
登录:Toast是viewer识别不到的,但是我们需要确认文本是否正确
- appium server 1.6.3以上
- 代码中必须制定automationName为UiAutomator2

- UiAutomator2只支持安卓版本5.0+
- jdk1.8 64位以上并配置JAVA_HOME环境变量
因为现在 appium server的版本比较高,默认使用的也是UiAutomator2,所以上面提到的前提不用特意设置
定位表达式:
- xpath定位://*[contains(@text,"手机号码格式不正确")]
- find_element("xpath","//android.widget.Toast")
from appium.webdriver import Remote
# 启动一次请求
caps = {"platformName": "Android",
"udid": "emulator-5554",
"appPackage": "com.lemon.lemonban",
"appActivity": ".activity.WelcomeActivity",
"unicodeKeyboard": True,
"resetKeyboard": True,
"automationName": "UiAutomator2"
}
driver = Remote(command_executor='http://127.0.0.1:4723/wd/hub',
desired_capabilities=caps)
# 设置隐性等待
driver.implicitly_wait(10)
# 查找元素输入账号密码,点击登录按钮
driver.start_activity('com.lemon.lemonban', '.activity.LoginActActivity')
driver.find_element('id', 'com.lemon.lemonban:id/et_mobile').send_keys('123')
driver.find_element('id', 'com.lemon.lemonban:id/et_password').send_keys('123')
driver.find_element('id', 'com.lemon.lemonban:id/btn_login').click()
el = driver.find_element('xpath', '//android.widget.Toast')
# 断言
assert el.text == '手机号码格式不正确'
driver.quit()
注意:以上所有的代码最后一定要加上driver.quit(),否则非正常关闭,下次再跑代码就会报错,这是appium的一个bug
9. 混合应用Hybrid App
原生应用是使用系统原生的组件开发的app,需要特定的语言,比如android的java,kotlin,ios的swift,object c
H5技术可以使用web技术开发app,原生和H5的组合就成了混合应用
混合应用不是在app上直接写HTML页面,而是把H5页面放在一个webview控件当中
webview是原生应用的一种控件,还有其他ImageView等,webview能做到和web页面交互的功能
常用的混合应用技术框架:
- Cordova Apache
- React Native,RN
- lonic
- Flutter,谷歌出的
如何区分是原生页面还是web网页:
方式一:UI上区分:看页面上方有没有进度条与关闭按钮


方式二:利用元素定位区分:原生页面是有很多元素,而且好定位,而web页面整个页面是一个元素,并且class名称是固定的android.webkit.WebView


方式三:下拉页面,背面会出现一个网址(这个不一定有)
方式四:网页定位工具chrome://inspect(这个是判断是不是webview最可靠的工具,但不稳定,速度慢,经常打不开定位元素页面)
chrome://version/查看一些信息

输入chrome://inspect,可以打开DevTools工具,下图是连接上了设备后的显示

当app中打开了一个网页时,刷新DevTools工具,可以查看到关于网页的相关信息,需要注意的是显示的chrome版本是手机端的不是浏览器的版本

点击inspect,就进入了定位元素的页面,其实就是F12的功能

方式五:当方式四不好用的时候,可以下载一个UC-DevTools工具,下载网址:https://dev.ucweb.com/docs/pwa/docs-zh/xy3whu

下载安装好,打开界面如下:

注意:设置中一定要选择本地资源

点击inspect后,进入元素定位页面,可以看到跟网页的那个显示是一样的

10.其他操作
- driver.hide_keyboard() 隐藏键盘
- driver.get_screentshot_as_file() 截屏
- shake 摇一摇
- lock 锁屏
- unlock 解屏
三种等待方法(同selenium用法)
更多推荐




所有评论(0)