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個元素組成
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'屬性的值
---------------------------------------------------------------------------------
關注微信公眾號即可在手機上查閱,並可接收更多測試分享~