# appium简明教程（10）——控件定位基础




狭义上讲，UI级的自动化测试就是让机器代替人去点来点去的过程。

但机器去点什么（点上面还是点左边），怎么点（是长按还是轻触），这些东西是必须由代码的编写者所指示清楚的。

控件定位就是解决机器点什么的问题的。

一般说来，我们可以这样告诉机器：去点登陆按钮。

机器很笨，它并不知道什么是登陆按钮。因为登陆按钮是自然语言的描述。

如果你让一个人去点登陆按钮，那么他其实也是要经过一系列的脑补以后才可以做这件事的。

这个脑补的过程还原如下：

```
这个一定是个按钮

这个按钮一定在被测的应用上

这个按钮大概上面有登陆这个文字信息

嗯，还真有一个，那么点吧。
```

这就是人探索性测试的一个简单过程。一般来说，如果你给出的信息不太充分，人类还是可以通过一系列的探索性思维去理解你的描述的。这个属于心理学的问题，不展开解释。

但是机器并不是人，如果你给出的描述不精确的话，机器是不会自发性的进行探索和脑补的。

因此控件定位就是精确的描述控件特征并告诉机器的过程。

本文版权归乙醇所有，欢迎转载，但请注明作者与出处，严禁用于任何商业用途

控件的特征就是控件的属性，我们可以通过上一讲中的uiautomatorviewer去获取。

在appium的定位世界里，下面这些方法是可以为我们使用的。也就是说，我们通过下面几个约定好的方式，按照webdriver和appium的DSL（自行搜索并理解）进行控件特征的描述和定位。

继承自webdriver的方法，也就是通过这3个特征可以定位控件

* find by "class" (i.e., ui component type，andorid上可以是android.widget.TextView)
* find by "xpath" (i.e., an abstract representation of a path to an element, with certain constraints，由于appium的xpath库不完备的原因，这个不太推荐)
* find by "id"(android上是控件的resource id)

由[Mobile JSON Wire Protocol](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile) 协议中定义的方法，更适合移动设备上的控件定位

* -ios uiautomation: a string corresponding to a recursive element search using the UIAutomation library (iOS-only)
* -android uiautomator: a string corresponding to a recursive element search using the UiAutomator Api (Android-only)
* accessibility id: a string corresponding to a recursive element search using the Id/Name that the native Accessibility options utilize.

在appium 的client对[Mobile JSON Wire Protocol](https://code.google.com/p/selenium/source/browse/spec-draft.md?repo=mobile)中定义的方法进行了封装，使其调用起来更加方便

### ruby篇

```ruby
find_element :accessibility_id, 'Animation'
find_elements :accessibility_id, 'Animation'
find_element :uiautomator, 'new UiSelector().clickable(true)'
find_elements :uiautomator, 'new UiSelector().clickable(true)'
```

当然了，你也可以使用原生的webdriver方法

```ruby
find_element id: 'resource_id'
```

另外，ruby lib里提供了一些非常好用的简便方法来进行控件的定位，好写，好读。

* text(value_or_index) :Find the first TextView that contains value or by index. If int then the TextView at that index is returned.
* button(value_or_index):Find the first button that contains value or by index. If int then the button at that index is returned


更多请看[这里](https://github.com/appium/ruby_lib/blob/master/docs/android_docs.md)

### python篇

```python
el = self.driver.find_element_by_android_uiautomator('new UiSelector().description("Animation")')
self.assertIsNotNone(el)
els = self.driver.find_elements_by_android_uiautomator('new UiSelector().clickable(true)')
self.assertIsInstance(els, list)

el = self.driver.find_element_by_accessibility_id('Animation')
self.assertIsNotNone(el)
els = self.driver.find_elements_by_accessibility_id('Animation')
self.assertIsInstance(els, list)

```

总的来说就是在driver里增加了

* find_element_by_accessibility_id
* find_elements_by_accessibility_id
* find_element_by_android_uiautomator
* find_elements_by_android_uiautomator

等方法

### java篇

前面也讲过了，新增了这些方法

```java
findElementByAccessibilityId()
findElementsByAccessibilityId()
findElementByIosUIAutomation()
findElementsByIosUIAutomation()
findElementByAndroidUIAutomator()
findElementsByAndroidUIAutomator()
```

讨论：从上面可以看出来，python 和 java client对移动端控件定位的封装是比较初级的。ruby lib中封装了很多方便和简洁的方法，因此可以看出，使用ruby lib是优于python和java的选择。当然，如果忽略性能的话。

下一节我们开始具体看下如何用resource id去定位控件。

本文版权归乙醇所有，欢迎转载，但请注明作者与出处，严禁用于任何商业用途




原始封面

![课程图片](https://images.unsplash.com/photo-1509978778156-518eea30166b?w=300)


