從零開始玩轉 PerfDogService Demo解析篇

騰訊WeTest發表於2020-11-10

1.Demo資料夾

當下載好PerfDogService後資料夾是這個樣子的。

從零開始玩轉 PerfDogService Demo解析篇


檔案說明:

PerfDogService.exe: Service啟動檔案,一般不用手工啟動,自動化指令碼會自動啟動此程式。
perfdog.proto: grpc介面和protobuf結構體的定義檔案
demo/python: python3的demo,依賴庫grpcio和protobuf
demo/java: java的demo,依賴庫grpc-netty-shaded, grpc-protobuf, grpc-stub
PerfDogService.jar: 服務所依賴的jar包

我們先不管其他,只專注於demo資料夾;
展開後是Java和Python兩種語言的Demo,我們本次只分析改造Python的

從零開始玩轉 PerfDogService Demo解析篇


Python的Demo只有三個檔案

從零開始玩轉 PerfDogService Demo解析篇


Demo.py: 我們程式的執行入口,同時我們主要操作的也是這個檔案;
perfdog_pb2.py: 此檔案是由協議緩衝區編譯器生成,也就是由perfdog.proto這個檔案生成的。我們不要修改它。
perfdog_pb2_grpc.py: 此檔案是gRPC Python協議編譯器外掛生成,也不要修改它
這裡簡單介紹下==協議緩衝區==
協議緩衝區是是一種與語言無關,平臺無關的資料序列化結構化機制;
只需要一次構造資料,然後就可以使用生成的特殊原始碼輕鬆地使用各種語言在各種資料流中寫入和讀取結構化資料;

從零開始玩轉 PerfDogService Demo解析篇


你用python語言,你辛辛苦苦用python定義好了一堆字典啦或者Class啦或者其他什麼資料,你想給隔壁老李用,然而老李用java啊,這時候隔壁小王也需要用,然而小王用C++啊,各種語言不能直接呼叫。這個時候透過協議緩衝區這種機制,先把你的資料編譯生成一種特殊的原始碼,老李和小王就可以呼叫這份原始碼了。

2.Demo.py檔案解析

從零開始玩轉 PerfDogService Demo解析篇

其實全篇只有一個Run函式,而且官方寫的註釋也比較清晰了,我們就來簡單看下吧

從零開始玩轉 PerfDogService Demo解析篇


0到3其實沒什麼好說的了,就是喚起PerfDogService服務,透過令牌和伺服器建立了一個連線,其中stub除了建立連線還有好多其他的方法

從零開始玩轉 PerfDogService Demo解析篇


接下來看看第四步

從零開始玩轉 PerfDogService Demo解析篇

deviceEventIterator這裡是一個可迭代物件,存放著當前所有的連線裝置,例如Android啦,Ios,模擬器啦等等;
從零開始玩轉 PerfDogService Demo解析篇


我們最常用的應該是device,這裡儲存著被測機型的uid,名字等。這裡的uid就是當前連線裝置的唯一標識,如果你安裝了ADB,可以在控制檯輸入ADB devices檢視你當期連線的裝置資訊,例如這樣:

從零開始玩轉 PerfDogService Demo解析篇


5其實就是開始初始化裝置
6是開始獲取當前被測裝置的所有安裝的應用,應用儲存在apps這個物件裡,這也是一個可迭代物件,
迭代apps可以獲取到每個app,以及每個app的名字,包名,版本,Icon,是不是系統App,subVersion等等。

從零開始玩轉 PerfDogService Demo解析篇

第7步這裡實際上是獲取了當前被測裝置的硬體資訊,例如像CPU,型號,安卓版本之類的等等

從零開始玩轉 PerfDogService Demo解析篇


第8步這裡開始選擇要蒐集的效能資料指標都有哪些,我這裡多加了一個CPU Core的使用率
第9步就開始蒐集效能資料了

從零開始玩轉 PerfDogService Demo解析篇


採集效能資料資訊實際上透過多執行緒的方式進行的,所以Sleep(20)就是採集20s的資料

從零開始玩轉 PerfDogService Demo解析篇


10和11就是新增不同時間段的註釋

從零開始玩轉 PerfDogService Demo解析篇


第12步是兩個操作
1.上傳整個資料到雲端
2.匯出第5秒到20秒的資料到本地,其中匯出路徑可以自己更改(outputDirectory)

從零開始玩轉 PerfDogService Demo解析篇


13最後停止測試,不過其實程式沒停止,如果此時你啟動Perfdog客戶端,可能會顯示這個錯誤。

從零開始玩轉 PerfDogService Demo解析篇


此時去Kill掉這個java進城就可以了。

從零開始玩轉 PerfDogService Demo解析篇

3.Demo簡單修改

由於我個人的需求1是不想每次配置都挨行程式碼修改,2是為後續搭建自定義的雲效能測試平臺做鋪墊,所以簡單修改了下程式碼:原始碼未刪,僅是註釋掉了,方便做對比;
1.提取常用配置
2.需要提前配置好需要測試的對應裝置
3.需要提前配置好要測試的APP(配置APP的名字)
4.只上傳一份資料到雲端,
5.儲存到本地的資料不會從中間擷取某段時間了。

# -*- coding: utf-8 -*-import subprocess
import timeimport traceback
import grpc
import perfdog_pb2_grpc
import perfdog_pb2
import threading
class Config():
    PERFDOGSERVER_PATH=r'C:\Users\Administrator\Desktop\perfdog\PerfDogService.exe' #PerfDogService的路徑
    TOKEN='XXXXXXXXXXXXXXXXXXXX '#token
    DEVICES_UID="813QEDTE228ZK" #需要測試的手機序列號
    APP_NAME="天氣" #需要測試的app名字
    TEST_TIMER=11 #需要測試時長
    LABEL="this is a label" #label內容
    NOTE="this is a note" #note內容
    CASENAME="天氣測試資料" #用例描述 ,會覆蓋相同用例名字的資料
    SAVEDATA_BEGINTIME=1 #匯出到本地資料的開始時間(秒)
    SAVEDATA_ENDTIME=20 #匯出到本地資料的結束時間(秒)
    OUTPUT="F:\\perfdog_service_output\\" #匯出檔案所儲存的目錄,
    SAVEDATA_TYPE=perfdog_pb2.EXPORT_TO_JSON #匯出檔案所儲存的型別,# 第一次執行demo前需要透過pip安裝grpcio(1.23.0)和protobuf(3.10.0)def run():
    try:        # 在程式碼裡啟動PerfDogService或手動啟動PerfDogService
        print("0.啟動PerfDogService")        # 1.**************************填入PerfDogService的路徑
        perfDogService = subprocess.Popen(Config.PERFDOGSERVER_PATH)        # 等待PerfDogService啟動完畢
        time.sleep(5)        print("1.透過ip和埠連線到PerfDog Service")
        options = [('grpc.max_receive_message_length', 100 * 1024 * 1024)]
        channel = grpc.insecure_channel('127.0.0.1:23456', options=options)        print("2.新建一個stub,透過這個stub物件可以呼叫所有伺服器提供的介面")
        stub = perfdog_pb2_grpc.PerfDogServiceStub(channel)        print("3.透過令牌登入,令牌可以在官網申請")
        userInfo = stub.loginWithToken(perfdog_pb2.Token(token=Config.TOKEN))        print("UserInfo:\n", userInfo)        print("4.啟動裝置監聽器監聽裝置,每當裝置插入和移除時會收到一個DeviceEvent")
        deviceEventIterator = stub.startDeviceMonitor(perfdog_pb2.Empty())        for deviceEvent in deviceEventIterator:            # 從DeviceEvent中獲取到device物件,device物件會在後面的介面中用到
            device = deviceEvent.device            print("當前devices: ",device," **** ",deviceEvent)            # time.sleep(20000)
            if deviceEvent.eventType == perfdog_pb2.ADD and device.uid==Config.DEVICES_UID:                print("裝置[%s:%s]插入\n" % (device.uid, perfdog_pb2.DEVICE_CONTYPE.Name(device.conType)))                # 每臺手機會返回兩個conType不同的裝置物件(USB的和WIFI的),如果是測有線,取其中的USB物件
                if device.conType == perfdog_pb2.USB:                    print("5.初始化裝置[%s:%s]\n" % (device.uid, perfdog_pb2.DEVICE_CONTYPE.Name(device.conType)))
                    stub.initDevice(device)                    print("6.獲取app列表")
                    appList = stub.getAppList(device)                    #
                    apps = appList.app
                    app_index = 0
                    for app in apps:                        print('%s: %s->%s' % (app_index, app.label, app.packageName))                        if app.label==Config.APP_NAME:
                            app_select=app_index                            break
                        else:
                            app_index += 1
                            app_select=None                    if app_select is None:app_select = int(input("未安裝輸入APP,請選擇要測試App: "))
                    app = apps[app_select]                    print("7.獲取裝置的詳細資訊")
                    deviceInfo = stub.getDeviceInfo(device)                    print("8.開啟效能資料項")
                    stub.enablePerfDataType(
                        perfdog_pb2.EnablePerfDataTypeReq(device=device, type=perfdog_pb2.NETWORK_USAGE))
                    stub.enablePerfDataType(
                        perfdog_pb2.EnablePerfDataTypeReq(device=device, type=perfdog_pb2.NORMALIZED_CPU_CORE_USAGE))                    print("9.開始收集[%s:%s]的效能資料\n" % (app.label, app.packageName))                    print(stub.startTestApp(perfdog_pb2.StartTestAppReq(device=device, app=app)))
                    req = perfdog_pb2.OpenPerfDataStreamReq(device=device)
                    perfDataIterator = stub.openPerfDataStream(req)
                    def perf_data_process():                        for perfData in perfDataIterator:                            print(perfData)
                    threading.Thread(target=perf_data_process).start()                    # 採集一些資料
                    time.sleep(Config.TEST_TIMER)                    print("10.設定label")
                    stub.setLabel(perfdog_pb2.SetLabelReq(device=device, label="I am a label"))
                    time.sleep(3)                    print("11.新增批註")
                    stub.addNote(perfdog_pb2.AddNoteReq(device=device, time=5000, note="I am a note"))                    print("12.上傳和匯出所有資料")
                    saveResult = stub.saveData(perfdog_pb2.SaveDataReq(
                        device=device,
                        caseName=Config.CASENAME,  # web上case和excel的名字
                        uploadToServer=True,  # 上傳到perfdog伺服器
                        exportToFile=True,  # 儲存到本地
                        outputDirectory=Config.OUTPUT,
                        dataExportFormat=Config.SAVEDATA_TYPE
                    ))                    print("儲存結果:\n", saveResult)                    # print("12.上傳和匯出第5秒到20秒的資料")
                    # stub.saveData(perfdog_pb2.SaveDataReq(
                    #     device=device,
                    #     beginTime=5000,  # 指定開始時間
                    #     endTime=20000,  # 指定結束時間
                    #     caseName="case2",  # web上case和excel的名字
                    #     uploadToServer=True,  # 上傳到perfdog伺服器
                    #     exportToFile=True,  # 儲存到本地
                    #     outputDirectory="F:\\perfdog_service_output\\",
                    #     dataExportFormat=perfdog_pb2.EXPORT_TO_EXCEL
                    # ))
                    print("13.停止測試")
                    stub.stopTest(perfdog_pb2.StopTestReq(device=device))                    print("over")                    break
                elif deviceEvent.eventType == perfdog_pb2.REMOVE:                    print("裝置[%s:%s]移除\n" % (device.uid, perfdog_pb2.DEVICE_CONTYPE.Name(device.conType)))
    except Exception as e:
                traceback.print_exc()if __name__ == '__main__':
    run()#

效能測試技術交流群:720150565

檢視PerfDog詳情:https://perfdog.qq.com/?ADTAG=media.dev_website


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31420651/viewspace-2733262/,如需轉載,請註明出處,否則將追究法律責任。

相關文章