화면 미끄럼 과 제스처 암 호 를 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.제스처 암 호 를 그 리 는 방법의 봉인 원리 와 사고방식 이해
위 에서 말 한 것 은 스 와 이 프 방법 으로 화면 미끄럼 과 제스처 비밀 번 호 를 모 의 해서 그 리 는 것 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 메 시 지 를 남 겨 주세요.스 와 이 프 는 바로 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!
만약 당신 이 본문 이 당신 에 게 도움 이 된다 고 생각한다 면,전 재 를 환영 합 니 다.번 거 로 우 시 겠 지만 출처 를 밝 혀 주 십시오.감사합니다!

좋은 웹페이지 즐겨찾기