スタートアップコード(プリコード)
# 导模块
from appium import webdriver
# 创建一个字典,包装相应的启动参数
desired_caps = dict()
# 需要连接的手机的平台(不限制大小写)
desired_caps['platformName'] = 'Android'
# 需要连接的手机的版本号(比如 9.2.1 的版可以填写9.2.1或9.2或9,以此类推)
desired_caps['platformVersion'] = '9'
# 需要连接的手机的设备号(andoird平台下,可以随便写,但是不能不写)
desired_caps['deviceName'] = '192.168.56.101:5555'
# 需要启动的程序的包名
desired_caps['appPackage'] = '启动的包名'
# 需要启动的程序的界面名
desired_caps['appActivity'] = '启动的界面名'
# 文本框输入中文时要用
desired_caps['unicodeKeyboard'] = True
desired_caps['resetKeyboard'] = True
# 连接appium服务器,获取driver
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
# 退出driver
driver.quit()
ブートプロセス:
注: appium を起動すると、実際にはこのマシンのポート 4723 を使用してサービスが開始されます。
- Python コードはローカル appium サーバーにアクセスし、ドライバー オブジェクトを取得します。
- Appium は、ドライバー オブジェクトによって呼び出されるメソッドをポスト リクエストに変換し、appium サーバーに送信します。
- Appium は受信したポストリクエストを通じてそれを携帯電話に送信し、携帯電話がそれを実行します。
1. スクリプト内で他のアプリを起動します
アプリケーションシナリオ: アプリケーションが別のアプリケーションにジャンプする必要がある場合、食品配達アプリケーションを通じて注文した後に支払いアプリケーションにジャンプするのと同じように、この API を使用してアプリケーションにジャンプできます。
方法:
# 参数:
# appPackage:要打开的程序的包名
# appActivity:要打开的程序的界面名
driver.start_activity(appPackage, appActivity)
2. アプリのパッケージ名とインターフェース名を取得します
アプリケーション シナリオ: あるアプリケーションから別のアプリケーションにジャンプするときに、そのパッケージ名、インターフェイス名を出力するか、レポートに対応する情報を表示したい場合は、このプロパティを呼び出して取得できます。
方法:
# 获取包名
driver.current_package
# 获取界面名
driver.current_activity
3. アプリを閉じてオブジェクトを駆動する
アプリケーションのシナリオ: 新しいアプリケーションを開く前に、アプリケーションを閉じる必要がある場合があります。
方法:
# 关闭当前操作的app,不会关闭驱动对象
driver.close_app()
# 关闭驱动对象,同时关闭所有关联的app
driver.quit()
4. アプリのインストールとアンインストール、インストールするかどうか
アプリケーションシナリオ: アプリケーションマーケットの一部のソフトウェアにはボタンがあり、特定のプログラムがインストールされている場合はアンインストールされ、インストールされていない場合はインストールされます。
方法:
# 安装app
# 参数:
# app_path:apk路径
driver.install_app(app_path)
# 卸载app
# 参数:
# app_id:应用程序包名
driver.remove_app(app_id)
# 判断app是否已经安装
# 参数:
# app_id:应用程序包名
# 返回值:
# 布尔类型,True为安装,False为没有安装
driver.is_app_installed(app_id)
5. アプリをバックグラウンドに置く
アプリケーション シナリオ: 銀行アプリは一定期間バックグラウンドに入り、フォアグラウンドに戻るとページはパスワードを再入力します。この機能を自動的にテストする必要がある場合は、この API をテストに使用できます。
方法:
# app放置到后台一定时间后再回到前台,模拟热启动
# 参数:
# seconds:后台停留多少秒
driver.background_app(seconds)
ホット スタート: バックグラウンドに入り、フォアグラウンドに戻ることを意味します。電源をオフにして再度オンにすることで電源を遮断する動作を「コールドスタート」と呼ぶことがあります。
6. 要素の配置
応用シナリオ: コンピューターがこの要素の「操作」を支援できるように、要素の位置決めを通じて要素を取得する必要があります。
要素の属性値の取得: インストールされた Android SDK ディレクトリにある uiautomatorviewer ツールを通じて取得できます。
要素メソッドの検索:
- ID で要素を検索する
# 参数:
# id_value:元素的resource-id属性值
# 返回值:
# 定位到的单个元素
driver.find_element_by_id(id_value)
- class_name で要素を検索する
# 参数:
# class_value:元素的class属性值
# 返回值:
# 定位到的单个元素
driver.find_element_by_class_name(class_value)
- xpathで要素を見つける
# 参数:
# xpath_value:定位元素的xpath表达式
# 返回值:
# 定位到的单个元素
driver.find_element_by_xpath(xpath_value)
要素のグループを見つける方法:
- ID で要素のグループを検索する
# 参数:
# id_value:元素的resource-id属性值
# 返回值:
# 列表,定位到的所有符合调价你的元素
driver.find_elements_by_id(id_value)
- class_name で要素のグループを検索します。
# 参数:
# class_value:元素的class属性值
# 返回值:
# 列表,定位到的所有符合调价你的元素
driver.find_elements_by_class_name(class_value)
- xpath を介して要素セットを検索する
# 参数:
# xpath_value:定位元素的xpath表达式
# 返回值:
# 列表,定位到的所有符合调价你的元素
driver.find_elements_by_xpath(xpath_value)
注意点:
1. 要素の位置は、現在の画面範囲内に表示される可視要素に基づきます。
2. find_element_by_xx メソッドを使用する場合、存在しない機能を渡すと、NoSuchElementException エラーが報告されます。
3. find_elements_by_xx メソッドを使用する場合、存在しない機能を渡してもエラーは報告されず、空のリストが返されます。
7. 要素待ち
適用シナリオ: ネットワーク速度の理由、サーバーの処理要求、コンピューターの構成の理由などにより、探している要素がすぐには出てこないため、直接見つけた場合、エラーが報告される可能性があります。
分類: 暗黙的待機と明示的待機
(1) 暗黙的な待機
アクションの範囲: 配置されたすべての要素に対する操作 (グローバルに有効)
方法:
# 参数:
# timeout:超时的时长,单位:秒
implicitly_wait(timeout)
(2) 表示待ち
動作範囲:特定の位置決め要素に対する動作(単一有効)
方法:
# 导入显示等待包
from selenium.webdriver.support.wait import WebDriverWait
# 参数:
# driver:驱动对象
# timeout:超时的时长,单位:秒
# poll_frequency:检测间隔时间,默认为0.5秒
# method:lambda查找元素表达式
# 返回值:
# 定位到的元素,如果没有定位到会抛出TimeoutException异常
element = WebDriverWait(driver, timeout, poll_frequency=0.5).until(method)
8. 要素をクリックします。
アプリケーションシナリオ: ボタンをクリックする必要がある場合に使用します。
方法:
# 对element按钮进行点击操作
element.click()
9. 入力ボックスの内容を入力およびクリアします
アプリケーションシナリオ: 入力ボックスに入力またはクリアする必要がある場合に使用されます。
方法:
# 对element输入框进行输入操作
# 参数:
# value:输入的内容
element.send_keys(value)
# 对element输入框进行输入操作
element.clear()
注意点: デフォルトの中国語入力は無効ですが、エラーは報告されません。これら 2 つのパラメータは「プリコード」に含める必要があります。
desired_caps['unicodeKeyboard'] = True
desired_caps['resetKeyboard'] = True
10. 要素のテキストコンテンツを取得する
アプリケーションシナリオ: ボタン、テキストボックス、入力ボックスなどのコントロールのテキストコンテンツを取得する必要がある場合に使用されます。
方法:
# 获取element控件的文本内容
# 返回值:
# 控件的文本内容
element.text
11. 要素の位置とサイズを取得する
アプリケーションシナリオ: 要素の位置とサイズを取得する必要がある場合に使用します。
方法:
# 获取element的位置
# 返回值:
# 字典,x为元素的x坐标,y为元素的y坐标
element.location
# 获取element的大小
# 返回值:
# 字典,width为宽度,height为告诉
element.size
12. 要素の属性値を取得する
アプリケーションシナリオ: 特性に従って要素を見つけた後、要素の属性名に対応する属性値を取得させます。
方法:
# 获取element的属性值
# 参数:
# value:要获取的属性名
# 返回值:
# 根据属性名得到的属性值
element.get_attribute(value) # value:元素的属性
注意点:
value='text' はテキストの属性値を返します。
value='name' は content-desc/text 属性値を返します
value='className' はクラス属性値を返します。これをサポートできるのは API=>18 だけです
value='resourceId' は resource-id 属性値を返します。API=>18 のみがサポート可能です
13. スライド&ドラッグイベント
アプリケーションシナリオ: 一部のボタンは画面を数回スライドさせないと表示されません。このとき、コードを使用して指のスライドをシミュレートする必要があります。
カテゴリ: スワイプ スライディング イベント、スクロール スライディング イベント、ドラッグ アンド ドロップ ドラッグ イベント
(1) スワイプスライドイベント
概念: ある座標位置から別の座標位置へのスライドは 2 点間のスライドにしかなりません (慣性は時間に応じて変化します)
方法:
# 参数:
# start_x: 起点X轴坐标
# start_y: 起点Y轴坐标
# end_x: 终点X轴坐标
# end_y: 终点Y轴坐标
# duration: 滑动这个操作一共持续的时间长度,单位:ms
driver.swipe(start_x, start_y, end_x, end_y, duration=None)
同じ距離であれば、継続時間が長いほど慣性は小さくなります
持续时间相同时,手指滑动的距离越大,实际滑动的距离也就越大
(2)scroll滑动事件
概念:从一个元素滑动到另一个元素,直到页面自动停止(惯性很大)
方法:
# 参数:
# origin_el: 滑动开始的元素
# destination_el: 滑动结束的元素
driver.scroll(origin_el, destination_el)
(3)drag_and_drop拖拽事件
概念:从一个元素滑动到另一个元素,第二个元素替代第一个元素原本屏幕上的位置(无惯性)
方法:
# 参数:
# origin_el: 滑动开始的元素
# destination_el: 滑动结束的元素
driver.drag_and_drop(origin_el, destination_el)
14、高级手势TouchAction
应用场景:TouchAction 可以实现一些针对手势的操作,比如滑动、长按、拖动等。我们可以将这些基本手势组合 成一个相对复杂的手势。比如,我们解锁手机或者一些应用软件都有手势解锁的这种方式。
使用步骤:
- 1. 创建 TouchAction 对象
- 2. 通过对象调用想执行的手势
- 3. 通过 perform() 执行动作
(1)轻敲操作
概念:模拟手指对某个元素或坐标按下并快速抬起
方法:
# 参数:
# element:元素
# x:x坐标
# y:y坐标
TouchAction(driver).tap(element=None, x=None, y=None).perform()
注:元素和坐标任选其一,选择坐标时需要标明x=,y=,否则会被误认为是element
(2)按下和抬起操作
概念:模拟手指一直按下,模拟手指抬起。可以用来组合成轻敲或长按的操作
方法:
# 模拟手指对元素或坐标的按下操作
# 参数:
# el:元素
# x:x坐标
# y:y坐标
TouchAction(driver).press(el=None, x=None, y=None).perform()
# 模拟手指对元素或坐标的抬起操作
TouchAction(driver).release().perform()
(3)等待操作
概念:模拟手指等待,比如按下后等待 5 秒之后再抬起
方法:
# 参数:
# ms:暂停的毫秒数
TouchAction(driver).wait(ms=0).perform()
(4)长按操作
概念:模拟手指对元素或坐标的长按操作。比如,长按某个按钮弹出菜单
方法:
# 参数:
# el:元素
# x:x坐标
# y:y坐标
# duration:长按时间,毫秒
TouchAction(driver).long_press(el=None, x=None, y=None, duration=1000).perform()
(5)移动操作
概念:模拟手指移动操作,比如,手势解锁需要先按下,再移动
方法:
# 参数:
# el:元素
# x:x坐标
# y:y坐标
TouchAction(driver).move_to(el=None, x=None, y=None).perform()
15、获取手机分辨率
应用场景:需要根据当前设备的屏幕分辨率来计算一些点击或者滑动的坐标
方法:
driver.get_window_size() # 返回值是字典{'height'= x, 'width'= x}
16、获取手机截图
应用场景:有些自动化的操作可能没有反应,但并不报错。此时我们就可以将操作过后的关键情况,截图留存。后期也可以根据图片发现问题
方法:
# 参数:
# filename:指定路径下,指定格式的图片
get_screenshot_as_file(filename)
17、获取和设置手机网络
应用场景:视频应用在使用流量看视频的时候,大部分都会提示用户正在是否继续播放。我们可能需要用自动化的形式来判断是否有对应的提示。即用流量的时候应该有提示,不用流量的时候应该没有提示。
方法:
# 获取手机网络
driver.network_connection
# 设置手机网络
# 参数: # connectionType:网络类型
driver.set_network_connection(connectionType)
手机网络类型对照: (流量、WiFi、飞行模式)
18、发送键到设备
应用场景:模拟按 “返回键” “home键” “音量加减”等等操作
方法:
# 参数:
# keycode:发送给设备的关键代码
# metastate:关于被发送的关键代码的元信息,一般为默认值
driver.press_keycode(keycode, metastate=None)
常用的手机键:
键名 | 键名 | 关键代码 |
KEYCODE_HOME | 按键Home | 3 |
キーコード_メニュー | メニュー | 82 |
KEYCODE_BACK | リターンキー | 4 |
KEYCODE_VOLUME_UP | 音量アップキー | 24 |
KEYCODE_VOLUME_DOWN | 音量ダウンキー | 25 |
キーに対応するコードは、「android キーコード」というキーワードで検索できます
例: https://blog.csdn.net/feizhixuan46789/article/details/16801429
19. 電話通知バーのオンとオフを切り替える
応用シナリオ: 携帯電話が通知バーを通じてメッセージを受信したかどうかを判断したい場合は、まず携帯電話の通知バーを操作する必要があります
方法:
# 打开手机通知栏
driver.open_notifications()
# 关闭手机通知栏
driver.press_keycode(4) # 直接返回就能关闭,没有专门的方法关闭