Appium(一):appium环境以及基础函数的封装

2024-09-04 16:38

本文主要是介绍Appium(一):appium环境以及基础函数的封装,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 
参考视频教程:  
 **Python主讲移动端自动化测试框架Appium 从基础到项目实战  **

一:搭建appium环境
1、JDK和Android SDK配置
2、安装Node.js
3、安装.net framework
4、安装Appium
5、安装appium - python - client

google教程很多,可以参照网上的教程,这里就不赘述了。最后使用appium-doctor检测环境搭建是否ok。
这篇文章主要介绍下基础函数的封装。

二:让appium跑起来

打开appium-server(我这里版本是V1.10.0),点击:Start Server:


1.png

进到如下这个界面,然后点击页面右上角的放大镜:


3.png

进到appium-server的基础信息设置界面,点击Saved Capability Sets:

2.png

这里面可以配置物理机或者模拟器的设备信息,然后开始一个session,需要配置的信息如下:


capabilities = {"platformName": "Android","deviceName": "0acfd8d5","appActivity": "com.imooc.component.imoocmain.splash.MCSplashActivity","appPackage": "cn.com.open.mooc","noReset": "true"#在当前 session 下不会重置应用的状态。默认值为 false,设置为true后,不需要每次运行用例都安装apk(特别是有开屏页的app,不需要每次都经过开屏页,打开app直接进入主页)}

根据appium版本不同,可能有些参数不是必须的,但是能加上就加上,避免出现问题。其中deviceName可以通过在cmd(windows)窗口下执行adb devices 获取,前提是要先打开设备的调试模式以及windows电脑需要具备adb环境;appActivity和appPackage的获取有很多种方法获取,这里有两种情况:第一种是本地有apk包的情况下,那么直接使用命令aapt dump badging XXX.apk(后面是apk包的绝对路径);第二种情况是没有apk包,但是模拟器或者真机上安装了应用,这时候可以使用adb logcat >c:\log.txt,把app的启动日志输出到本地的log文件,然后去log文件过滤查找,如何过滤查找关键字,这个百度也有,我一般是过滤START或者cmp关键字,后面一般跟的就是apk的Activity和Package名称(不推荐使用这个方法,因为我在多次尝试的过程中遇到华为手机有一个坑爹的问题,就是系统日志默认是关闭的,需要输入一串命令来打开log开关:*#*#2846579#*#*,进入projectmenu–后台设置–LOG设置–LOG开关–打开,最终以失败告终);或者使用adb logcat | grep START命令(windows使用findstr过滤),在cmd窗口输入这个命令后,启动app,然后查看cmd窗口输出的日志


4.png

可以看到输出的日志中,有一个LAUNCHER关键字,后面紧接着flg=0x10200000cmp=cn.com.open.mooc/com.imooc.component.imoocmain.splash.MCSplashActivity中的cn.com.open.mooc就是包名,com.imooc.component.imoocmain.splash.MCSplashActivity就是启动页的Activity(推荐使用这种方法)。
准备工作做完之后,在appium-server的基础信息设置界面选择一个自己已保存的设备,然后点击start session,就可以看到appium-server端有日志输出,这个日志很重要,后续可以作为调试信息来定位问题,同时也能看到手机也就运行起了相应的apk(整个过程都是需要打开调试模式的)

三、页面滑动初级使用

appium的滑动函数是:driver.swipe(x,y,x1,y1,time)。起始点:x,y;终点x1,y1;time是可选参数,左右滑动Y坐标不变,X变化;上下滑动X坐标不变,Y变化。appium中的坐标和数学的坐标不同,appium坐标原点在界面左上角。
滑动函数的封装:
代码和数据分离可以有效减少由于数据变化而维护代码的成本,所以封装一个获取手机屏幕大小和滑动的类,达到的效果是:只需要告诉程序我想要滑动的方向即可,滑动坐标的起始点并不需要关心。
代码实现:


from appium import webdriver
from time import sleep
capabilities = {"platformName": "Android",#"automationName":"Uiautomator2",#获取toast元素需要的"deviceName": "0acfd8d5","appActivity": "com.imooc.component.imoocmain.splash.MCSplashActivity",# "appWaitActivity":"cn.com.open.mooc.index.splash.GuideActivity"#真机启动页等待"appPackage": "cn.com.open.mooc","noReset": "true"#在当前 session 下不会重置应用的状态。默认值为 false,设置为true后,不需要每次运行用例都安装apk}class getSizeAndSwipe():def __init__(self):#构造函数,实例化类的对象时调用self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub", capabilities)self.size = self.driver.get_window_size()#获取屏幕的大小,返回的形式是{'width': 1080, 'height': 1812}self.width = self.size["width"]#获取宽self.height = self.size["height"]#获取高def swipeUp(self):x1 = self.width / 2y1 = self.height / 10 * 9#获取高的十分之九的位置x2 = x1y2 = self.height / 10 * 1#获取十分之一的位置self.driver.swipe(x1,y1,x2,y2)#向上滑动x坐标不变,y坐标变小def swipeDown(self):x1 = self.width / 2y1 = self.height / 10 * 1x2 = x1y2 = self.height / 10 * 9self.driver.swipe(x1, y1, x2, y2)def swipeRight(self):x1 = self.width / 10 * 1y1 = self.height / 2x2 = self.width / 10 * 9y2 = y1self.driver.swipe(x1, y1, x2, y2)def swipeLeft(self):x1 = self.width / 10 * 9y1 = self.height / 2x2 = self.width / 10 * 1y2 = y1self.driver.swipe(x1, y1, x2, y2)def swipeAction(self,direction):#定义一个滑动函数,传入一个方向即可if direction == "up":self.swipeUp()elif direction == "down":self.swipeDown()elif direction == "left":self.swipeLeft()else:self.swipeRight()
if __name__ == "__main__":vivoSwipe = getSizeAndSwipe()vivoSwipe.swipeAction("up")#告知滑动的方向即可
四、元素定位
1、id定位
2、class_name定位
3、层级定位
4、uiautomator定位
5、Xpath定位
6、原生页面和webview页面切换,以及toast元素获取

封装一个登陆页面元素定位的类,每种定位方式封装为一个方法,代码实现:


from appium import webdriver
from time import sleep
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
capabilities = {"platformName": "Android","automationName":"Uiautomator2",#获取toast元素需要的"deviceName": "0acfd8d5","appActivity": "com.imooc.component.imoocmain.splash.MCSplashActivity",# "appWaitActivity":"cn.com.open.mooc.index.splash.GuideActivity"#真机启动页等待"appPackage": "cn.com.open.mooc","noReset": "true"#在当前 session 下不会重置应用的状态。默认值为 false,设置为true后,不需要每次运行用例都安装apk}class handleLoginElement():def __init__(self):self.driver = webdriver.Remote("http://127.0.0.1:4723/wd/hub",capabilities)#初始化driverdef goLoginById(self):#id定位的方式登陆bottoms = self.driver.find_elements_by_id("cn.com.open.mooc:id/lav")#底部的四个按钮(首页,手记,我的学习,账号的id属性是一样的,先找出所有的,然后再通过索引查找需要的元素)count = bottoms[3]#账号元素的索引为3count.click()#做一个点击操作sleep(1)self.driver.find_element_by_id("cn.com.open.mooc:id/rl_login_before").click()self.driver.find_element_by_id("cn.com.open.mooc:id/right_text").click()#若是已有账号,那么直接点击登陆跳转到登陆界面;非首次登陆,不需要这一步,点击登陆会直接跳转到登陆界面self.driver.find_element_by_id("cn.com.open.mooc:id/accountEdit").clear()#先清理一下默认的上次输入过的文本self.driver.find_element_by_id("cn.com.open.mooc:id/accountEdit").send_keys("15555555555")#输入self.driver.find_element_by_id("cn.com.open.mooc:id/passwordEdit").clear()self.driver.find_element_by_id("cn.com.open.mooc:id/passwordEdit").send_keys("XXXX")self.driver.find_element_by_id("cn.com.open.mooc:id/loginLabel").click()#点击登陆sleep(2)def goLoginByClassName(self):#name定位的方式登陆bottoms = self.driver.find_elements_by_class_name("android.widget.ImageView")print(len(bottoms))#可以打印看下找到了几个name属性为android.widget.ImageView的元素count = bottoms[25]count.click()sleep(1)self.driver.find_elements_by_class_name("android.widget.TextView")[0].click()#通过索引来操作元素#第二次登陆,没有上面的这一步self.driver.find_element_by_id("cn.com.open.mooc:id/right_text").click()self.driver.find_elements_by_class_name("android.widget.EditText")[0].clear()self.driver.find_elements_by_class_name("android.widget.EditText")[0].send_keys("15555555555")self.driver.find_elements_by_class_name("android.widget.EditText")[1].clear()self.driver.find_elements_by_class_name("android.widget.EditText")[1].send_keys("XXXX")self.driver.find_elements_by_class_name("android.widget.TextView")[2].click()sleep(2)def goLoginByUiAutomator(self):bottoms = self.driver.find_elements_by_android_uiautomator('new UiSelector().resourceId("cn.com.open.mooc:id/lav")')count = bottoms[3]count.click()sleep(1)self.driver.find_elements_by_android_uiautomator('new UiSelector().className("android.widget.TextView")')[0].click()self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("cn.com.open.mooc:id/right_text")').click()#若是已有账号,那么直接点击登陆跳转到登陆界面;非首次登陆,不需要这一步,点击登陆会直接跳转到登陆界面self.driver.find_elements_by_android_uiautomator('new UiSelector().className("android.widget.EditText")')[0].clear()self.driver.find_elements_by_android_uiautomator('new UiSelector().className("android.widget.EditText")')[0].send_keys("15555555555")self.driver.find_elements_by_android_uiautomator('new UiSelector().className("android.widget.EditText")')[1].clear()self.driver.find_elements_by_android_uiautomator('new UiSelector().className("android.widget.EditText")')[1].send_keys("XXXX")self.driver.find_elements_by_android_uiautomator('new UiSelector().className("android.widget.TextView")')[2].click()sleep(2)def goLoginByXpath(self):# self.driver.find_elements_by_xpath('//*[contains(@text,"账号")]')[1].click()#写法一,找到页面上text属性包含"账号"的元素# self.driver.find_element_by_xpath('//android.widget.TextView[@text="账号"]').click()#写法二,找到页面上classname为android.widget.TextView并且text属性等于"账号"的元素self.driver.find_element_by_xpath('//android.widget.TextView[@text="账号"]/../../preceding-sibling::*[@index="2"]').click()#定位页面上classname为android.widget.TextView并且text等于"账号"的元素;/../../代表向上两个层级,preceding-sibling代表兄弟节点,意思是找到兄弟节点下面index=2的元素def getWebView(self):#原生和H5页面之间的切换webview = self.driver.contextsprint(webview)#打印看下当前的上下文窗口有几个,获取要切换的窗口for view in webview:if view == "XXX":#XXX是要切换过去的窗口self.driver.switch_to.content(view)breakdef getToast(self):sleep(1)bottoms = self.driver.find_elements_by_id("cn.com.open.mooc:id/lav")  # 底部的四个按钮(首页,手记,我的学习,账号的id属性是一样的,先找出所有的,然后再通过索引查找需要的元素)count = bottoms[3]  # 账号元素的索引为3count.click()  # 做一个点击操作sleep(1)self.driver.find_elements_by_class_name("android.widget.TextView")[0].click()  # 通过索引来操作元素self.driver.find_element_by_android_uiautomator('new UiSelector().resourceId("cn.com.open.mooc:id/right_text")').click()self.driver.find_elements_by_class_name("android.widget.EditText")[0].clear()self.driver.find_elements_by_class_name("android.widget.EditText")[0].send_keys("15555555555")self.driver.find_elements_by_class_name("android.widget.TextView")[2].click()self.driver.find_elements_by_class_name("android.widget.EditText")[1].send_keys("123456")self.driver.find_elements_by_android_uiautomator('new UiSelector().className("android.widget.TextView")')[2].click()toast_element = ("xpath", "//*[contains(@text,'登录密码错误')]")#//代表根目录,*是通配符。表示根目录下所有text属性包含"登录密码错误"的元素try:toast = WebDriverWait(self.driver, 10, 0.1).until(EC.presence_of_element_located(toast_element))print(toast.text)except:print("toast未找到")if __name__ == "__main__":handleelement = handleLoginElement()handleelement.getToast()

其中,获取toast元素,需要
1、Appium1.6.3以上(包括1.6.3)
2、Android版本在5.0以上
引入了两个包:


from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

WebDriverWait用于智能等待;expected_conditions用于直到某个条件满足


toast = WebDriverWait(self.driver, 10, 0.1).until(EC.presence_of_element_located(toast_element))

这段代码的含义是:智能等待10s,每隔0.1秒检测一次,直到某个定位元素出现为止。

这篇关于Appium(一):appium环境以及基础函数的封装的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1136461

相关文章

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

安装nodejs环境

本文介绍了如何通过nvm(NodeVersionManager)安装和管理Node.js及npm的不同版本,包括下载安装脚本、检查版本并安装特定版本的方法。 1、安装nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash 2、查看nvm版本 nvm --version 3、安装

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

高并发环境中保持幂等性

在高并发环境中保持幂等性是一项重要的挑战。幂等性指的是无论操作执行多少次,其效果都是相同的。确保操作的幂等性可以避免重复执行带来的副作用。以下是一些保持幂等性的常用方法: 唯一标识符: 请求唯一标识:在每次请求中引入唯一标识符(如 UUID 或者生成的唯一 ID),在处理请求时,系统可以检查这个标识符是否已经处理过,如果是,则忽略重复请求。幂等键(Idempotency Key):客户端在每次

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

pico2 开发环境搭建-基于ubuntu

pico2 开发环境搭建-基于ubuntu 安装编译工具链下载sdk 和example编译example 安装编译工具链 sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib 注意cmake的版本,需要在3.17 以上 下载sdk 和ex

AI基础 L9 Local Search II 局部搜索

Local Beam search 对于当前的所有k个状态,生成它们的所有可能后继状态。 检查生成的后继状态中是否有任何状态是解决方案。 如果所有后继状态都不是解决方案,则从所有后继状态中选择k个最佳状态。 当达到预设的迭代次数或满足某个终止条件时,算法停止。 — Choose k successors randomly, biased towards good ones — Close

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip