ZOZOSUIT計測テスト、自動化への道(接触篇)

f:id:vasilyjp:20181210172650p:plain

こんにちは。品質管理部エンジニアリングチームの遠藤です。 前回の壮絶な失敗を何事もなかったかのように忘れ去り、次のテーマへ移りたいと思います。

工夫しなければいけなかったこと

ZOZOSUIT自動測定については前回のとおり何となくぼんやりとイメージはついていたのですが、「これはどうしよう」と思ったことが2つありました。

  • デバイスIDに依存したくない
  • 外部ディスプレイにどうやってブラウザ開くの?

といったことでした。

Androidデバイスの制御をする場合、デバイスIDをもとに制御するわけですが、これをそのままプログラム内に書いてしまうとその端末しか制御できません。またディスプレイが複数ついているためどのディスプレイにどの端末を向けているのかを事前に登録してからプログラムを動作させなければいけません。最初はとりあえずプロトタイプということでそのまま動かしていましたが、まずはここをなんとかしたかったです。 とりあえず、やってみます。

私やる!やるったらやる!

では具体的にどうすればよいでしょうか。デバイスに接続しているUSBケーブルの情報から接続しているデバイスIDがわかればなんとかなりそうです。とりあえず何も接続しない状態で、USBのシステム情報を確認してみます。

% ioreg -p IOUSB -w0
+-o Root  <class IORegistryEntry, id 0x100000100, retain 15>
  +-o AppleUSBXHCI Root Hub Simulation@14000000  <class AppleUSBRootHubDevice, id 0x100000351, registered, matched, active, busy 0 (0 ms), retain 15>
    +-o Bluetooth USB Host Controller@14300000  <class AppleUSBDevice, id 0x100000fc5, registered, matched, active, busy 0 (9 ms), retain 33>

こんどはUSBポートを増設した状態でやってみます。

% ioreg -p IOUSB -w0
+-o Root  <class IORegistryEntry, id 0x100000100, retain 15>
  +-o AppleUSBXHCI Root Hub Simulation@14000000  <class AppleUSBRootHubDevice, id 0x100000351, registered, matched, active, busy 0 (0 ms), retain 17>
    +-o Bluetooth USB Host Controller@14300000  <class AppleUSBDevice, id 0x100000fc5, registered, matched, active, busy 0 (9 ms), retain 33>
    +-o 4-Port USB 2.0 Hub@14100000  <class AppleUSBDevice, id 0x1000022ba, registered, matched, active, busy 0 (2 ms), retain 21>
    +-o 4-Port USB 3.0 Hub@14400000  <class AppleUSBDevice, id 0x1000022d0, registered, matched, active, busy 0 (1 ms), retain 21>

ポートが認識されています。そこにデバイスを接続してみます。

% ioreg -p IOUSB -w0
+-o Root  <class IORegistryEntry, id 0x100000100, retain 15>
  +-o AppleUSBXHCI Root Hub Simulation@14000000  <class AppleUSBRootHubDevice, id 0x100000351, registered, matched, active, busy 0 (0 ms), retain 17>
    +-o Bluetooth USB Host Controller@14300000  <class AppleUSBDevice, id 0x100000fc5, registered, matched, active, busy 0 (9 ms), retain 33>
    +-o 4-Port USB 2.0 Hub@14100000  <class AppleUSBDevice, id 0x1000022ba, registered, matched, active, busy 0 (2 ms), retain 22>
    | +-o F5321@14110000  <class AppleUSBDevice, id 0x100002315, registered, matched, active, busy 0 (7 ms), retain 25>
    +-o 4-Port USB 3.0 Hub@14400000  <class AppleUSBDevice, id 0x1000022d0, registered, matched, active, busy 0 (1 ms), retain 21>

14110000にF5321が接続されています。いろいろ抜き差しして調査してみた結果、この番号は基本的に変わらないようでした。 f:id:vasilyjp:20181119081220j:plain 自分の環境ではこんな感じでした。このナンバーのケーブルをあらかじめ対応させる予定の外部ディスプレイに向けておけばいい感じにいけそうです。

で、さっきのコマンドでデバイスIDを確認してっと、 f:id:vasilyjp:20181119081300p:plain これよく見たらデバイスIDじゃなくてデバイス名じゃねーか!

adb devicesでデバイス名との対応ができればいいのですが、表示されません。 f:id:vasilyjp:20181119081307p:plain

と思ってたら adb devices -l で表示されました。 f:id:vasilyjp:20181119081314p:plain 最初(さっきまで)はこれを知らず、system_profiler SPUSBDataTypeから無理やり取得していました。

コードに置き換えてみる(python3)

では早速これをコードに置き換えてみます。

import subprocess


def cmd(_cmd_str):
    # print("cmd:" + _cmd_str)
    proc = subprocess.run(_cmd_str, stdout=subprocess.PIPE, shell=True)
    return proc.stdout.decode("utf8")


#指定したUSB IDに繋がっているAndroidデバイス名を取得する
def check_usb_connect(_check_usb_id):
    cmd_str = "ioreg -p IOUSB -w0 | sed 's/[^o]*o //; s/  <.*$//' | grep '.*@.*' | grep -v Hub | grep -v USB"
    res = cmd(cmd_str)
    # print(res)
    for line in res.splitlines():
        dn, usb_id = line.split('@')
        # print(dn, usb_id)
        if usb_id == _check_usb_id:
            return dn
    return ""

#デバイス名からデバイスIDを取得する。
def deviceId_from_deviceName(_deviceName):
    cmd_str = "adb devices -l"
    res = cmd(cmd_str)
    for line in res.splitlines():
        if "product:" in line:
            device_id, etc = line.split('             ')
            elist = etc.split(' ')
            # print(device_id)
            device_name = elist[4].split(':')[1]
            if device_name == _deviceName:
                return device_id
    return ""


print("-----------")
device_name = check_usb_connect("14110000")
print("device_name:" + device_name)
device_id = deviceId_from_deviceName(device_name)
print("device_id:" + device_id)
できました! f:id:vasilyjp:20181119081630p:plain

注意点

ただ、これだと同じデバイス名の端末を接続すると見分けがつきません。なのでsystem_profiler SPUSBDataTypeなどの情報から、USBポートとの対応など考慮してデバイスIDを取得したほうがよさそうです。

次回予告

幾夜魘されたか知らない悪夢、目の前の僅かな一跨ぎ。それができない泥沼の中で 俺は喘ぐ。
俺はどうしようもない絶望の中、次のミッションに取り掛かった。
今回はうまく行ったが次の問題がうまく行くと保証されたわけじゃない。
だが前に進まねばならない。俺が俺でいるために。
人を人たらしめるもの、それが目の前の問題をただがむしゃらに考え生きる、
ということなのだとするならば、あるいは俺も・・・。
そんなことを考えながら、俺は目を閉じ、今日も水玉のスーツに袖を通す。

次回、最終章(発動編)。ブラウザの扉は開くのか?

最後に

ZOZOテクノロジーズでは、一緒にサービスを作成、サポートしてくれるエンジニアを大募集中です。 ご興味のある方は、以下のリンクからぜひご応募ください!

www.wantedly.com

カテゴリー