概要
テストが全く存在しないUnityPJにて、半年間必死でAirtest+Pocoを用いて厳密なシナリオテストの導入を行いました。
公式ドキュメントがざっくりとしか書かれていなかったため、あらゆる記事から情報をかき集めた内容をここにまとめます。
あらゆる情報をごった煮で載せるので、頑張ってカテゴライズはしようと思います。
以下の内容で困っている人には助けになると思います。
- ログのHTML出力をコードで行いたい
- 他の.airファイルを呼び出したい
- Androidの実機に対してコマンドラインでテスト実行したい
- AirtestからAndroid実機に対してアプリインストール・起動コマンドを実行したい
- AirtestIDE上でWindowsアプリがDeviceタブに埋め込まれないようにしたい
まずはじめに
私が半年間かけて探し出した優良記事をまずまとめておきます。
-
https://gitee.com/AirtestProject/Poco
- Pocoの使い方が丁寧に記載されている
-
https://github.com/AirtestProject/Airtest/blob/master/docs/wiki/code/code_example.md
- Airtestの公式Github内で例も交えて紹介されているREADME
-
https://qiita.com/mmm_hiro/items/f6776d3458f767cf9d09
- Unityの関数をPoco経由でAirtestから呼び出す事が出来る
公式ドキュメント集
Airtestのインスト
Airtestの公式ドキュメント
Pocoの公式ドキュメント
この記事では上記の優良記事で、個人的に欲しかった部分を翻訳してまとめてる程度です。
+aで私の経験的に便利だったものを少しだけ添えています。
エディタ(IDE)設定関連
Windowsアプリの埋め込み無し設定
デフォルト設定でWindowsアプリを指定するとDevicesタブに埋め込まれてしまう。
それを防ぐためにSettingsを開いて「Connect windows without embedding」をチェックすれば開発しやすくなる。
実機操作関連
Androidアプリのテスト
実機でテストを実行
WindowsとAndroidの実機をUSB接続している前提でお話します。
adbコマンドが使えるように設定をお願いします。
$ adb devices
List of devices attached
00adbe3a8489b958 device
$ /d/AirtestIDE/AirtestIDE.exe runner {.airまでの絶対パス}/Sample.air --device Android://127.0.0.1:5073/00adbe3a8489b958
Android://127.0.0.1:5073/00adbe3a8489b958
USB実機の場合はローカルホスト指定
特別設定していない限りポートも5073固定のはず
最後のシリアル番号はadb devices
で取得したデバイスIDを入れる
auto_setupでデバイス指定も可能
auto_setup関数のdevices引数にデバイス情報を渡している場合は、コマンドでデバイス指定無しに出来る
# -*- encoding=utf8 -*-
__author__ = "ohyoso"
auto_setup(__file__, devices=["android://127.0.0.1:5037/00adbe3a8489b958"])
# テストコード
複数端末をコード上で切り替えて操作可能(らしい)
先述のauto_setupでのdevicesで2つ以上指定していた場合、IndexまたはデバイスIDで現在操作したい端末が切り替え可能らしい(試したことは無いです)
auto_setup(__file__, devices=["android://127.0.0.1:5037/00001", "android://127.0.0.1:5037/00002"])
# devicesでの登録順で多分Indexが振られていて、切り替え可能
set_current(0)
set_current(1)
# デバイスIDを指定して、固定デバイスで操作可能(だと思う)
set_current("00001")
set_current("00002")
アプリのインストール/アンインストール
uninstall("com.example.myapp") # アプリケーションIDを指定する
install(r"D:\TestApp\SampleApp.apk") # apkのパスを指定する
アプリの実行/停止
#スタート・ストップ両方アプリケーションIDを指定
start_app("com.example.myapp")
stop_app("com.example.myapp")
Poco(Unity)関連
クリック位置の調整
Unityの場合、Anchor設定によってクリック位置の調整が必要となる。
focus関数を間に挟むことも可能なので、状況に応じて使い分けることが出来る。
poco("hoge").click([0.5, 0.5]) #UIパーツの中心を押す
poco("hoge").click("center") #↑と同じ挙動
hoge_item = poco("hoge").focus([0.5, 0.5]) #中心にフォーカスされたUIパーツを取得可能
hoge_item.click()
hoge_item.long_click(duration=3) #3秒間クリック
Unityの関数を呼び出す
UnityへのPoco導入及び、Unityの関数を実行できるようになるまでを別記事にしている。
そちらを参照してほしい。
(FIXME: 後々URL記載予定)
Airtestの特殊操作
別の.airファイルを呼び出したい
usingで呼び出し可能
def hello():
log("Hello world")
class Dog:
def __init__(self):
def cry(self):
log("bow")
using('Utility.air')
from Utility import hello, Dog
hello() # Hello world
dog = Dog()
dog.Bow() # bow
ログ関連
ログファイルの生成方法
AirtestIDE上
AirtestIDE上で Ctrl+L を押すと、テストの一番最後の実行履歴からHTMLのログデータを出力してブラウザ上で確認可能
テキストログファイルの生成方法
auto_setup関数でlogdirをTrueにすると、スクリプトのディレクトリにlogフォルダが作成される
logフォルダには、log.txtとスナップショットの画像が格納されている。
# -*- encoding=utf8 -*-
__author__ = "ohyoso"
auto_setup(__file__, logdir=True)
テキストログファイルの場所を変更したい
テキストファイル名と、保存先を任意に変更可能
auto_setupの記述は必要無し
# -*- encoding=utf8 -*-
__author__ = "ohyoso"
from airtest.core.settings import Settings
from airtest.core.helper import set_logdir
Settings.LOG_FILE = "sample_log.txt"
set_logdir(r'D:\LogTest')
HTMLレポートの作成
log.txtをHTML形式に変換してくれる、simple_report関数を呼び出す
以下のコードの場合、Sample.air/log/log.txtテストコード実行後に実行ログをHTMLに変換する
from airtest.report.report import simple_report
auto_setup(__file__, logdir=True)
# テストコード
simple_report(__file__,logpath=True,output=r"D:\Hogehoge\Sample.air\log\log.html")
simple_reportの設定可能な引数は以下の通りである
simple_report(filepath, logpath=True, logfile='', output='')
filepath : 対象の.airパス
logpath : Trueの場合、filepath内のlogフォルダが指定される
logfile : ログファイルが別の場所に出力されている場合、指定する際に使う
output : HTMLの出力パス
先程記述したサンプルコードは、Sample.air実行時のSample.air/log/log.txt
をlog/log.html
に変換している。
更にカスタマイズ可能なLogToHtml
関数が用意されているが、個人的には上記で満足だと考える。
もし詳細を見たい場合はこちらを参照してほしい。
スナップショットを取る方法
「ログファイルの生成方法」で紹介したログフォルダに保存されるスナップショットを撮れる
snapshot(filename="123.jpg", msg="Homepage screenshot", quality=90, max_size=800)
filename : ファイル名を指定可能
msg : HTMLログファイルでスナップショットに紐づくメッセージを仕込むことが出来る
quality : 1~99でクオリティを指定出来る
max_size : 最大サイズ
ログ出力
log関数
log関数を使うことで、標準出力+ログファイルで確認可能
# ログに対して説明を付与することが可能
character_name = "Hogehoge"
log(character_name,desc="キャラクター名")
# String以外のデータ構造を渡すことが可能
data = {"name": "Hogehoge", "power": 123456}
log(data,desc="キャラクターの現在のパラメータ")
# Exceptionの詳細をトレースバックすることも
try:
1/0
except Exception as e:
log(e)
# ログにタイムスタンプやスナップショットを付与することも
import datetime
log("123", timestamp=datetime.datetime.now(), desc="〇〇の現在状況スナップショット", snapshot=True)
試しにメモ帳でデモテストを組み、紫一色にした後に以下のログを仕込んだ際の結果を示す
(もっと良いデモを組みたかったが、ちょうどいいサンプルが無かった)
log("test", timestamp=datetime.datetime.now(), desc="紫一色変更した際の時間と状況", snapshot=True)
ログレベルの変更
出力するログレベルを制御することで、エラーの早期発見に役立つだろう
__author__ = "Airtest"
import logging
logger = logging.getLogger("airtest")
logger.setLevel(logging.ERROR)
おまけとまとめ
pocoのAutoRecording機能って使ったことありますでしょうか。
Unityで制作中のゲームアプリで使ってみたのですが、個人的にあまり芳しくなかったです・・。
- まずAndroidアプリでしか使えない
- アプリ内のレイヤー順を考慮してくれず、前レイヤーの透明パネル等を選択してしまう
- 更にPocoのアンカー設定で判定されるため、当たり判定がそもそものUIと全く別のところにあることも
正直この機能があるから簡単に導入出来そうと積極的になっていましたが、使い勝手が悪い事から結果シナリオテストの導入をオミットしてしまいました。
HTMLのログビュワー等素敵なツールが揃っているので、局所的な繰り返しテスト、モンキータップテストには最適だと思います。
良きAirtestライフを~~