1. 程式人生 > 其它 >Poco API精講之元素屬性操作attr、setattr……

Poco API精講之元素屬性操作attr、setattr……

上期回顧:Poco API精講之focus()


以下基於
python3.8;airtestIDE1.2.13;airtest1.2.4;pocoui1.0.85

注意:Poco框架和Airtest框架很多API是同名的,但使用方法完全不一樣!!!
具體Poco框架和Airtest框架是什麼關係,可以看之前文章:Airtest Project——UI自動化利器介紹

之前講了Poco框架的元素定位,今天我們講下元素定位成功後,都可以對元素進行哪些操作。

我們以官方Unity小遊戲Demo為例,如“pearl”這個文字元素,我們通過AirtestIDE選中後,在Log檢視窗就可以看到其詳細屬性資訊了。

 

 

我們挑常用的看下:

type :  Text # 型別為Text
name :  name # 名稱是name
text :  pearl # 文字是pearl
visible :  True # 元素可見
pos :  [0.2421603, 0.6666666] # 元素中心的螢幕相對座標,如果0.2421603*螢幕長度=絕對座標點
size :  [0.1234445, 0.055555556] # 元素在螢幕相對座標的長寬,如果0.1234445*螢幕長度=元素絕對長度
anchorPoint :  [0.5, 0.5] # 錨點位置-中心
clickable :  False # 元素不可點選

1.attr(name)

獲取元素屬性值

引數:
name - 屬性名稱,如name、type、text、visible、pos、clickable等

返回:
屬性值,如果屬性不存在返回None

異常:
PocoNoSuchNodeException:元素不存在

原始碼解析:

# 原始碼位置:your_python_path\site-packages\poco\proxy.py
    def attr(self, name):
    # to optimize performance speed, retrieve only the first matched element.
    # 優化速度,只選擇第一個匹配到的節點
    nodes = self._do_query(multiple=False)
    val = self.poco.agent.hierarchy.getAttr(nodes, name)
    if six.PY2 and isinstance(val, six.text_type):
        # 文字型別的屬性值,只在python2裡encode成utf-8的str,python3保持str型別
        # 這是為了在寫程式碼的時候,無論py2/3始終可以像下面這樣寫
        # node.attr('text') == '節點屬性值'
        val = val.encode('utf-8')
    return val

第1行:獲取元素資訊(即上面例子中的所有屬性值)
第2行:在元素資訊中取得指定屬性的值
之後是為了相容Python2,現在我們都用Python3,可以忽略。

示例:

poco(text='pearl').attr("name")  # 值為name
poco(text='pearl').attr("text")  # 值為pearl

 


2.setattr(name, val)

設定元素的屬性的值。

引數:
name - 屬性名稱,如name、type、text、visible、pos、clickable等
val - 值

異常:
InvalidOperationException:非法操作。當設定失敗時丟擲。

原始碼解析:

# 原始碼位置:your_python_path\site-packages\poco\proxy.py
    def setattr(self, name, val):
        nodes = self._do_query(multiple=False)
        try:
            return self.poco.agent.hierarchy.setAttr(nodes, name, val)
        except UnableToSetAttributeException as e:
            raise InvalidOperationException('"{}" of "{}"'.format(str(e), self))

和attr()一樣,先獲取元素資訊,之後去設定元素屬性的值。
需要注意的是並不是所有屬性都可以修改。比如上例中的pearl元素的text屬性就是一個不可修改的屬性。但如果是Input類元素的text屬性,則是可修改的。
比如這個輸入框,其實一共由3個元素組成

Placeholder,是一個Text型別的元素,是整個輸入框的一個提示文字展示

Text,也是一個Text型別的元素,是整個輸入框的已輸入內容的文字展示
pos_input,才是InputField型別的元素,此型別元素才可設定Text屬性

示例:

# 給輸入框設定值為"測試工程師小站"

# 該元素Text屬性無法修改,操作不生效
poco(text="").setattr("text", "測試工程師小站")
# 該元素Text屬性無法修改,操作不生效
poco("Placeholder").setattr("text", "測試工程師小站")
# 該元素可操作,可操作後,實際是poco(text="")的text值被修改為了'測試工程師小站'
# 所以再用poco(text="")的話就無法定位到了,應該用poco(text="測試工程師小站")
poco("pos_input").setattr('text','測試工程師小站')

如果你覺得很迷惑,實際跑一下,看看結果。


3.get_text()

獲取元素'text'屬性值

返回:
'text'屬性值,沒有時返回None

原始碼解析:

# 原始碼位置:your_python_path\site-packages\poco\proxy.py
    def get_text(self):
        text = self.attr('text')
        return text

可以看到原始碼很簡單,就是通過attr()獲取'text'屬性的值

示例:

poco("Placeholder").get_text()  # 返回"Enter text..."

 

4.set_text(text)

設定元素'text'屬性值

引數:
text - 文字內容

異常:
InvalidOperationException:非法操作。當無法設定時丟擲。

原始碼解析:

# 原始碼位置:your_python_path\site-packages\poco\proxy.py
    def set_text(self, text):
        return self.setattr('text', text)

很簡單,就是通過setattr()設定'text'屬性的值

示例:

# 所以上面設定輸入框內容的操作也可以這樣寫
poco("pos_input").set_text("測試工程師小站")
 

5.get_name()

獲取元素'name'屬性值

返回:
'name'屬性值

原始碼解析:

# 原始碼位置:your_python_path\site-packages\poco\proxy.py
    def get_name(self):
        return self.attr('name')

很簡單,就是通過attr()獲取'name'屬性的值

示例:

# 以例1演示
poco(text='pearl').get_name()  # 返回"name"

 


6.get_size()

獲取元素在螢幕相對座標中的大小

返回:
[width, height] in range of 0 ~ 1

原始碼解析:

# 原始碼位置:your_python_path\site-packages\poco\proxy.py
    def get_size(self):
        return self.attr('size')

很簡單,就是通過attr()獲取'size'屬性的值

示例:

# 以例1演示
poco(text='pearl').get_size()  # 返回[0.1234445, 0.055555556]

 


7.get_position(focus=None)

獲取元素在螢幕上的相對座標

引數:
focus - 元素相對座標,如[0.1,0.1],指元素長、寬各10%的位置,即左上角,取值範圍0~1

返回:
相對座標,如[0.498,0.35555]

異常:
PocoNoSuchNodeException:元素不存在

原始碼解析:

# 原始碼位置:your_python_path\site-packages\poco\proxy.py
    def get_position(self, focus=None):
        focus = focus or self._focus or 'anchor'
        if focus == 'anchor':
            pos = list(map(float, self.attr('pos')))
        elif focus == 'center':
            x, y = map(float, self.attr('pos'))
            w, h = self.get_size()
            ap_x, ap_y = map(float, self.attr("anchorPoint"))
            fx, fy = 0.5, 0.5
            pos = [x + w * (fx - ap_x), y + h * (fy - ap_y)]
        elif type(focus) in (list, tuple):
            x, y = map(float, self.attr('pos'))
            w, h = self.get_size()
            ap_x, ap_y = map(float, self.attr("anchorPoint"))
            fx, fy = focus
            pos = [x + w * (fx - ap_x), y + h * (fy - ap_y)]
        else:
            raise TypeError('Unsupported focus type {}. '
                            'Only "anchor/center" or 2-list/2-tuple available.'.format(type(focus)))
        return pos

通過focus值的不同情況,返回螢幕相對座標。但不管是哪種情況,都是通過attr()獲取'pos'屬性的值,然後再去計算出需要的值。

示例:

# 以例1演示

# 直接返回預設的pos值
poco(text='pearl').get_position()  # 返回[0.2421603, 0.6666666]
# 返回元素中心點在螢幕的相對座標
poco(text='pearl').get_position('center')  # 返回[0.2421603, 0.6666666]
# 返回元素相對座標[0.1,0.1](即元素左上角)在螢幕的相對座標
poco(text='pearl').get_position([0.1,0.1])  # 返回[0.1927825, 0.6444443776]

 

如果你不太清楚座標系的具體概念,可以看:Airtest和Poco座標詳解

 


8.get_bounds()

獲取元素在螢幕相對座標系中的邊界

返回:
[top, right, bottom, left] in range of 0 ~ 1

原始碼解析:

# 原始碼位置:your_python_path\site-packages\poco\proxy.py
    def get_bounds(self):
        size = self.get_size()
        top_left = self.get_position([0, 0])

        # t, r, b, l
        bounds = [top_left[1], top_left[0] + size[0], top_left[1] + size[1], top_left[0]]
        return bounds

第1行:get_size()的原始碼是self.attr('size'),最上面我們講屬性的時候知道size屬性記錄了元素在螢幕相對座標的長寬
第2行:返回元素即左上角(左上頂點)在螢幕的相對座標
第3行:左上頂點有了,長寬有了,就能計算出四條邊在螢幕相對座標的邊界值了

示例:

# 以例1演示

# 注意返回的順序是[top, right, bottom, left] 
poco(text='pearl').get_bounds()  # 返回[0.638888822, 0.30388255, 0.6944443779999999, 0.18043805]

 


9.exists()

判斷元素是否存在。

返回:
True if exists otherwise False

原始碼解析:

# 原始碼位置:your_python_path\site-packages\poco\proxy.py
    def exists(self):
        try:
            return self.attr('visible')
        except (PocoTargetRemovedException, PocoNoSuchNodeException):
            return False

很簡單,就是通過attr()獲取'visible'屬性的值

 

---------------------------------------------------------------------------------

關注微信公眾號即可在手機上查閱,並可接收更多測試分享~