对象定位是自动化测试中很关键的一步,也能够说是最关键的一步,毕竟你对象都没定位那么你想操做也不行。因此本章节的知识我但愿你们多动手去操做,不要仅仅只是书本上的知识,毕竟这个我只可以举例说明。下面咱们来看咱们经常使用的一些定位方式html
find_element_by_id()
find_element_by_name() #appium较新版本name定位被去掉
find_element_by_class_name()
find_element_by_xpath()
python
项目使用的工具是uiautomatorviewer,在安卓sdk的tools目录下(C:\Program Files (x86)\Android\androidSDK\tools,查看环境搭建章节)android
不管是在web自动化仍是app自动化中id都是惟一的web
面图片中左边部分用红色圈出来的对象的id咱们在右边的属性中能够看到,他的id我一样是用红色圈出,若是咱们须要对“点击相机,搜你所见”这个输入框进行输入信息,咱们只需操做右边的id就行,下面咱们直接看代码app
#!/usr/bin/env python # -*- codinfg:utf-8 -*- ''' @author: Jeff LEE @file: 启动百度.py @time: 2018-07-25 15:24 @desc: ''' import time from appium import webdriver desired_caps={ 'platformName':'Android', 'deviceName':'D3F021C19001219', #手机设备名称,经过adb devices查看 'platformVersion':'4.4', #android系统的版本号 'unicodeKeyboard':'True', 'resetKeyboard':'True', 'appPackage':'com.baidu.searchbox',#apk包名 'appActivity':'com.baidu.searchbox.SplashActivity', #apk的launcherActivity } driver=webdriver.Remote('http://localhost:4723/wd/hub',desired_caps) time.sleep(5) # 点击“输入框” driver.find_element_by_id("com.baidu.searchbox:id/baidu_searchbox").click() time.sleep(3) # 输入字段 searchInputBox = driver.find_element_by_id('com.baidu.searchbox:id/SearchTextInput') searchInputBox.send_keys("Appium") time.sleep(3) driver.quit()
经过上面的代码咱们可以直接在输入框中输入Appium,以下图所示工具
在实际工做中className定位用得相对而言会比较少。当你常常去看class时你会发现不少的className是同样的,你没有办法对其进行惟必定位,下面咱们看下面两张图片测试
经过className定位的代码ui
driver.find_element_by_class_name('android.widget.TextView')
这种方式去定位,你会发现你永远定位不了‘appium原理’,这是为何呢?由于在设计的时候若是你查找的元素在页面有多个,系统会自动给你选择第一个,因此你永远操做不了后面的,那如何解决这种问题呢?咱们看后面讲解。spa
xpath定位在web自动化中是最多见的,并且也是最有效的,使用xpath定位避免了找不到元素致使报错的问题,可是在app中使用xpath定位是一件很low的事情。为何这么说呢?由于在做者的经历中只要碰见使用xpath定位元素他的反应就会比较慢,自动化的目的是为了提升效率,可是使用xpath后会下降效率,因此这里说很 low。设计
经过xpath定位的代码
driver.find_element_by_xpath('//android.widget.TextView[@text="appium原理"]').click()
运行结果
在xpath里面咱们的语法是这样'//android.widget.TextView[@text="appium原理"]',这个和咱们以前web的xpath同样,意思是查找全部节点中节点为android.widget.TextView (这里使用的是text,也可使用id或class等元素,系统会依次去找)而且他的text属性值为appium原理,这样是否更容易理解呢?下来多练习。这样的定位方式不推荐,效率很慢。
在前面的章节中咱们已经提到了层级定位,只是不知道具体怎么操做而已。在不少的自动化中若是只是靠简单的定位是没有办法完成自动化的,就像刚xpath定位同样,有的元素的id、className都是同样的,xpath定位效率低下,这个时候咱们大多数都会采用层级定位。
从上面的图片咱们能够看出id为android.widget.TabWidget的节点下面包含了不少的android.widget.FrameLayout
从这张图片咱们不难看出,若是咱们要定位这个元素咱们是没办法去定位的,这种状况咱们大多数使用的是层级定位以及xpath,这里咱们来看如何使用层级定位。
首先咱们能够看出两幅图的结构上的区别,第二幅图元素他是在第一幅图里面的,这里咱们称第一幅图id为android:id/tabs的节点为第二幅图元素的父节点,咱们只须要先经过id定位到父节点,而后再从父节点往下面进行定位第二幅图就能够了
elemet =driver.find_element_by_id('android:id/tabs') elemet.find_element_by_class_name('android.widget.FrameLayout').click()
运行会你会发现不报错,可也不会点击,这个是为何呢?由于在父节点下的全部子节点他的className都是“android.widget.FrameLayout”,这种状况下他怎么去点击操做呢?因此在这种状况下会引起一个新的定位问题,就是咱们接下来要讲的List定位
List故名思义就是一个列表,那么他的个数也就成了不肯定性,因此这里须要用复数,因此在咱们定位时咱们不可以接着用find_element_by_id等等定位方式了,咱们须要用他的复数形式find_elements_by_id,全部的定位方式都同样须要采用复数加s。
以上面例子为例,我要点击‘好看视频’,代码以下:
elemet =driver.find_element_by_id('android:id/tabs') elemets=elemet.find_elements_by_class_name('android.widget.FrameLayout') elemets[1].click()
运行结果以下:
在web自动化中咱们会碰见frame的问题,在碰见这些内嵌的标签后咱们须要作的就是切换窗口,那么在app自动化测试也有相似的状况就是咱们常常看见的内嵌html,在咱们原生的app中增长一个由html作成的页面
后续补充,只要在测试以前加这个代码便可
#获取当前页面全部的contexts webview = driver.contexts #在获取到的contexts list里面去挨个循环 for context in webview: #判断循环中单个的context是不是webview,若是是就进行切换,而且跳出循环 if 'WEBVIEW' in context: driver.switch_to.context(context) break
在app自动化中咱们常常会碰见一个问题,咱们须要查找的元素不在当前可展现的屏幕,至于在什么地方咱们不知道,若是这个时候咱们一直使用在当前页面查找,那么系统就会报错,为了解决这个问题咱们就须要使用滑动查找。
首先的思路是咱们在须要查找对象的页面查找一下该元素,判断该元素是否在当前页面,若是该元素不在该页面那么咱们就须要去互动屏幕,到咱们的下一屏幕,而后再进行查找,依次类推到找到为止。
方式咱们有了,那么咱们就须要知道实现这个功能应该有哪些点。下面跟着我一块儿来分析一下:
一、须要查找的元素咱们是否是须要知道是什么呢?这个须要先肯定
二、咱们须要找的页面是在咱们的当前页面的上方仍是下方仍是左方仍是右方,咱们不能肯定,那么咱们是否须要肯定咱们须要滑动的方向?
三、元素和方向有了,可是你知道咱们每次须要滑动屏幕的多少吗?那么咱们是否须要先去获取屏幕的大小,而后针对不一样的方向去计算一个滑动的值呢?
class BaseOperate(object): def __init__(self,driver): self.driver =driver self.get_size() def get_size(self): self.width = self.driver.get_window_size()['width'] self.height = self.driver.get_window_size()['height'] def swipe_left(self,t): self.driver.swipe(self.width*9/10,self.height/2,self.width/10,self.height/2,t) self.screenshot() def swipe_right(self,t): self.driver.swipe(self.width/10,self.height/2,self.width*9/10,self.height/2,t) self.screenshot() def swipe_up(self,t): self.driver.swipe(self.width/2,self.height*9/10,self.width/2,self.height/10,t) self.screenshot() def swipe_down(self,t): self.driver.swipe(self.width/2,self.height/5,self.width/2,self.height*9/10,t) self.screenshot() def findLocal(self): x = 1 while x==1: if self.fact() == 1: self.swipe_up(2000) time.sleep(3) self.fact() else: print ("找到了") x=2 def fact(self): n =1 try: self.driver.find_element_by_id('cn.com.open.mooc:id/tv_replace').click() except Exception,e: return n