Poco API精講之點擊click()、long_click()、double_click()

上期回顧:Poco API精講之 等待 wait


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

注意:Poco框架和Airtest框架很多API是同名的,但使用方法完全不一樣!!!一定不要搞混了,我初學時也經常搞混,這點一定要注意!
具體Poco框架和Airtest框架是什麼關係,可以看之前文章:Airtest Project——UI自動化利器介紹

今天講一下Poco最基本的操作click()、long_click(),大家不要和Airtest框架的click()也叫touch()弄混了。
Airtest框架的touch()是基於絕對座標或圖片的;Poco的click是基於元素的。
Airtest的touch()詳情可以看之前的文章:Airtest API精講之touch()

Poco的click分兩種,一種是基於全局操作的click、一種是基於UI對象的click,不明白的可以看之前的文章
Poco實例(全局操作) API彙總
Poco UI對象 API彙總

click

1.1 Poco基於全局操作的click

click(pos)
按屏幕相對座標點擊
上面說Airtest框架的click是基於絕對座標,這裏又說了相對座標,不懂的可以看之前的文章:Airtest和Poco座標詳解,這裏不再解釋

參數:
pos - 相對座標,如[0.5,0.5]

異常:
InvalidOperationException: 座標在屏幕以外時報錯

源碼解析:

# 源碼位置:your_python_path\site-packages\poco\pocofw.py
    def click(self, pos):
        if not (0 <= pos[0] <= 1) or not (0 <= pos[1] <= 1):
            raise InvalidOperationException('Click position out of screen. pos={}'.format(repr(pos)))
        ret = self.agent.input.click(pos[0], pos[1])
        self.wait_stable()
        return ret

首先我們知道Poco的click是基於屏幕相對座標,相對座標是把屏幕長寬抽象爲0-1的長度,所以源碼中首先判斷一下X,Y座標是不是小於0或大於1,是的話就表明座標在屏幕以外,是無法點擊到的,所以需要拋出一個超屏的錯誤。如果在屏幕內,則通過代理執行點擊。這裏用到代理的原因是不同Poco類型的操作底層實現是不一樣的,Poco設計上使用了代理類,這樣你無需關心每一種的底層實現,直接通過調用代理即可。

另外根據源碼我們還學會一招,就是判斷元素是否在屏幕內,比如你的腳本要適配各種型號的手機,在大的手機上你要點的元素直接就顯示在屏幕上,在小的手機上你要點的元素需要滑動才能顯示在屏幕上,就可以通過這種辦法來判斷。

示例:

from airtest.core.api import *
from poco.drivers.unity3d import UnityPoco

auto_setup(__file__)

poco = UnityPoco()

# 基於全局操作的click,點擊屏幕左上角
poco.click([0.1,0.1])


# 判斷元素是否在屏幕內,是的話直接點擊,否則滑動後再點擊
button = poco("測試工程師小站")
p = button.get_position()
if 0 < p[0] < 1 and 0 < p[1] < 1:
    poco.click(p)  # 也可以寫成button.click()
else:
    swipe()  # 具體swipe參數需要根據實際情況定
    poco.click(p)  # 也可以寫成button.click()

1.2 Poco基於UI對象的click

click(focus=None, sleep_interval=None)
單擊元素,如果UI對象是一組元素則點擊第1個

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

異常:
PocoNoSuchNodeException:元素不存在

源碼解析:

# 源碼位置:your_python_path\site-packages\poco\proxy.py
    @wait
    def click(self, focus=None, sleep_interval=None):
        focus = focus or self._focus or 'anchor'
        pos_in_percentage = self.get_position(focus)
        self.poco.pre_action('click', self, pos_in_percentage)
        ret = self.poco.click(pos_in_percentage)
        if sleep_interval:
            time.sleep(sleep_interval)
        else:
            self.poco.wait_stable()
        self.poco.post_action('click', self, pos_in_percentage)
        return ret

第1行,獲取元素的錨點,默認爲中心點,不知道錨點的去看座標系介紹。
第2行,根據錨點,算出要點擊的相對座標
第4行,根據相對座標執行點擊,可以看到,基於UI對象的click最終也是調用的基於全局操作的click

另外說下此處click()頭上的@wait裝飾器,就是加了一個wait_for_appearance()的等待:

# 源碼位置:your_python_path\site-packages\poco\proxy.py
def wait(func):
    @wraps(func)
    def wrapped(proxy, *args, **kwargs):
        try:
            return func(proxy, *args, **kwargs)
        except PocoNoSuchNodeException as e:
            try:
                proxy.wait_for_appearance(timeout=proxy.poco._pre_action_wait_for_appearance)
                return func(proxy, *args, **kwargs)
            except PocoTargetTimeout:
                raise e
    return wrapped

wait裝飾器邏輯:首先嚐試直接執行原方法,如果報PocoNoSuchNodeException的錯,則通過wait_for_appearance()等待
對裝飾器不熟的可以看:Python三大器之裝飾器

示例:
點擊默認點在 anchorPoint 上,每個UI都會有一個 anchorPoint ,也就是檢視器(Inspector)中UI包圍盒的那個紅點,大部分情況下 anchorPoint 都在UI包圍盒的正中央。如果想指定其他的點擊位置,可以傳一個參數到 click 方法中,這個參數是一個用list或tuple表示的2維向量,其 [x, y] 值分別表示相對於包圍盒左上角的偏移量,左上角爲 [0, 0] ,右下角爲 [1, 1] ,具體用法請見:Airtest和Poco座標詳解

poco("測試工程師小站").click()  # 點擊元素中心
poco("測試工程師小站").click([0.1,0.1])  # 點擊元素左上角
poco("測試工程師小站").click([0.9,0.9], sleep_interval=3)  # 點擊元素右下角,之後休息3秒

long_click

long_click就是比click多了一個時間參數,其他都一樣

2.1 Poco基於全局操作的long_click

long_click(pos, duration=2.0)
長按

參數:
pos - 相對座標,如[0.5,0.5]
duration - 長按時長,默認2秒

異常:
InvalidOperationException: 座標在屏幕以外時報錯

源碼解析:

# 源碼位置:your_python_path\site-packages\poco\pocofw.py
    def long_click(self, pos, duration=2.0):
        try:
            duration = float(duration)
        except ValueError:
            raise ValueError('Argument `duration` should be <float>. Got {}'.format(repr(duration)))

        if not (0 <= pos[0] <= 1) or not (0 <= pos[1] <= 1):
            raise InvalidOperationException('Click position out of screen. {}'.format(repr(pos)))
        return self.agent.input.longClick(pos[0], pos[1], duration)

和click基本一樣,就是多了一步檢測duration參數合法性

示例:

from airtest.core.api import *
from poco.drivers.unity3d import UnityPoco

auto_setup(__file__)

poco = UnityPoco()

# 長按屏幕左上角10秒
poco.long_click([0.1,0.1], 10)

2.2 Poco基於UI對象的long_click

long_click(duration=2.0)
長按

參數:
duration - 持續時間,默認2秒

源碼解析:

# 源碼位置:your_python_path\site-packages\poco\proxy.py
    @wait
    def long_click(self, duration=2.0):
        try:
            duration = float(duration)
        except ValueError:
            raise ValueError('Argument `duration` should be <float>. Got {}'.format(repr(duration)))

        pos_in_percentage = self.get_position(self._focus or 'anchor')
        self.poco.pre_action('long_click', self, pos_in_percentage)
        ret = self.poco.long_click(pos_in_percentage, duration)
        self.poco.post_action('long_click', self, pos_in_percentage)
        return ret

和click基本一樣,就是多了一步檢測duration參數合法性

示例:

poco("測試工程師小站").long_click(10)  # 長按元素中心10秒

double_click()

不知是忘了還是啥原因,實際官方在Unity Poco中並未實現double_click,所以直接運行會報錯。但我們可以自己封裝一個

from airtest.core.api import *
from poco.drivers.unity3d import UnityPoco

auto_setup(__file__)

poco = UnityPoco()

qasite_double_click(poco_ins):
    # 等待元素出現
    poco_ins.wait_for_appearance()
    # 獲取元素屏幕相對座標
    p = poco_ins.get_position()
    # 轉換爲屏幕絕對座標
    pos = poco.agent.input.get_target_pos(p[0], p[1])
    # 調用Airtest框架的雙擊
    double_click(pos)


button = poco("測試工程師小站")
qasite_double_click(button)

 

 

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章