appium 自动化控制(小白干货。。。)

测试环境准备

硬件环境

  1. 手机:真机或模拟器(可以Android Studio工具创建模拟器,也可以用第三方模拟器如网易木木)
  2. 电脑:Android手机可以用Windows/Mac,ios手机只能用Mac

软件环境

  1. java环境 参考连接
  2. node.js 官网下载,直接安装
    查看是否安装成功:npm -v 或 node -v
    用于安装appium server
  3. python环境 官网下载,直接安装,配置环境变量
    用于安装appium客户端
  4. Android Studio工具 官网下载,直接安装
    用于安装Adroid SDK、创建android模拟器
  5. Android SDK ,安装教程
    查看是否安装成功:adb version
    常用的adb命令就在这里面
  6. Appium Inspector 官网下载,直接安装
    用于定位app页面元素
  7. appium server
    安装方式:npm install appium@1.19.1 -g
    查看是否安装成功 : appium -v 有版本号
    启动appium server后,它会监听本地4723端口,只要往这个端口发送请求,它会接收这个请求,并把它解析成手机端执行的指令。
  8. appium 客户端
    安装方式:pip install appium-python-client
    提供编写自动化测试脚本api

测试流程

该流程的执行环境为:win10操作系统+木木模拟器(android6) + python3.10.1 + appium1.19.1 + Appium-Python-Client2.2.0

  1. 启动木木浏览器,安装测试app(.apk文件),安装方式有3:
  • 模拟器右下角 ”更多“ - ”安装“
  • 命令行 adb install [apk路径,可以直接把.apk文件拖拽到这里]
  • 代码自动化安装
# 实现 APP 的安装
driver.install_app('/Users/johndoe/path/to/app.apk') 
# 检测 APP 是否被安装
driver.is_app_installed('com.example.AppName');
  1. 连接模拟器(cmd):
  • 连接木木模拟器:adb connect 127.0.0.1:7555
  • 连接android studio自带模拟器,无需连接。
  • 连接真机,数据线连接手机并且开启usb调试模式。
    验证连接成功(cmd):adb devices
  1. 启动appium server(cmd): appium 回车
  2. pycharm编写测试用例,运行。

编写测试用例流程

1. 定义caps字典,存储app相关信息

 caps = {}
            caps["platformName"] = "Android"
            caps["deviceName"] = "simulator"
            caps["appPackage"] = "com.xueqiu.android"
            caps["appActivity"] = ".view.WelcomeActivityAlias"
            caps["noReset"] = "true"

2. 定义包含caps里面的信息的driver

            self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
            # app启动比较慢,添加隐式等待
            self.driver.implicitly_wait(10)

备注:

a. Remote方法会自动启动应用,进入首页。
b. 由于启动driver比较耗时,当执行多条用例时,不用每条case都重新定义一次driver,可以把定义driver的代码挪到setup_class(), 启动应用采用driver.lauch()方法。driver.lauch()是热启动,会进入到app的首页。
3.编写测试用例步骤(定位,交互,断言)

    def test_input(self):
        el1 = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "OS")
        el1.click()
        el2 = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Morse Code")
        el2.click()

4. 退出app,回收session

        self.driver.quit()

代码优化

进行PO封装,实现功能复用
框架优化(自动关闭弹窗,关键数据比如日志和截图记录,数据驱动等)

appium常用api

设备交互相关api

…待续

driver相关api

定义回收driver

# 定义driver
driver=webdriver.Remote('http://localhost:4723/wd/hub',caps)
# 销毁driver
driver.quit()

wait相关Api

# 隐式等待10秒
self.driver.implicitly_wait(10)

元素定位Api

# ACCESSIBILITY_ID 定位
driver.find_element(AppiumBy.ACCESSIBILITY_ID, "OS")
# ID 定位
driver.find_element(AppiumBy.ID,"com.xueqiu.android:id/search_input_text")
# XPATH 定位
driver.find_element(AppiumBy.XPATH,"//*[@resource-id='com.xueqiu.android:id/code' and @text='BABA']")

应用相关Api

# 安装应用
driver.install_app("/path/xxxx.apk")
# 检查应用是否安装
driver.is_app_installed("package")
# 卸载应用
driver.remove_app("package")
# 启动应用
driver.start_activity("package","activity")
# 启动应用2
driver.launch_app()
# 关闭应用
driver.close_app()
# 重置应用
driver.reset()
# 把当前应用放到app后台
driver.background_app()
# 获得activity
driver.current_activity

文件操作相关api

# 从设备拉出文件:下载
driver.pull_file("path/filename")
# 向设备推送文件:上传
driver.push_file("path")
app页面元素相关api

动作事件

# 点击、清空内容、输入
ele = driver.find_element(AppiumBy.XPATH,"//*[@text='Grid']")
ele.click()
ele.clear()
ele.sendkeys()

属性获取

# 定位元素
ele = driver.find_element(AppiumBy.XPATH,"//*[@text='Grid']")
# 获取文本属性值
ele.text
# 获取指定属性值
ele.get_attribute("clickble")
# 获取位置属性值,返回{"y": 19,"x": 498},左上角的坐标
ele.location
# 获取大小属性值,返回{”width“:200,”height“:50}
ele.size
# 是否可见,返回bool
ele.is_enabled()
# 是否可用,返回bool
ele.is_displayed()
# 是否被选中,返回bool
ele.is_selected()

swip 滑屏事件

"""简单方式 driver.swipe(startX,startY,endX,endY,time)"""
driver.swipe(500,800,500,200,100)

"""适用各种分辨率方式 """
size = driver.get_window_size()
width = size.get("width")
height = size.get("height")
start_x = width / 2
start_y = height * 0.8
end_x = start_x
end_y = height * 0.3
duration = 2000
driver.swipe(start_x, start_y, end_x, end_y, duration)

TouchAction 事件

# 实例化action,传参driver
action = TouchAction(driver)
# 按下,,参数可以是元素也可以是坐标,press()方法一般和release()方法成对使用
ele = driver.find_element(AppiumBy.XPATH,"//*[@text='Grid']")
action.press(el=ele)
# 按下2
action.press(x=100, y=30)
# 释放
action.release()
# 长按,参数可以是元素也可以是坐标
action.long_press(el=ele)
# 点击,参数可以是元素也可以是坐标
action.tap(x=10,y=20)
# 移动,参数可以是元素也可以是坐标
action.move_to(el=ele)
# 暂停1秒
action.wait(1000)

"""实例代码"""
action = TouchAction(self.driver)
width = self.driver.get_window_size().get("width")
height = self.driver.get_window_size().get("height")
start_x = width * 0.5
start_y = height * 0.8
end_x = start_x
end_y = height * 0.2
ele = self.driver.find_element(AppiumBy.XPATH,"//*[@text='Grid']")
action.press(x=start_x, y=start_y).wait(1000).move_to(x=end_x, y=end_y).wait(1000).release().perform()

keyevent键盘事件

"""常用键盘编号
返回键:4
搜索键:84
回车键:66
退格键:67
"""
driver.keyevent(4)
driver.keyevent(66)

toast事件

        toast_text = self.driver.find_element(AppiumBy.XPATH,"//*[@class='android.widget.Toast']").text
        # toast_text = self.driver.find_element(AppiumBy.XPATH,"//*[@text='Clicked popup menu item Search']").text

滑屏事件除了用sweep还可以用scrool(ele1,ele2) 从ele1滑动到ele2