騰訊出品小程式自動化測試框架【Minium】系列(四)API詳解(上)

久曲健 發表於 2023-01-27
框架 騰訊 自動化測試

寫在前面

不知道是不是因為之前出過書的原因,在寫教程之類的文章,會潛意識有自帶目錄和章節的感覺在裡面,有點說不出的感覺吧。

上篇文章我們介紹了關於元素定位的使用方法,這篇文章將為大家分享關於MiniumMinium、App模組的API 使用。

常用API使用詳解

get_system_info()

獲取系統資訊

shutdown()

測試結束時呼叫, 停止 微信開發者IDE 以及 minium, 並回收資源。一般供測試框架呼叫

screen_shot()

截圖

ide上僅能擷取到wxml頁面的內容,Modal/Actionsheet/授權彈窗等無法擷取

Parameters:

名稱 型別 預設值 說明
save_path str Not None 截圖儲存路徑
format str raw 截圖資料返回格式,raw 或者 pillow

示例程式碼如下:

def test_screen_shot(self):
    """
    截圖操作
    :return:
    """
    output_path = os.path.join(os.path.dirname(__file__), "outputs/test_screen_shot.png")
    print(output_path)
    if not os.path.isdir(os.path.dirname(output_path)):
        os.mkdir(os.path.dirname(output_path))
    if os.path.isfile(output_path):
        os.remove(output_path)
    ret = self.app.screen_shot(output_path)  # 截圖並存到`output_path`資料夾中
    self.assertTrue(os.path.isfile(output_path))

evaluate()

向 app Service 層注入程式碼並執行

真機除錯2.0下, 注入的程式碼只支援es5的語法

Parameters:

名稱 型別 預設值 說明
app_function str Not None 程式碼字串
args list Not None 引數
sync bool False 是否同步執行

Returns:

  • sync == True: dict(result={"result": 函式返回值})
  • sync == False: str(訊息ID)。配合get_async_response用獲取返回值

示例程式碼如下:

import minium

# sync == True
@minium.ddt_class
class TestApp(minium.MiniTest):
    @minium.ddt_case([], ["1", "2"])
    def test_evaluate_sync(self, args):
        result = self.app.evaluate(
            "function(){args=arguments;return 'test evaluate: '.concat(Array.from(args));}", args, sync=True
        )
        self.assertEqual(
            result.get("result", {}).get("result"), "test evaluate: {}".format(",".join(args))
        )

get_async_response()

獲取evaluate方法非同步呼叫的結果

Parameters:

名稱 型別 預設值 說明
msg_id str Not None evaluate返回的訊息ID
timeout int None 等待超時時間,None: 立刻返回

示例程式碼如下:

import minium

# sync == False
@minium.ddt_class
class TestApp(minium.MiniTest):
    @minium.ddt_case([], ["1", "2"])
    def test_evaluate_async(self, args):
        msg_id = self.app.evaluate(
            "function(){args=arguments;return 'test evaluate: '.concat(Array.from(args));}", args, sync=False
        )
        # 你可以做一些其他操作後, 再透過get_async_response方法獲取前面注入程式碼的執行結果
        result = self.app.get_async_response(msg_id, 5)
        self.assertEqual(
            result.get("result", {}).get("result"), "test evaluate: {}".format(",".join(args))
        )

get_all_pages_path()

獲取所有已配置的頁面路徑

Returns:

  • list

示例程式碼如下:

def test_get_all_pages_path(self):
    """
    獲取所有已配置的頁面路徑
    :return:list
    """
    all_pages_path = self.app.get_all_pages_path()
    self.assertListEqual(
        ['page/component/index', 'page/API/index', 'page/cloud/index', 'page/extend/index', 'page/animation/index',
         'packageComponent/pages/view/view/view', 'packageComponent/pages/view/scroll-view/scroll-view',
         'packageComponent/pages/view/swiper/swiper', 'packageComponent/pages/view/movable-view/movable-view',
         'packageComponent/pages/view/cover-view/cover-view', 'packageComponent/pages/content/text/text',
         'packageComponent/pages/content/icon/icon', 'packageComponent/pages/content/progress/progress',
         'packageComponent/pages/content/rich-text/rich-text', 'packageComponent/pages/form/button/button',
         'packageComponent/pages/form/checkbox/checkbox', 'packageComponent/pages/form/form/form',
         'packageComponent/pages/form/input/input', 'packageComponent/pages/form/label/label',
         'packageComponent/pages/form/picker/picker', 'packageComponent/pages/form/picker-view/picker-view',
         'packageComponent/pages/form/radio/radio', 'packageComponent/pages/form/slider/slider',
         'packageComponent/pages/form/switch/switch', 'packageComponent/pages/form/textarea/textarea',
         'packageComponent/pages/form/editor/editor', 'packageComponent/pages/nav/navigator/navigator',
         'packageComponent/pages/nav/navigator/navigate', 'packageComponent/pages/nav/navigator/redirect',
         'packageComponent/pages/media/image/image', 'packageComponent/pages/media/video/video',
         'packageComponent/pages/media/camera/camera', 'packageComponent/pages/media/live-pusher/live-pusher',
         'packageComponent/pages/media/live-player/live-player', 'packageComponent/pages/map/map/map',
         'packageComponent/pages/canvas/canvas-2d/canvas-2d', 'packageComponent/pages/canvas/webgl/webgl',
         'packageComponent/pages/open/ad/ad', 'packageComponent/pages/open/open-data/open-data',
         'packageComponent/pages/open/web-view/web-view',
         'packageComponent/pages/obstacle-free/aria-component/aria-component',
         'packageComponent/pages/doc-web-view/doc-web-view', 'packageAPI/pages/api/login/login',
         'packageAPI/pages/api/get-user-info/get-user-info', 'packageAPI/pages/api/request-payment/request-payment',
         'packageAPI/pages/api/jump/jump', 'packageAPI/pages/api/share/share',
         'packageAPI/pages/api/share-button/share-button', 'packageAPI/pages/api/custom-message/custom-message',
         'packageAPI/pages/api/subscribe-message/subscribe-message',
         'packageAPI/pages/api/choose-address/choose-address',
         'packageAPI/pages/api/choose-invoice-title/choose-invoice-title',
         'packageAPI/pages/api/soter-authentication/soter-authentication', 'packageAPI/pages/api/setting/setting',
         'packageAPI/pages/ar/visionkit-basic/visionkit-basic',
         'packageAPI/pages/ar/visionkit-basic-v2/visionkit-basic-v2', 'packageAPI/pages/ar/plane-ar/plane-ar',
         'packageAPI/pages/ar/plane-ar-v2/plane-ar-v2', 'packageAPI/pages/ar/plane-ar-3dof/plane-ar-3dof',
         'packageAPI/pages/ar/2dmarker-ar/2dmarker-ar', 'packageAPI/pages/ar/3dmarker-ar/3dmarker-ar',
         'packageAPI/pages/ar/osd-ar/osd-ar', 'packageAPI/pages/ar/face-detect/face-detect',
         'packageAPI/pages/ar/body-detect/body-detect', 'packageAPI/pages/ar/hand-detect/hand-detect',
         'packageAPI/pages/ar/ocr-detect/ocr-detect', 'packageAPI/pages/ar/photo-ocr-detect/photo-ocr-detect',
         'packageAPI/pages/ar/photo-hand-detect/photo-hand-detect',
         'packageAPI/pages/ar/photo-body-detect/photo-body-detect',
         'packageAPI/pages/ar/photo-face-detect/photo-face-detect',
         'packageAPI/pages/page/set-navigation-bar-title/set-navigation-bar-title',
         'packageAPI/pages/page/navigation-bar-loading/navigation-bar-loading',
         'packageAPI/pages/page/navigator/navigator', 'packageAPI/pages/page/pull-down-refresh/pull-down-refresh',
         'packageAPI/pages/page/animation/animation', 'packageAPI/pages/page/action-sheet/action-sheet',
         'packageAPI/pages/page/modal/modal', 'packageAPI/pages/page/toast/toast',
         'packageAPI/pages/page/canvas/canvas', 'packageAPI/pages/page/get-wxml-node-info/get-wxml-node-info',
         'packageAPI/pages/page/page-scroll/page-scroll',
         'packageAPI/pages/page/intersection-observer/intersection-observer',
         'packageAPI/pages/device/clipboard-data/clipboard-data', 'packageAPI/pages/device/bluetooth/bluetooth',
         'packageAPI/pages/device/bluetooth/slave/slave',
         'packageAPI/pages/device/screen-brightness/screen-brightness', 'packageAPI/pages/device/vibrate/vibrate',
         'packageAPI/pages/device/add-contact/add-contact', 'packageAPI/pages/device/wifi/wifi',
         'packageAPI/pages/device/get-network-type/get-network-type',
         'packageAPI/pages/device/on-network-status-change/on-network-status-change',
         'packageAPI/pages/device/get-system-info/get-system-info',
         'packageAPI/pages/device/on-compass-change/on-compass-change',
         'packageAPI/pages/device/make-phone-call/make-phone-call', 'packageAPI/pages/device/scan-code/scan-code',
         'packageAPI/pages/device/on-accelerometer-change/on-accelerometer-change',
         'packageAPI/pages/device/capture-screen/capture-screen', 'packageAPI/pages/device/ibeacon/ibeacon',
         'packageAPI/pages/device/get-battery-info/get-battery-info', 'packageAPI/pages/media/image/image',
         'packageAPI/pages/media/voice/voice', 'packageAPI/pages/media/file/file',
         'packageAPI/pages/media/load-font-face/load-font-face',
         'packageAPI/pages/media/background-audio/background-audio', 'packageAPI/pages/media/video/video',
         'packageAPI/pages/media/audio/audio', 'packageAPI/pages/media/media-container/media-container',
         'packageAPI/pages/location/get-location/get-location',
         'packageAPI/pages/location/open-location/open-location',
         'packageAPI/pages/location/choose-location/choose-location', 'packageAPI/pages/network/request/request',
         'packageAPI/pages/network/web-socket/web-socket', 'packageAPI/pages/network/upload-file/upload-file',
         'packageAPI/pages/network/download-file/download-file', 'packageAPI/pages/network/mdns/mdns',
         'packageAPI/pages/network/udp-socket/udp-socket', 'packageAPI/pages/storage/storage/storage',
         'packageAPI/pages/storage/get-background-fetch-data/get-background-fetch-data',
         'packageAPI/pages/storage/get-background-prefetch-data/get-background-prefetch-data',
         'packageAPI/pages/performance/get-performance/get-performance', 'packageAPI/pages/worker/worker/worker',
         'packageAPI/pages/framework/two-way-bindings/two-way-bindings', 'packageAPI/pages/framework/wxs/wxs',
         'packageAPI/pages/framework/resizable/resizable', 'packageAPI/pages/framework/wxs/movable',
         'packageAPI/pages/framework/wxs/sidebar', 'packageAPI/pages/framework/wxs/stick-top',
         'packageAPI/pages/framework/wxs/nearby', 'packageAPI/pages/ai/mobilenet/index',
         'packageAPI/pages/ai/style-trans/index', 'packageCloud/pages/user/user-authentication/user-authentication',
         'packageCloud/pages/database/crud/crud', 'packageCloud/pages/database/db-permission/db-permission',
         'packageCloud/pages/database/server-date/server-date',
         'packageCloud/pages/storage/upload-file/upload-file',
         'packageCloud/pages/storage/download-file/download-file',
         'packageCloud/pages/storage/get-temp-file-url/get-temp-file-url',
         'packageCloud/pages/storage/delete-file/delete-file',
         'packageCloud/pages/storage/cloud-file-component/cloud-file-component',
         'packageCloud/pages/scf/get-wx-context/get-wx-context', 'packageCloud/pages/scf/scf-database/scf-database',
         'packageCloud/pages/scf/scf-storage/scf-storage', 'packageCloud/pages/scf/scf-openapi/scf-openapi',
         'packageExtend/pages/form/cell/cell', 'packageExtend/pages/form/slideview/slideview',
         'packageExtend/pages/form/form/form', 'packageExtend/pages/form/uploader/uploader',
         'packageExtend/pages/base/article/article', 'packageExtend/pages/base/icons/icons',
         'packageExtend/pages/base/badge/badge', 'packageExtend/pages/base/flex/flex',
         'packageExtend/pages/base/footer/footer', 'packageExtend/pages/base/gallery/gallery',
         'packageExtend/pages/base/grid/grid', 'packageExtend/pages/base/loadmore/loadmore',
         'packageExtend/pages/base/loading/loading', 'packageExtend/pages/base/panel/panel',
         'packageExtend/pages/base/preview/preview', 'packageExtend/pages/operate/dialog/dialog',
         'packageExtend/pages/operate/msg/msg', 'packageExtend/pages/operate/msg/msg_success',
         'packageExtend/pages/operate/msg/msg_text', 'packageExtend/pages/operate/msg/msg_text_primary',
         'packageExtend/pages/operate/msg/msg_fail',
         'packageExtend/pages/operate/half-screen-dialog/half-screen-dialog',
         'packageExtend/pages/operate/actionsheet/actionsheet', 'packageExtend/pages/operate/toptips/toptips',
         'packageExtend/pages/navigation/navigation/navigation', 'packageExtend/pages/navigation/tabbar/tabbar',
         'packageExtend/pages/search/searchbar/searchbar', 'packageExtend/pages/extend/emoji/emoji',
         'packageExtend/pages/extend/video-swiper/video-swiper', 'packageExtend/pages/extend/index-list/index-list',
         'packageExtend/pages/extend/recycle-view/recycle-view', 'packageExtend/pages/extend/sticky/sticky',
         'packageExtend/pages/extend/tabs/tabs', 'packageExtend/pages/extend/vtabs/vtabs',
         'packageExtend/pages/extend/barrage/barrage', 'packageExtend/pages/extend/select-text/select-text',
         'packageExtend/pages/extend/wxml-to-canvas/wxml-to-canvas',
         'packageExtend/pages/adapt/telescopic/telescopic', 'packageExtend/pages/adapt/linebreak/linebreak',
         'packageExtend/pages/adapt/sidenavigation/sidenavigation',
         'packageExtend/pages/adapt/pagination/pagination', 'packageExtend/pages/adapt/freelayout/freelayout',
         'packageExtend/pages/adapt/layeredpresentation/layeredpresentation',
         'packageExtend/pages/adapt/horizontalexpansion/horizontalexpansion',
         'packageSkyline/pages/worklet/animation/index', 'packageSkyline/pages/worklet/gesture/index',
         'packageSkyline/pages/worklet/bottom-sheet/index', 'packageSkyline/pages/share-element/list/index',
         'packageSkyline/pages/share-element/card/index', 'packageSkyline/pages/half-page/scale-page/index',
         'packageSkyline/pages/half-page/half-page/index', 'packageSkyline/pages/address-book/index',
         'packageSkyline/pages/half-screen/index', 'packageSkyline/pages/tabs/index',
         'packageSkyline/pages/album/index', 'packageSkyline/pages/preview/index',
         'packageSkyline/pages/custom-route/index', 'packageSkyline/pages/custom-route/detail',
         'packageSkyline/pages/scroll-view/index', 'packageXRFrame/pages/index/index',
         'packageXRFrame/pages/scene-basic/index', 'packageXRFrame/pages/scene-basic-light/index',
         'packageXRFrame/pages/scene-basic-animation/index', 'packageXRFrame/pages/scene-basic-particle/index',
         'packageXRFrame/pages/scene-basic-touch/index', 'packageXRFrame/pages/scene-basic-visible-layer/index',
         'packageXRFrame/pages/scene-basic-shadow/index', 'packageXRFrame/pages/scene-basic-video/index',
         'packageXRFrame/pages/scene-basic-render-texture/index',
         'packageXRFrame/pages/scene-basic-postprocessing/index',
         'packageXRFrame/pages/scene-gltf-damageHelmet/index', 'packageXRFrame/pages/scene-gltf-unlit/index',
         'packageXRFrame/pages/scene-gltf-animation/index', 'packageXRFrame/pages/scene-gltf-morph/index',
         'packageXRFrame/pages/scene-gltf-light-loading/index', 'packageXRFrame/pages/scene-ar-basic/index',
         'packageXRFrame/pages/scene-ar-2dmarker/index', 'packageXRFrame/pages/scene-ar-osdmarker/index',
         'packageXRFrame/pages/scene-ar-camera/index', 'packageXRFrame/pages/scene-ar-face/index',
         'packageXRFrame/pages/scene-ar-hand/index', 'packageXRFrame/pages/scene-ar-body/index',
         'packageXRFrame/pages/scene-custom-logic/index', 'packageXRFrame/pages/scene-custom-render/index',
         'packageXRFrame/pages/scene-scan-render/index', 'packageXRFrame/pages/scene-scan-team/index',
         'packageXRFrame/pages/scene-classic-wxball/index', 'packageXRFrame/pages/scene-classic-video/index',
         'packageXRFrame/pages/scene-classic-perspect/index', 'packageXRFrame/pages/scene-classic-portal/index',
         'packageXRFrame/pages/scene-classic-osd/index', 'packageXRFrame/pages/scene-classic-face/index',
         'packageXRFrame/pages/scene-last-record/index'],
        all_pages_path,
        "test ok",
    )

get_current_page()

獲取當前頂層頁面

Returns:

  • 頁面物件

示例程式碼如下:

import minium


class AppTest(minium.MiniTest):
    def test_get_current_page(self):
        page = self.app.get_current_page()  # 同self.app.current_page
        self.assertIsNotNone(page.path)
        self.assertNotEqual("", page.path)
        print(page.path)

go_home()

跳轉到小程式首頁

示例程式碼如下:

def test_go_home(self):
    """
    跳轉到小程式首頁
    :return: 
    """
    self.page.get_element("view", inner_text="檢視容器").click()
    self.page.get_element("navigator", inner_text="view").click()
    # 跳轉到小程式首頁
    self.app.go_home()

以導航的方式跳轉到指定頁面

不能跳到 tabbar 頁面。支援相對路徑和絕對路徑, 小程式中頁面棧最多十層

Parameters:

名稱 型別 預設值 說明
url str Not None 頁面路徑
params dict None 頁面引數
is_wait_url_change bool True 是否等待新的頁面跳轉

個人感覺就是跳轉到指定頁面,也可以理解為導航欄上的超連結帶路徑那種的

示例程式碼如下:

def test_navigate_to(self):
    """
    跳轉到指定頁面
    :return:
    """
    pass_page = self.app.get_current_page()
    self.app.navigate_to("/packageComponent/pages/view/view/view")

關閉當前頁面,返回上一頁面

示例程式碼如下:

def test_navigate_to(self):
    """
    返回上一頁
    :return:
    """
    pass_page = self.app.get_current_page()
    # 跳轉到指定頁面
    self.app.navigate_to("/packageComponent/pages/view/view/view")
    # 返回上一頁
    self.app.navigate_back()

redirect_to()

關閉當前頁面,重定向到應用內的某個頁面

不允許跳轉到 tabbar 頁面

Parameters:

名稱 型別 預設值 說明
url str Not None 頁面路徑
params dict None 頁面引數
is_wait_url_change bool True 是否等待新的頁面跳轉

個人感覺同navigate_to()用法很像,各種細節感興趣的同學可以自行嘗試。

示例程式碼如下:

def redirect_to(self):
    """
    重定向到指定頁面
    :return:
    """
    # 重定向到指定頁面
    self.app.redirect_to("/packageComponent/pages/view/view/view")

relaunch()

關閉所有頁面,開啟到應用內的某個頁面

Parameters:

名稱 型別 預設值 說明
url str Not None 頁面路徑

示例程式碼如下:

def test_relaunch(self):
    """
    關閉所有頁面,開啟到應用內的某個頁面
    :return:
    """
    pass_page = self.app.get_current_page()
    # 重定向到指定頁面
    self.app.redirect_to("/packageComponent/pages/view/view/view")
    # 關閉所有頁面,開啟到應用內的某個頁面
    self.app.relaunch("/packageComponent/pages/view/movable-view/movable-view")

switch_tab()

跳轉到 tabBar 頁面

會關閉其他所有非tabBar頁面

Parameters:

名稱 型別 預設值 說明
url str Not None 需要跳轉的 tabBar 頁面的路徑(需在 app.json 的 tabBar 欄位定義的頁面),路徑後不能帶引數
is_click bool False 切換tab的時候觸發一次onTabItemTap

示例程式碼如下:

def switch_tab(self):
    """
    跳轉到 tabBar 頁面
    :return:
    """
    pass_page = self.app.get_current_page()
    print(pass_page)
    # 重定向到指定頁面
    self.app.redirect_to("/packageComponent/pages/view/view/view")
    # 關閉所有頁面,開啟到應用內的某個頁面
    self.app.relaunch("/packageComponent/pages/view/movable-view/movable-view")
    # 跳轉到 tabBar 頁面
    self.app.switch_tab("/page/API/index")

什麼是tabbar頁面?

舉個例子,比如我們小程式的底部有圖示加文字的幾個按鈕,每個按鈕對應一個頁面,而整個小程式中有很多頁面,小程式底部圖示加文字對應的幾個頁面是tabbar頁面,這個在app.json中有設定。
eg:在app.json中設定對應的tabbar頁面

"tabBar": {
    "color": "#333",
    "selectedColor": "#d43c33",
    "backgroundColor": "#fff",
    "position": "bottom",
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "主頁",
        "iconPath": "/static/images/tabs/tab-home.png",
        "selectedIconPath": "/static/images/tabs/tab-home-current.png"
      },
      {
        "pagePath": "pages/video/video",
        "text": "影片",
        "iconPath": "/static/images/tabs/select.png",
        "selectedIconPath": "/static/images/tabs/selected.png"
      },
      {
        "pagePath": "pages/personal/personal",
        "text": "個人中心",
        "iconPath": "/static/images/tabs/tab-my.png",
        "selectedIconPath": "/static/images/tabs/tab-my-current.png"
      }
    ]
  }

get_perf_time()

查詢小程式的效能指標,跟stop_get_perf_time配對使用

Parameters:

名稱 型別 預設值 說明
entry_types list Not None 可選項為['render', 'script', 'navigation', 'loadPackage']中的1個或多個

stop_get_perf_time()

結束查詢,跟get_perf_time配對使用

示例程式碼如下:

def test_get_perf_time(self):
    """
    查詢小程式的效能指標
    :return:
    """
    self.app.get_perf_time(entry_types=["navigation"])
    self.app.navigate_to("/packageComponent/pages/view/view/view")
    self.app.redirect_to("/packageComponent/pages/view/movable-view/movable-view")
    perf_data = self.app.stop_get_perf_time()
    print(perf_data)

可以看到一些路徑跳轉的耗時,結果如下:

[{
	'entryType': 'navigation',
	'name': 'route',
	'startTime': 1674803063419,
	'duration': 387,
	'navigationType': 'navigateTo',
	'path': 'packageComponent/pages/view/view/view',
	'pageId': 53,
	'referrerPath': 'page/component/index',
	'referrerPageId': 52,
	'navigationStart': 1674803063575
}, {
	'entryType': 'render',
	'name': 'firstRender',
	'startTime': 1674803063575,
	'duration': 74,
	'path': 'packageComponent/pages/view/view/view',
	'pageId': 53,
	'viewLayerReadyTime': 1674803063618,
	'initDataSendTime': 1674803063603,
	'initDataRecvTime': 1674803063619,
	'viewLayerRenderStartTime': 1674803063619,
	'viewLayerRenderEndTime': 1674803063646
}, {
	'entryType': 'render',
	'name': 'firstPaint',
	'startTime': 1674803063583,
	'path': 'packageComponent/pages/view/view/view',
	'pageId': 53
}, {
	'entryType': 'render',
	'name': 'firstContentfulPaint',
	'startTime': 1674803063667,
	'path': 'packageComponent/pages/view/view/view',
	'pageId': 53
}, {
	'entryType': 'render',
	'name': 'largestContentfulPaint',
	'startTime': 1674803063667,
	'path': 'packageComponent/pages/view/view/view',
	'pageId': 53
}, {
	'entryType': 'navigation',
	'name': 'route',
	'startTime': 1674803063419,
	'duration': 387,
	'navigationType': 'navigateTo',
	'path': 'packageComponent/pages/view/view/view',
	'pageId': 53,
	'referrerPath': 'page/component/index',
	'referrerPageId': 52,
	'navigationStart': 1674803063575
}, {
	'entryType': 'render',
	'name': 'firstRender',
	'startTime': 1674803063575,
	'duration': 74,
	'path': 'packageComponent/pages/view/view/view',
	'pageId': 53,
	'viewLayerReadyTime': 1674803063618,
	'initDataSendTime': 1674803063603,
	'initDataRecvTime': 1674803063619,
	'viewLayerRenderStartTime': 1674803063619,
	'viewLayerRenderEndTime': 1674803063646
}, {
	'entryType': 'render',
	'name': 'firstPaint',
	'startTime': 1674803063583,
	'path': 'packageComponent/pages/view/view/view',
	'pageId': 53
}, {
	'entryType': 'render',
	'name': 'firstContentfulPaint',
	'startTime': 1674803063667,
	'path': 'packageComponent/pages/view/view/view',
	'pageId': 53
}, {
	'entryType': 'render',
	'name': 'largestContentfulPaint',
	'startTime': 1674803063667,
	'path': 'packageComponent/pages/view/view/view',
	'pageId': 53
}, {
	'entryType': 'navigation',
	'name': 'route',
	'startTime': 1674803063419,
	'duration': 387,
	'navigationType': 'navigateTo',
	'path': 'packageComponent/pages/view/view/view',
	'pageId': 53,
	'referrerPath': 'page/component/index',
	'referrerPageId': 52,
	'navigationStart': 1674803063575
}, {
	'entryType': 'navigation',
	'name': 'route',
	'startTime': 1674803063874,
	'duration': 680,
	'navigationType': 'redirectTo',
	'path': 'packageComponent/pages/view/movable-view/movable-view',
	'pageId': 54,
	'referrerPath': 'packageComponent/pages/view/view/view',
	'referrerPageId': 53,
	'navigationStart': 1674803064353
}, {
	'entryType': 'render',
	'name': 'firstRender',
	'startTime': 1674803064353,
	'duration': 71,
	'path': 'packageComponent/pages/view/movable-view/movable-view',
	'pageId': 54,
	'viewLayerReadyTime': 1674803064393,
	'initDataSendTime': 1674803064367,
	'initDataRecvTime': 1674803064375,
	'viewLayerRenderStartTime': 1674803064394,
	'viewLayerRenderEndTime': 1674803064421
}, {
	'entryType': 'render',
	'name': 'firstPaint',
	'startTime': 1674803064358,
	'path': 'packageComponent/pages/view/movable-view/movable-view',
	'pageId': 54
}, {
	'entryType': 'render',
	'name': 'firstContentfulPaint',
	'startTime': 1674803064425,
	'path': 'packageComponent/pages/view/movable-view/movable-view',
	'pageId': 54
}, {
	'entryType': 'render',
	'name': 'largestContentfulPaint',
	'startTime': 1674803064425,
	'path': 'packageComponent/pages/view/movable-view/movable-view',
	'pageId': 54
}, {
	'entryType': 'navigation',
	'name': 'route',
	'startTime': 1674803063874,
	'duration': 680,
	'navigationType': 'redirectTo',
	'path': 'packageComponent/pages/view/movable-view/movable-view',
	'pageId': 54,
	'referrerPath': 'packageComponent/pages/view/view/view',
	'referrerPageId': 53,
	'navigationStart': 1674803064353
}, {
	'entryType': 'render',
	'name': 'firstRender',
	'startTime': 1674803064353,
	'duration': 71,
	'path': 'packageComponent/pages/view/movable-view/movable-view',
	'pageId': 54,
	'viewLayerReadyTime': 1674803064393,
	'initDataSendTime': 1674803064367,
	'initDataRecvTime': 1674803064375,
	'viewLayerRenderStartTime': 1674803064394,
	'viewLayerRenderEndTime': 1674803064421
}, {
	'entryType': 'render',
	'name': 'firstPaint',
	'startTime': 1674803064358,
	'path': 'packageComponent/pages/view/movable-view/movable-view',
	'pageId': 54
}, {
	'entryType': 'render',
	'name': 'firstContentfulPaint',
	'startTime': 1674803064425,
	'path': 'packageComponent/pages/view/movable-view/movable-view',
	'pageId': 54
}, {
	'entryType': 'render',
	'name': 'largestContentfulPaint',
	'startTime': 1674803064425,
	'path': 'packageComponent/pages/view/movable-view/movable-view',
	'pageId': 54
}, {
	'entryType': 'navigation',
	'name': 'route',
	'startTime': 1674803063874,
	'duration': 680,
	'navigationType': 'redirectTo',
	'path': 'packageComponent/pages/view/movable-view/movable-view',
	'pageId': 54,
	'referrerPath': 'packageComponent/pages/view/view/view',
	'referrerPageId': 53,
	'navigationStart': 1674803064353
}]

wait_for_page()

等待頁面跳轉成功

Parameters:

名稱 型別 預設值 說明
page_path str Not None 需要等待的頁面路徑, 需要絕對路徑, 如/pages/index

示例程式碼如下:

def test_wait_for_page(self):
    """
    等待頁面跳轉成功
    :return:布林型別
    """
    self.page.get_element("view",inner_text='表單元件').click()
    el = self.app.current_page.get_element('navigator',inner_text='button')
    el.tap()
    current_page=self.app.get_current_page()
    time.sleep(3)
    print(current_page)
    ret = self.app.wait_for_page("/packageComponent/pages/form/button/button")
    print(ret)
    self.assertTrue(ret, "wait success")
    self.assertEqual(self.app.current_page.path, "/packageComponent/pages/form/button/button", "path ok")

wait_util()

指定時間內, 剩餘沒有完成的非同步請求數 <= {cnt}個, 此時認為頁面非同步載入完成

Parameters:

名稱 型別 預設值 說明
cnt int Not None 剩餘的非同步請求個數
max_timeout int 10 最大等待時間

示例程式碼如下:

def test_wait_util(self):
    """
    確定指定時間內, 非同步請求是否完成的
    :return:布林型別
    """
    self.page.get_element("view",inner_text='表單元件').click()
    el = self.app.current_page.get_element('navigator',inner_text='button')
    el.tap()
    ret = self.app.wait_util(0, 5)  # 5s內, 頁面沒有任何未完成的非同步請求
    self.assertTrue(ret, "wait success")

寫在最後

關於Minium介面中minium、App部分的APi已經介紹完畢,這兩個模組中部分Api沒做分享感興趣的同學可以到官方文章自行檢視。

仔細看了下API部分還真不少,下篇文章會為大家分享PageElement這兩個模組的Api,感興趣的同學可以蹲一下,建議收藏,也請星標我的公號(軟體測試君),並幫忙轉發給你更多的人,我需要你的支援,謝謝!