화면 미끄럼 과 제스처 암 호 를 swipe 방법 으로 모 의 그리 기
App 자동화 테스트 에 서 는 화면 이 미 끄 러 지고 제스처 암 호 를 그 리 는 두 가지 중요 한 동작 이 있 습 니 다.현재 많은 App 이 시작 할 때 시작 할 때 안내 애니메이션 이나 컨 텍스트 내용 을 불 러 올 때 수 동 으로 미 끄 러 지 거나 내 려 가 페이지 를 불 러 와 야 하기 때문에 자동화 테스트 과정 에서 손의 미끄럼 작업 을 모 의 하 는 것 이 중요 하 다.두 번 째 중요 한 것 은 수 동 으로 구 궁 격 을 그 려 서 제스처 비밀 번 호 를 설정 하 는 것 입 니 다.이런 제스처 비밀 번 호 는 제 가 아 는 범위 에서 대부분 금융 류 의 app 에서 가장 흔히 볼 수 있 고 사용자 정보 에 대한 비밀 성 이 좋 은 app 도 있 습 니 다.그래서 제스처 비밀 번 호 를 그 리 는 것 도 app 자동화 테스트 에서 반드시 파악 해 야 할 동작 입 니 다.그러면 다음 에 우 리 는 두 가지 조작 을 어떻게 실현 해 야 하 는 지 설명 하기 시작 했다.본론 에 들 어가 기 전에 핸드폰 에서 가로 좌표 의 원점 은 화면의 왼쪽 상단 정점(0,0)의 위치 에서 시작 되 었 다 는 것 을 알 아야 한다.
슬라이딩 스크린
swipe 방법
미끄럼 화면의 동작 을 모 의 합 니 다.저 희 는 swipe 방법 을 통 해 이 방법의 소스 코드 를 먼저 보 겠 습 니 다.
def swipe(self, start_x, start_y, end_x, end_y, duration=None):
"""Swipe from one point to another point, for an optional duration.
Args:
start_x (int): x-coordinate at which to start
start_y (int): y-coordinate at which to start
end_x (int): x-coordinate at which to stop
end_y (int): y-coordinate at which to stop
duration (:obj:`int`, optional): time to take the swipe, in ms.
Usage:
driver.swipe(100, 100, 100, 400)
Returns:
`WebElement`
"""
# `swipe` is something like press-wait-move_to-release, which the server
# will translate into the correct action
action = TouchAction(self)
action \
.press(x=start_x, y=start_y) \
.wait(ms=duration) \
.move_to(x=end_x, y=end_y) \
.release()
action.perform()
return self
매개 변수start_x, start_y:미 끄 러 지기 시작 할 때의 초기 좌 표를 나타 낸다.즉,어디서부터 미 끄 러 지기 시작 하 는 지 를 나타 낸다.
end_x, end_y:미 끄 러 진 좌 표를 나타 낸다.즉,어디 까지 미 끄 러 지 는 것 이다.
duration: : 미끄럼 과정의 시간 간격 을 표시 합 니 다.아 날로 그 작업 을 할 때 우 리 는 시간 간격 을 설정 하 는 것 이 좋 습 니 다.코드 가 너무 빨리 작 동 하기 때문에 실제 컴퓨터 나 시 뮬 레이 터 의 반응 이 비교적 느 리 고 조작 이 실패 하 며 단 위 는 밀리초 로 계산 하 는 것 을 피 하 는 것 이 좋 습 니 다.
소스 코드 를 통 해 우 리 는 swipe 방법 이 실제 적 으로 Touch Action 을 사용 하여 이 루어 진 것 을 발견 했다.이런 유형 은 뒤에서 우 리 는 여전히 사용 할 것 이다.주로 터치 스크린 동작 을 모 의 하 는 것 이다.
사고의 방향 을 실현 하 다.
평소에 우리 가 화면 을 미 끄 러 뜨 릴 때 어떻게 조작 하 는 지 상상 해 보 세 요.예 를 들 어 왼쪽으로 화면 을 미 끄 러 뜨리 면 우 리 는 화면 오른쪽 에 손 을 놓 고 화면 을 누 르 고 왼쪽으로 미 끄 러 집 니 다.그러면 코드 는 우리 가 화면의 어느 위치 에서 부터 말 을 더 듬 는 지 어떻게 압 니까?바로 좌표 입 니 다.우 리 는 먼저 화면의 너비,높이 를 얻 은 다음 에 그 비례 에 따라 마우스 의 위치 좌 표를 계산 할 수 있 습 니 다.제 가 여기 서 얻 은 시작 좌 표 는 화면 너비 의 0.9 배,높이 의 0.5 배 입 니 다.아마도 우리 가 실제 화면 을 미 끄 러 뜨 릴 때 손가락 의 조작 위치 입 니 다.아래 에 재생 된 애니메이션 에 따라 마우스 가 시작 하 는 대략적인 위치 와 끝 위 치 를 관찰 할 수 있 습 니 다.
다음 에 우 리 는 애니메이션 에서 마우스 의 조작 을 모 의 하기 시작 했다.
우선 getwindow_size()방법 은 화면의 너비 와 높이 를 가 져 온 다음 마우스 의 초기 위치 와 끝 을 계산 합 니 다.
def get_phone_size(self):
""" """
width = self.driver.get_window_size()['width'] #
height = self.driver.get_window_size()['height'] #
return width, height
아 날로 그 애니메이션 을 통 해 알 수 있 듯 이 마 우 스 는 시작 점 좌표(화면 너비 의 3/4,높이 의 1/2)위치 에서 끝 점 좌표(화면 너비 1/4,높이 1/2)까지 미 끄 러 집 니 다.ok.그 다음 에 swipe()방법 으로 미 끄 러 집 니 다.
def swipe_left(self, duration=300):
""" """
width, height = self.get_phone_size
start = width * 0.9, height * 0.5
end = width * 0.1, height * 0.5
return self.driver.swipe(*start, *end, duration)
def swipe_right(self, duration=300):
""" """
width, height = self.get_phone_size
start = width * 0.9, height * 0.5
end = width * 0.1, height * 0.5
return self.driver.swipe(*start, *end, duration)
def swipe_up(self, duration):
""" """
width, height = self.get_phone_size
start = width * 0.9, height * 0.5
end = width * 0.1, height * 0.5
return self.driver.swipe(*start, *end, duration)
def swipe_down(self, duration):
""" """
width, height = self.get_phone_size
start = width * 0.9, height * 0.5
end = width * 0.1, height * 0.5
return self.driver.swipe(*start, *end, duration)
방법 최적화이상 의 모든 방법 은 한 번 호출 하면 한 번 만 미 끄 러 질 수 있 고 서로 다른 미끄럼 방향 은 서로 다른 방법 을 사용 해 야 하기 때문에 사용 할 때 비교적 번거롭다.그래서 우 리 는 코드 를 최적화 시 켜 하나의 함 수 를 호출 하여 서로 다른 횟수,서로 다른 방향의 미끄럼 을 실현 할 수 있다.
for 순환 을 사용 하여 연속 적 인 미끄럼 을 실현 하고 direction 파 라 메 터 를 도입 하 며 사전 과 반사 체 제 를 결합 하여 서로 다른 매개 변수 에 따라 서로 다른 미끄럼 방향 을 실행 하 는 방법 을 실현 하고 num 파 라 메 터 를 전달 하여 미끄럼 횟수 를 제어 합 니 다.구체 적 인 코드 는 다음 과 같 습 니 다.
def skip_welcome_page(self, direction, num=3):
"""
:param direction: str ,left, right, up, down
:param num:
:return:
"""
direction_dic = {
"left": "swipe_left",
"right": "swipe_right",
"up": "swipe_up",
"down": "swipe_down"
}
time.sleep(3)
if hasattr(self, direction_dic[direction]):
for _ in range(num):
getattr(self, direction_dic[direction])() #
else:
raise ValueError(" {} , direction {} ".
format(direction, direction_dic.keys()))
이상 은 모든 미끄럼 스크린 의 조작 입 니 다.구체 적 인 효 과 는 우리 뒤에서 보 겠 습 니 다.(당신 도 먼저 해 보 세 요)제스처 암호
터치 액 션 클래스
아 날로 그 제스처 암 호 를 그립 니 다.TouchAction 류 를 사용 합 니 다.이 종 류 는 짧 은 누 르 기 press()방법,wait()방법,move 를 제공 합 니 다.to()방법,release()방법,perform()방법 등 자주 사용 하 는 방법,다음은 이 몇 가지 방법의 역할 을 간단하게 설명 하 겠 습 니 다.
press(element, x, y) : 그 중에서 element 매개 변 수 는 요소 대상 입 니 다.element 가 비어 있 지 않 을 때 x 와 y 는 None 이 어야 합 니 다.element 가 None 일 때 x 가 None 이 아니라면 y 도 None 이 될 수 없습니다.즉,안 드 로 이 드 운영 체제 에서 element 와(x,y)는 하 나 를 전달 해 야 합 니 다.애플 시스템 은 전달 하지 않 아 도 됩 니 다.여기 서 소개 하지 않 습 니 다.
wait(duration):duration 은 시간 입 니 다.밀리초 단위 입 니 다.이 방법 은 한 동안 기다 리 는 것 입 니 다.sleep 의 역할 과 유사 합 니 다.sleep 는 Touch Ation 대상 에 접근 할 수 없습니다.
release():이 방법의 역할 은 press 등 압력 동작 과 결합 하여 사용 하 는 것 으로 들 어 올 리 는 동작 을 나타 낸다.
perform():이 방법 은 모든 누 르 기 및 기다 림,release 등 동작 을 적용 하 는 역할 을 합 니 다.
사고의 방향 을 실현 하 다.
대부분의 app 의 제스처 설정 암 호 를 모 의 하면 두 가지 상황 을 만 날 수 있 습 니 다.하 나 는 9 궁 격 에 있 는 모든 요 소 는 포 지 셔 닝 표현 식 을 통 해 포 지 셔 닝 할 수 있 고 다른 하 나 는 모든 점 이 포 지 셔 닝 표현 식 을 통 해 포 지 셔 닝 할 수 없 으 며 전체 9 궁 격 요소 만 포 지 셔 닝 할 수 있 습 니 다.모든 점 은 좌 표를 얻 는 방식 으로 만 포 지 셔 닝 할 수 있 습 니 다.그러면 우리 가 오늘 제스처 비밀 번 호 를 그 리 는 상황 을 모 의 하 는 것 이 두 번 째 입 니 다.만약 에 이런 것 을 파악 하면 첫 번 째 는 더욱 간단 합 니 다.다음은 각 점 의 좌 표를 어떻게 얻 는 지 분석 하고 아래 의 그림 을 보 겠 습 니 다.
위의 그림 에서 x 축,y 축 은 핸드폰 의 좌표 표시 방식 입 니 다.수학 중의 2 차원 좌 표를 구별 하 십시오.그 중에서 x 축 방향 은 핸드폰 화면의 너비 width 를 나타 내 고 y 축 방향 은 화면의 높이 height 를 나타 내 며 원점 은(0,0)입 니 다.파란색 사각형 은 9 궁 격 제스처 작업 의 전체 요소(내부 9 개 포인트 포함),startx, start_y 는 9 궁 격 원소 의 시작 좌표 점 을 대표 합 니 다.startx 도 9 궁 격 시작 점 거리 y 축의 거리,starty 도 9 궁 격 시작 점 거리 x 축의 거리 입 니 다.이 몇 가지 값 의 관 계 를 이해 해 주 십시오.다음은 WebElement 대상 의 rect 방법 을 통 해 9 궁 격 요소 의 너비,높이 와 시작 점 좌 표를 얻 을 수 있 습 니 다.
def get_element_size_location(element):
width = element.rect["width"] # 9
height = element.rect["height"] # 9
# 9
start_x = element.rect["x"]
start_y = element.rect["y"]
return width, height, start_x, start_y
rect 방법 을 사용 하 는 것 외 에 location 과 size 방법 으로 요소 의 시작 점 좌표 와 너비,높이 를 각각 얻 을 수 있 습 니 다.두 가지 방법 은 똑 같이 사전 으로 돌아 갈 수 있 습 니 다.
element.location ->{"x": start_x, "y": start_y}
element.size ->{"width": width, "height": height}
다음은 9 궁 격 원소 의 width,height,start 를 통 해x, start_y.각 점 의 좌 표를 계산 하고 우 리 는 위의 그림 에 따라 9 궁 격 요소 의 width 와 height 를 각각 6 등분 으로 나눈다.앞의 3 개 점(1,2,3)의 좌 표 는 각각
width, height, start_x, start_y = self.get_element_size_location(element)
point_1 = {"x": int(start_x + width * (1 / 6) * 1), "y": int(start_y + height * (1 / 6) * 1)}
point_2 = {"x": int(start_x + width * (1 / 6) * 3), "y": int(start_y + height * (1 / 6) * 1)}
point_3 = {"x": int(start_x + width * (1 / 6) * 5), "y": int(start_y + height * (1 / 6) * 1)}
중간 3 개 점(4,5,6)의 좌 표 는 각각
point_4 = {"x": int(start_x + width * (1 / 6) * 1), "y": int(start_y + height * (1 / 6) * 3)}
point_5 = {"x": int(start_x + width * (1 / 6) * 3), "y": int(start_y + height * (1 / 6) * 3)}
point_6 = {"x": int(start_x + width * (1 / 6) * 5), "y": int(start_y + height * (1 / 6) * 3)}
마지막 3 개 점(7,8,9)의 좌 표 는 각각
point_7 = {"x": int(start_x + width * (1 / 6) * 1), "y": int(start_y + height * (1 / 6) * 5)}
point_8 = {"x": int(start_x + width * (1 / 6) * 3), "y": int(start_y + height * (1 / 6) * 5)}
point_9 = {"x": int(start_x + width * (1 / 6) * 5), "y": int(start_y + height * (1 / 6) * 5)}
다음은 TouchAction 클래스 의 move 를 사용 하 겠 습 니 다.to,wait,release,perform 방법 은 한 점 에서 다른 점 으로 이동 하여 제스처 암 호 를 모 의 하 는 연결 작업(링크 1-2-3-6-9)을 실현 합 니 다.
TouchAction(driver).press(x=point_1["x"], y=point_1["y"]).wait(300)\
.move_to(x=point_2["x"], y=point_2["y"]).wait(500)\
.move_to(x=point_3["x"], y=point_3["y"]).wait(500)\
.move_to(x=point_6["x"], y=point_6["y"]).wait(500)\
.move_to(x=point_9["x"], y=point_9["y"]).wait(500).release().perform()
전체 코드슬라이더 코드 가 포함 되 지 않 음
base.py
"""
------------------------------------
@Time : 2019/8/6 20:22
@Auth : linux
@File : base.py
@IDE : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ : [email protected]
@GROUP: 878565760
------------------------------------
"""
from appium.webdriver import WebElement
from appium.webdriver.common.touch_action import TouchAction
from appium.webdriver.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import NoSuchElementException, TimeoutException
class Base(object):
def __init__(self, driver: WebDriver):
self.driver = driver
@staticmethod
def get_element_size_location(element):
width = element.rect["width"]
height = element.rect["height"]
start_x = element.rect["x"]
start_y = element.rect["y"]
return width, height, start_x, start_y
def gesture_password(self, element: WebElement):
width, height, start_x, start_y = self.get_element_size_location(element)
point_1 = {"x": int(start_x + width * (1 / 6) * 1), "y": int(start_y + height * (1 / 6) * 1)}
point_2 = {"x": int(start_x + width * (1 / 6) * 3), "y": int(start_y + height * (1 / 6) * 1)}
point_3 = {"x": int(start_x + width * (1 / 6) * 5), "y": int(start_y + height * (1 / 6) * 1)}
point_4 = {"x": int(start_x + width * (1 / 6) * 1), "y": int(start_y + height * (1 / 6) * 3)}
point_5 = {"x": int(start_x + width * (1 / 6) * 3), "y": int(start_y + height * (1 / 6) * 3)}
point_6 = {"x": int(start_x + width * (1 / 6) * 5), "y": int(start_y + height * (1 / 6) * 3)}
point_7 = {"x": int(start_x + width * (1 / 6) * 1), "y": int(start_y + height * (1 / 6) * 5)}
point_8 = {"x": int(start_x + width * (1 / 6) * 3), "y": int(start_y + height * (1 / 6) * 5)}
point_9 = {"x": int(start_x + width * (1 / 6) * 5), "y": int(start_y + height * (1 / 6) * 5)}
TouchAction(self.driver).press(x=point_1["x"], y=point_1["y"]).wait(300) \
.move_to(x=point_2["x"], y=point_2["y"]).wait(500) \
.move_to(x=point_3["x"], y=point_3["y"]).wait(500) \
.move_to(x=point_6["x"], y=point_6["y"]).wait(500) \
.move_to(x=point_9["x"], y=point_9["y"]).wait(500).release().perform()
def find_element(self, locator: tuple, timeout=30) -> WebElement:
wait = WebDriverWait(self.driver, timeout)
try:
element = wait.until(lambda driver: driver.find_element(*locator))
return element
except (NoSuchElementException, TimeoutException):
print('no found element {} by {}', format(locator[1], locator[0]))
if __name__ == '__main__':
pass
테스트 코드
test_gesture_password.py
import time
import unittest
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy
from base import Base
class TestGesture(unittest.TestCase):
def setUp(self):
desired = {
"automationName": "uiautomator1",
"platformName": "Android",
"platformVersion": '5.1.1',
"deviceName": "127.0.0.1:62001",
"appPackage": "com.xxzb.fenwoo",
"appActivity": "com.xxzb.fenwoo.activity.addition.WelcomeActivity",
"app": r"D:\AppAutoTest\appPackage\Future-release-2018.apk",
"unicodeKeyboard": True, #
"resetKeyboard": True
}
self.driver = webdriver.Remote(command_executor="http://127.0.0.1:4723/wd/hub",
desired_capabilities=desired)
self.base = Base(self.driver)
def test_gesture_password(self):
#
self.driver.start_activity(app_package="com.xxzb.fenwoo",
app_activity=".activity.user.CreateGesturePwdActivity")
commit_btn = (MobileBy.ID, 'com.xxzb.fenwoo:id/right_btn')
password_gesture = (MobileBy.ID, 'com.xxzb.fenwoo:id/gesturepwd_create_lockview')
element_commit = self.base.find_element(commit_btn)
element_commit.click()
# 9
password_element = self.base.find_element(password_gesture)
self.base.gesture_password(password_element)
time.sleep(5) #
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main()
이상 은 완전한 제스처 암호 조작 을 모 의 하 는 코드 입 니 다.그러나 문제 가 생 겼 습 니 다.제 가 여기 서 실 행 했 을 때 성공 하지 못 해서 어색 합 니 다.그러나 저 는 다른 사람 이 이런 점 의 좌 표를 얻 고 한 점 의 좌표 에서 다른 점 의 좌표 로 이동 하 는 방식 으로 선 을 그 리 는 것 을 본 적 이 있 습 니 다.물론 성공 할 수 있 는 지 없 는 지 먼저 시험 해 보고 내 려 다 볼 수 있 습 니 다!방법 재 작성
위의 방식 도 성공 하지 못 한다 면 아래 의 방법 을 시도 해 보 세 요.원 리 는 같 습 니 다.주로 다른 점 은 move 입 니 다.to 방법 은 각 점 의 좌표 가 아니 라 상대 점 의 좌표,즉 한 점 에서 다른 점 으로 이동 하 는 거리 좌표 이다.예 를 들 어 점 1 의 좌 표 는(360,579)이 고 점 2 의 좌 표 는(580,579)이다.그러면 이동 하 는 거 리 는 가로 220,세로 0 이 어야 한다.전달 하 는 매개 변 수 는 이런 move 이 어야 한다.to(x=220,y=0)(여기 서 전달 하 는 매개 변 수 는 상대 위치 좌표 라 고 하지만 moveto 의 소스 코드 는 바로 제 가 예전 에 쓴 방법 에 따라 전달 한 것 입 니 다.구체 적 으로 왜 그런 지 저도 잘 모 르 겠 습 니 다)일부 코드 를 수정 하면 다음 과 같 습 니 다.
TouchAction(self.driver).press(x=point_1["x"], y=point_1["y"]).wait(300) \
.move_to(x=point_2["x"]-point_1["x"], y=point_2["y"]-point_1["y"]).wait(500) \
.move_to(x=point_3["x"]-point_2["x"], y=point_3["y"]-point_2["y"]).wait(500) \
.move_to(x=point_6["x"]-point_3["x"], y=point_6["y"]-point_3["y"]).wait(500) \
.move_to(x=point_9["x"]-point_6["x"], y=point_9["y"]-point_6["y"]).wait(500).release().perform()
상대 좌표 의 계산 방법:다음 목표 점 좌 표를 사용 하여 앞의 점 의 좌 표를 빼 면 상대 좌표 입 니 다.이 코드 를 교체 하면 확실히 성공 한 것 을 발견 할 수 있 습 니 다.코드 최적화
상기 코드 는 매번 같은 비밀번호 만 그 릴 수 있다 는 것 을 알 게 될 것 입 니 다.만약 에 제 가 다른 비밀 번 호 를 그 리 려 면 그 릴 때 전달 하 는 좌 표를 수정 해 야 합 니 다.우수한 프로그래머 로 서 어떻게 이렇게 어 눌 할 수 있 습 니까?이 말 에 대해 나 는 모든 암호 조합 을 그 릴 수 있 는 방법 을 생각해 야 한다.내 가 함수 getsture 를 그 려 줄 때password()다른 암 호 를 전달 할 때(예 를 들 어 이러한 방식 getsturepassword(1,2,3,6,9)그러면 프로그램 이 저 를 도와 1-2-3-6-9 를 연결 해 야 합 니 다.그래서 저 는 사전 을 사용 하여 모든 숫자 를 각각 좌표 점 에 대응 하 는 것 을 생각 했 습 니 다.아래 와 같이.
def get_password_location(self, element: WebElement) -> dict:
width, height, start_x, start_y = self.get_element_size_location(element)
point_1 = {"x": int(start_x + width * (1 / 6) * 1), "y": int(start_y + height * (1 / 6) * 1)}
point_2 = {"x": int(start_x + width * (1 / 6) * 3), "y": int(start_y + height * (1 / 6) * 1)}
point_3 = {"x": int(start_x + width * (1 / 6) * 5), "y": int(start_y + height * (1 / 6) * 1)}
point_4 = {"x": int(start_x + width * (1 / 6) * 1), "y": int(start_y + height * (1 / 6) * 3)}
point_5 = {"x": int(start_x + width * (1 / 6) * 3), "y": int(start_y + height * (1 / 6) * 3)}
point_6 = {"x": int(start_x + width * (1 / 6) * 5), "y": int(start_y + height * (1 / 6) * 3)}
point_7 = {"x": int(start_x + width * (1 / 6) * 1), "y": int(start_y + height * (1 / 6) * 5)}
point_8 = {"x": int(start_x + width * (1 / 6) * 3), "y": int(start_y + height * (1 / 6) * 5)}
point_9 = {"x": int(start_x + width * (1 / 6) * 5), "y": int(start_y + height * (1 / 6) * 5)}
keys = {
1: point_1,
2: point_2,
3: point_3,
4: point_4,
5: point_5,
6: point_6,
7: point_7,
8: point_8,
9: point_9
}
return keys
그리고 나 서 나 는 다른 방법 을 통 해 연결선 을 그 리 는 기능 을 실현 했다.
def gesture_password(self, element: WebElement, *pwd): # pwd ,pwd[0]
""" : , 9
pwd: , :1, 2, 3, 6, 9
"""
if len(pwd) > 9:
raise ValueError(" 9 !")
keys_dict = self.get_password_location(element) # 9
start_point = "TouchAction(self.driver).press(x={0}, y={1}).wait(200)".\ # keys_dict[pwd[0]]
format(keys_dict[pwd[0]]["x"], keys_dict[pwd[0]]["y"]) #
for index in range(len(pwd)-1): # 0,1,2,3
follow_point = ".move_to(x={0}, y={1}).wait(200)".\
format(keys_dict[pwd[index+1]]["x"] - keys_dict[pwd[index]]["x"],
keys_dict[pwd[index+1]]["y"] - keys_dict[pwd[index]]["y"]) #
start_point = start_point + follow_point #
full_point = start_point + ".release().perform()" # .release().perform()
return eval(full_point) #
비교적 이해 하기 어 려 운 부분 은 내 가 이미 상세 하 게 주석 을 달 았 다.물론,너 는 나의 코드 를 복사 해서 먼저 성공 적 으로 그 릴 수 있 는 지 검증 한 다음 에 코드 의 실현 원 리 를 분석 할 수 있다.모든 코드
수 정 된 제스처 암호 코드&슬라이더 코드
"""
------------------------------------
@Time : 2019/8/6 20:45
@Auth : linux
@File : base.py
@IDE : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ : [email protected]
@GROUP: 878565760
------------------------------------
"""
import time
from appium.webdriver import WebElement
from appium.webdriver.common.touch_action import TouchAction
from appium.webdriver.webdriver import WebDriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import NoSuchElementException, TimeoutException
class Base(object):
def __init__(self, driver: WebDriver):
self.driver = driver
@property
def get_phone_size(self):
""" """
width = self.driver.get_window_size()['width']
height = self.driver.get_window_size()['height']
return width, height
def swipe_left(self, duration=300):
""" """
width, height = self.get_phone_size
start = width * 0.9, height * 0.5
end = width * 0.1, height * 0.5
return self.driver.swipe(*start, *end, duration)
def swipe_right(self, duration=300):
""" """
width, height = self.get_phone_size
start = width * 0.1, height * 0.5
end = width * 0.9, height * 0.5
return self.driver.swipe(*start, *end, duration)
def swipe_up(self, duration):
""" """
width, height = self.get_phone_size
start = width * 0.5, height * 0.9
end = width * 0.5, height * 0.1
return self.driver.swipe(*start, *end, duration)
def swipe_down(self, duration):
""" """
width, height = self.get_phone_size
start = width * 0.5, height * 0.1
end = width * 0.5, height * 0.9
return self.driver.swipe(*start, *end, duration)
def skip_welcome_page(self, direction, num=3):
"""
:param direction: str ,left, right, up, down
:param num:
:return:
"""
direction_dic = {
"left": "swipe_left",
"right": "swipe_right",
"up": "swipe_up",
"down": "swipe_down"
}
time.sleep(3)
if hasattr(self, direction_dic[direction]):
for _ in range(num):
getattr(self, direction_dic[direction])() #
else:
raise ValueError(" {} , direction {} ".
format(direction, direction_dic.keys()))
@staticmethod
def get_element_size_location(element):
width = element.rect["width"]
height = element.rect["height"]
start_x = element.rect["x"]
start_y = element.rect["y"]
return width, height, start_x, start_y
def get_password_location(self, element: WebElement) -> dict:
width, height, start_x, start_y = self.get_element_size_location(element)
point_1 = {"x": int(start_x + width * (1 / 6) * 1), "y": int(start_y + height * (1 / 6) * 1)}
point_2 = {"x": int(start_x + width * (1 / 6) * 3), "y": int(start_y + height * (1 / 6) * 1)}
point_3 = {"x": int(start_x + width * (1 / 6) * 5), "y": int(start_y + height * (1 / 6) * 1)}
point_4 = {"x": int(start_x + width * (1 / 6) * 1), "y": int(start_y + height * (1 / 6) * 3)}
point_5 = {"x": int(start_x + width * (1 / 6) * 3), "y": int(start_y + height * (1 / 6) * 3)}
point_6 = {"x": int(start_x + width * (1 / 6) * 5), "y": int(start_y + height * (1 / 6) * 3)}
point_7 = {"x": int(start_x + width * (1 / 6) * 1), "y": int(start_y + height * (1 / 6) * 5)}
point_8 = {"x": int(start_x + width * (1 / 6) * 3), "y": int(start_y + height * (1 / 6) * 5)}
point_9 = {"x": int(start_x + width * (1 / 6) * 5), "y": int(start_y + height * (1 / 6) * 5)}
keys = {
1: point_1,
2: point_2,
3: point_3,
4: point_4,
5: point_5,
6: point_6,
7: point_7,
8: point_8,
9: point_9
}
return keys
def gesture_password(self, element: WebElement, *pwd):
""" : , 9
pwd: 1, 2, 3, 6, 9
"""
if len(pwd) > 9:
raise ValueError(" 9 !")
keys_dict = self.get_password_location(element)
start_point = "TouchAction(self.driver).press(x={0}, y={1}).wait(200)". \
format(keys_dict[pwd[0]]["x"], keys_dict[pwd[0]]["y"])
for index in range(len(pwd) - 1): # 0,1,2,3
follow_point = ".move_to(x={0}, y={1}).wait(200)". \
format(keys_dict[pwd[index + 1]]["x"] - keys_dict[pwd[index]]["x"],
keys_dict[pwd[index + 1]]["y"] - keys_dict[pwd[index]]["y"])
start_point = start_point + follow_point
full_point = start_point + ".release().perform()"
return eval(full_point)
def find_element(self, locator: tuple, timeout=30) -> WebElement:
wait = WebDriverWait(self.driver, timeout)
try:
element = wait.until(lambda driver: driver.find_element(*locator))
return element
except (NoSuchElementException, TimeoutException):
print('no found element {} by {}', format(locator[1], locator[0]))
if __name__ == '__main__':
pass
"""
------------------------------------
@Time : 2019/8/6 20:47
@Auth : linux
@File : test.py
@IDE : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ : [email protected]
@GROUP: 878565760
------------------------------------
"""
import time
import unittest
from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy
from base import Base
class TestGesture(unittest.TestCase):
def setUp(self):
desired = {
"automationName": "uiautomator1",
"platformName": "Android",
"platformVersion": '5.1.1',
"deviceName": "127.0.0.1:62001",
"appPackage": "com.xxzb.fenwoo",
"appActivity": "com.xxzb.fenwoo.activity.addition.WelcomeActivity",
"app": r"D:\AppAutoTest\appPackage\Future-release-2018.apk",
"unicodeKeyboard": True, #
"resetKeyboard": True
}
self.driver = webdriver.Remote(command_executor="http://127.0.0.1:4723/wd/hub",
desired_capabilities=desired)
self.base = Base(self.driver)
def test_gesture_password(self):
self.base.skip_welcome_page('left', 3) #
time.sleep(3) #
self.driver.start_activity(app_package="com.xxzb.fenwoo",
app_activity=".activity.user.CreateGesturePwdActivity")
commit_btn = (MobileBy.ID, 'com.xxzb.fenwoo:id/right_btn')
password_gesture = (MobileBy.ID, 'com.xxzb.fenwoo:id/gesturepwd_create_lockview')
element_commit = self.base.find_element(commit_btn)
element_commit.click()
password_element = self.base.find_element(password_gesture)
self.base.gesture_password(password_element, 1, 2, 3, 6, 5, 4, 7, 8, 9)
time.sleep(5) #
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main()
테스트 효과슬라이더 포함
총결산
마지막 으로,우 리 는 모든 조작 을 완성 하기 위해 습득 해 야 할 지식 을 다시 한 번 정리 하 였 다.
1.화면 이 미 끄 러 질 때 시작 위치 와 끝 위 치 는 어디서부터 시작 하고 끝 나 는 지,어떻게 가 져 오 는 지
2.화면 을 움 직 일 때 사용 하 는 swipe()방법
3.여러 번 의 미끄럼 방법의 실현 원 리 를 실현 하고 여기에 반 사 를 사 용 했 습 니 다.사실 if 를 사용 해도 똑 같은 효 과 를 실현 할 수 있 지만 if 가 약간 low 인 것 같 습 니 다.
4.9 궁 격 시작 위치 와 핸드폰 화면의 관계 및 각 점 의 좌 표를 어떻게 계산 합 니까?
5.Touch Action 류 에서 자주 사용 하 는 방법
6.제스처 암 호 를 그 리 는 방법의 봉인 원리 와 사고방식 이해
위 에서 말 한 것 은 스 와 이 프 방법 으로 화면 미끄럼 과 제스처 비밀 번 호 를 모 의 해서 그 리 는 것 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 메 시 지 를 남 겨 주세요.스 와 이 프 는 바로 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!
만약 당신 이 본문 이 당신 에 게 도움 이 된다 고 생각한다 면,전 재 를 환영 합 니 다.번 거 로 우 시 겠 지만 출처 를 밝 혀 주 십시오.감사합니다!