Appiumで開発者向けオプションが有効なスマートフォンを操作する。
スマートフォンを扱うならば複数の指による操作を行いたい。
そういうときに
Multi Touch Performを使うようだが、このクラスは終息するので
W3C Actionsを使う指示がある。
各言語の例はマルチタッチのものだが、Pythonは違う。
Pythonは村八分された…w
まずピンチを実現したい。
ピンチのコードについて
Generating Touch Gestures to Zoom In and Out on Google Mapsを参考にPythonへ移植する。
Seleniumに含まれるモジュールを見てPythonでマルチタッチを行う方法を探り、なんとかピンチを実現する。
import math
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.actions import interaction
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.actions.pointer_input import PointerInput
from selenium.webdriver.common.actions.pointer_actions import PointerActions
from appium import webdriver
from appium.webdriver.common.appiumby import AppiumBy as By
STEPS = 16
WAIT = .001
def zoom(p, r0, r1, angle, duration):
angle = math.pi / 2 - ( 2 * math.pi * angle / 360 )
options = {}
chain = ActionChains(driver)
chain.w3c_actions = ActionBuilder(driver, **options)
zoom1(chain.w3c_actions, p, r0, r1, angle, duration)
zoom1(chain.w3c_actions, p, r0, r1, angle + math.pi, duration)
return chain
def zoom1(ab, p, r0, r1, angle, duration):
p0 = ( p[0] + r0 * math.cos(angle), p[1] - r0 * math.sin(angle) )
p1 = ( p[0] + r1 * math.cos(angle), p[1] - r1 * math.sin(angle) )
pointer_input = ab.add_pointer_input(interaction.POINTER_TOUCH, '{}-{}'.format(interaction.POINTER_TOUCH, len(ab.devices)))
pointer_action = PointerActions(pointer_input, duration=duration)
pointer_action.move_to_location(*p0)
pointer_action.pointer_down()
pointer_action.pause(WAIT)
for i in range(1, STEPS):
pointer_action.move_to_location(p0[0] + ( p1[0] - p0[0] ) * i / STEPS, p0[1] + ( p1[1] - p0[1] ) * i / STEPS)
pointer_action.pause(WAIT)
pointer_action.move_to_location(*p1)
pointer_action.pause(WAIT)
pointer_action.release()
def zoom_in(p, d, d0=100, duration=200):
return zoom(p, d0, d0 + d, 45, duration)
def zoom_out(p, d, d0=100, duration=200):
return zoom(p, d0 + d, d0, 45, duration)
def get_position(element, pos='c'):
pos = pos.lower()
rect = element.rect
(x, y) = (rect['x'], rect['y'])
if 'r' in pos: x += rect['width']
elif not 'l' in pos: x += .5 * rect['width']
if 'b' in pos or 'd' in pos: y += rect['height']
elif not 't' in pos and not 'u' in pos: y += .5 * rect['height']
return (x, y)
caps = {}
caps["platformName"] = "android"
caps["ensureWebviewsHavePages"] = True
driver = webdriver.Remote("http://localhost:5554/wd/hub", caps)
element = driver.find_element(getattr(By, 'ID'), 'jp.co.yahoo.android.weather.type1:id/snackbar_area')
center = get_position(element)
zoom_out(center, 500).perform()
zoom_in(center, 500).perform()
zoom_out(center, 500).perform()
zoom_in(center, 500).perform()
driver.quit()
Yahoo!天気を実機で検証していたが、次の2つが重要だった:
- 遷移中の状態をアクションとして実行する
- それらの間に適切なウエイトを入れる
動きは少しトロくて滑らかでないw
アプリケーションによって挙動が違う…?
2022/09/29 21:39