Appium 求助 : find_element_by_class_name 无法查找子集中的元素

宁如虎 · 2015年07月31日 · 最后由 五棵木 回复于 2016年09月30日 · 2559 次阅读

环境配置

appium 版本:1.4
appium-python-client: 采用 pip install --upgrade appium-python-client 更新到最新
windows7

程序界面示例

上图所示,listview 中除英文字母外,每一行的 layout id 都是 com.browan.freeppmobile.android:id/Layout_ContactListItem
右边为一 Button 组件

功能要求

为了验证右边到底是 freep 文字 还是空白

验证代码逻辑如下

els = driver.find_elements_by_id('com.browan.freeppmobile.android:id/Layout_ContactListItem')#获取所有可见行数据
try:
    els[0].find_element_by_name('A0_test') # 查找是否存在A0_test的行
    button = els[0].find_element_by_class_name('android.widget.Button') #在所在行寻找button组件
    self.assertFalse(button.is_displayed()) # 是否显示
except:
    self.assertTrue(False)

代码运行情况如下:

  1. 逻辑上应该找不到 button 才对,实际上找到了
  2. appium 中的查找元素,支持在其子集中查找元素? 如目前代码所示,在 A0_test 所在行,查找 button
  3. 还是说 els[0].find_element_by_class_name 与 driver.find_element_by_class_name,实际是一样的效果
共收到 10 条回复 时间 点赞

请问楼主解决该问题了吗?求分享😀

准确的来说 Appium 支持在父控件中查找子控件。

在 selenium 的 webelement 类中你可以查找到对应的内容:

def find_element_by_class_name(self, name):
        """Finds element within this element's children by class name.

        :Args:
            - name - class name to search for.
        """
        return self.find_element(by=By.CLASS_NAME, value=name)

在 Appium python clinet 中的 WebElement 就是继承 Selenum 的 WebElement 扩展了在 UiAutomator 中的 accessibility id 以及直接使用 Uiautomator 的语法规则。

class WebElement(SeleniumWebElement):
    def find_element_by_ios_uiautomation(self, uia_string):
        """Finds an element by uiautomation in iOS.

        :Args:
         - uia_string - The element name in the iOS UIAutomation library

        :Usage:
            driver.find_element_by_ios_uiautomation('.elements()[1].cells()[2]')
        """
        return self.find_element(by=By.IOS_UIAUTOMATION, value=uia_string)

    def find_elements_by_ios_uiautomation(self, uia_string):
        """Finds elements by uiautomation in iOS.

        :Args:
         - uia_string - The element name in the iOS UIAutomation library

        :Usage:
            driver.find_elements_by_ios_uiautomation('.elements()[1].cells()[2]')
        """
        return self.find_elements(by=By.IOS_UIAUTOMATION, value=uia_string)

    def find_element_by_android_uiautomator(self, uia_string):
        """Finds element by uiautomator in Android.

        :Args:
         - uia_string - The element name in the Android UIAutomator library

        :Usage:
            driver.find_element_by_android_uiautomator('.elements()[1].cells()[2]')
        """
        return self.find_element(by=By.ANDROID_UIAUTOMATOR, value=uia_string)

    def find_elements_by_android_uiautomator(self, uia_string):
        """Finds elements by uiautomator in Android.

        :Args:
         - uia_string - The element name in the Android UIAutomator library

        :Usage:
            driver.find_elements_by_android_uiautomator('.elements()[1].cells()[2]')
        """
        return self.find_elements(by=By.ANDROID_UIAUTOMATOR, value=uia_string)

    def find_element_by_accessibility_id(self, id):
        """Finds an element by accessibility id.

        :Args:
         - id - a string corresponding to a recursive element search using the
         Id/Name that the native Accessibility options utilize

        :Usage:
            driver.find_element_by_accessibility_id()
        """
        return self.find_element(by=By.ACCESSIBILITY_ID, value=id)

    def find_elements_by_accessibility_id(self, id):
        """Finds elements by accessibility id.

        :Args:
         - id - a string corresponding to a recursive element search using the
         Id/Name that the native Accessibility options utilize

        :Usage:
            driver.find_elements_by_accessibility_id()
        """
        return self.find_elements(by=By.ACCESSIBILITY_ID, value=id)

    def set_text(self, keys=''):
        """Sends text to the element. Previous text is removed.
        Android only.

        :Args:
         - keys - the text to be sent to the element.

        :Usage:
            element.set_text('some text')
        """
        data = {
            'elementId': self._id,
            'value': [keys]
        }
        self._execute(Command.REPLACE_KEYS, data)
        return self

1、获取文本ele.get_attribute("用uiautomatorviewer看属性名")
2、java-client 可以找子元素,我不知道 Python 可不可以,但打印出 button 数量就知道可不可以了。
3、Xpath 和 UiSelector 都可以做到 “查找指定父元素下的子元素”。

@julian1610
因为是 listview 列表,id 都是一致的,不能进行区分
目前关键是如何匹配,行文本及 button 之间的对应关系;
button 有的有,有的没有,不能进行一一对应,所以单纯遍历也无法做到;目前想到的只能是找子元素这一出路;
其他想法都否定了

换个定位方法吧,比如 ID 或 XPATH

@sanlengjingvv
关键是如何获取 e1 下的文本或者 button

for ele in els:
     ele.find_element_by_??     #是一线性布局,怎么获取它下面的button

问题回到 els[0].find_element_by_class_name 与 driver.find_element_by_class_name 实际效果一样,一样的话,还是无法查找线性布局下的子元素,如何定位此元素下的 button 控件?

对 els 中每个元素 el
{
    打印 el 的文本
    获取 el 下所有的 button 存入 buttons
    打印 buttons 数量
    对 buttons 中每个元素 button
   {
        打印 button 的文本
   }
}

答案是:

3. els[0].find_element_by_class_name与driver.find_element_by_class_name,实际是一样的效果

#1 楼 @skytiger0419 请使用 md 来进行编辑

@lihuazhang@seveniruby@monkey
怎么修改后,还是无法通过

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册