MENU

iPhone自动化测试

May 29, 2018 • Read: 146 • 开发阅读设置

0x01 简介

WebDriverAgent一款自动化iOS测试工具,相当于在iphone上安装一个软件作为服务端,然后接受处理来自mac客户端的请求。


0x01 安装

#安装WebDriverAgent
git clone https://github.com/facebook/WebDriverAgent.git 
brew install carthage
brew install node
cd WebDriverAgent && sudo ./Scripts/bootstrap.sh

#安装libimobiledevice 
brew install --HEAD libimobiledevice 

#安装imobiledevice
brew install imobiledevice

#安装facebook-wda
pip install --pre  facebook-wda

0x02 配置

  • 基本设置

iphone 屏幕常亮、wifi 连接以及后续设置信任开发者。

  • 配置证书
cd WebDriverAgent
open WebDriverAgent.xcodeproj

WebDriverAgentLib -> Signing

WebDriverAgentRunner -> Product Bundle Identifier -> com.facebook.WebDriverAgentRunerfdfdasf    //修改BundleID避免重名

WebDriverAgentRunner -> Signing
Product -> Destination -> xxx的iphone
Product -> Scheme -> WebDriverAgentRunner
View -> Debug Area -> Activate Console
Product -> Test
sudo iproxy 8100 8100
  • 验证
http://localhost:8100/inspector
http://localhost:8100/status
ideviceinstaller -l //查看所有应用Bundle ID
  • 定位元素

图片浏览器定位,鼠标放上去就能显示当前坐标,比如GIMP或者在线网站


0x03 facebook-wda语法

  • 基本操作
import wda
wda.DEBUG = True  #开启debug模式方便查看API
c = wda.Client("http://192.168.1.101:8100")

c.home()            #点击主页按钮
c.source(accessible = True) #获取页面源码
c.screenshot('screen.png')  #截图只能保存png
  • 会话操作
import wda
wda.DEBUG = True
c = wda.Client("http://192.168.1.101:8100")
s = c.session()   
with c.session("com.apple.Health") as s:
    print s.window_size()              #获取尺寸
    s.tap(200,200)                     #模拟触摸
    s.double_tap(200,200)              #双次触摸
    s.tap_hold(100, 100, press_time) #在 (100, 100) 的位置按压 press_time 后松开
# s.swipe(X1,Y1,X2,Y2, 0.5)# 0.5秒
# s.swipe_left()
# s.swipe_right()
# s.swipe_up()
# s.swipe_down()

# #抽头保持
# s.tap_hold(X,Y, 1.0)
  • 操作元素
import wda
wda.DEBUG = True
c = wda.Client("http://192.168.1.101:8100")
with c.session("com.apple.Health") as s:
    s(text='Dashboard').get().tap()
    s(text = ' Dashboard ').find_elements() #查找所有匹配元素,返回元素对象数组 
    s(text = 'Dashboard ').child(className = ' Cell ')#使用子元素搜索子元素
    s.set_text("Hello WDA\n") # 发送文本
    s.set_text("\b\b\b") # 删除三个字符
   s(text='Dashboard').wait_gone(timeout=10.0)

   s(className="Image").swipe("left")#像图片左滑动
   RECT = e.bounds#例如:矩形(X = 144,Y = 28,宽度= 88.0,高度= 27.0)
  • 弹框操作

弹框可以用alert进行处理或者直接s(name=u'知道了').tap()

session.alert.accept()

0x04 测试案例

  • 下载以及登录APP
# -*- coding:utf-8 -*-
# !/usr/bin/env python


import time
import wda

wda.DEBUG = True
c = wda.Client("http://localhost:8100/")


def download():
    s = c.session("com.apple.mobilesafari", ["-u", "https://itunes.apple.com/app/id590338362"])
    e = s(name=u'打开').get(timeout=10, raise_error=False)
    e.tap()
    time.sleep(5)
    if s(className='Button', name=u'获取').exists:
        s(className='Button', name=u'获取').get(timeout=2, raise_error=False).tap()
        s(className='Button', name=u'安装').get(timeout=30, raise_error=False).tap()
    elif s(className='Button', name=u'重新下载').exists:
        s(className='Button', name=u'重新下载').get(timeout=10, raise_error=False).tap()
    else:
        exit()


def alert_callback(session):
    """
    处理不知何时就会突然弹出的警告框
    """
    btns = set([u'不再提醒', 'OK', u'知道了', 'Allow', u'允许']).intersection(session.alert.buttons())
    if len(btns) == 0:
        raise RuntimeError("Alert can not handled, buttons: " + ', '.join(session.alert.buttons()))
    session.alert.click(list(btns)[0])


def login():
    USERNAME = 'xxxx'
    PASSWORD = 'xxxx'
    s = c.session('com.netease.cloudmusic')
    s.set_alert_callback(alert_callback)
    if s(name=u'发现音乐', type='Button').wait(3, raise_error=False): # 开头有2s的广告,所以这里需要等待3s
        return # 已经登录直接跳过
    s(name=u'登录/注册').tap()
    s.set_alert_callback(alert_callback)
    s(name=u'手机号登录').tap()
    s(type='TextField').set_text(USERNAME + '\n')
    s(type='SecureTextField').set_text(PASSWORD + '\n')
    s(name=u'登录').click_exists(timeout=3.0)
    assert s(name=u'发现音乐', type='Button').wait(5.0)


def main():
    download()
    time.sleep(180)
    login()


if __name__ == "__main__":
    main()
  • 答题
# -*- coding:utf-8 -*-
# !/usr/bin/env python
# 通过wda截图然后PIL剪裁定位文字后用OCR识别并放入搜素引擎找出词频最高的一个即答案。

import wda
import webbrowser
import base64
import time
import io
import requests
from PIL import Image
import urllib.parse

wda.DEBUG = True
c = wda.Client()

while True:
    time.sleep(0.5)
    c.screenshot('1.png')
    im = Image.open("1.png")
    region = im.crop((75, 315, 1167, 789))
    imgByteArr = io.BytesIO()
    region.save(imgByteArr, format='PNG')
    image_data = imgByteArr.getvalue()
    base64_data = base64.b64encode(image_data)
    r = requests.post('https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic',
                      params={'access_token': "24.3ad800dedc42aa06d955e786a8b304f9.2592000.1530559010.282335-11341238"}, data={'image': base64_data})
    result = ''
    for i in r.json()['words_result']:
        result += i['words']
    result = urllib.parse.quote(result)
    webbrowser.open('https://baidu.com/s?wd=' + result)
    input("> Next")
  • 批量删除短信
import time
import wda

c = wda.Client()

with c.session('com.apple.MobileSMS') as s:
    while 1:
        s.swipe(300, 300, 100, 300, 0.5) # 左滑
        s.tap_hold(c.session().window_size().width * 3 - 20, 900, 0.2) # 点击删除
  • 模拟点击
import time
import wda

wda.DEBUG = True
c = wda.Client("http://localhost:8100/")


def test():
    s = c.session("com.yaymedialabs.putong")
    while 1:
        s(name='home user dislike button', type='Button').click_exists()
        #time.sleep(0.1)
test()

0x05 引用

iOS 真机如何安装 WebDriverAgent
使用 Python 库 facebook-wda 完成网易云音乐 iOS 客户端的自动化测试
iOS自动化实践——WebDriverAgent(六)
微信「跳一跳」破解程序开发记录