Android 查看客户端转储CPU使用情况

Android 查看客户端转储CPU使用情况,android,view,android-testing,androidviewclient,Android,View,Android Testing,Androidviewclient,我通过Python使用Android View Client dump()从Android设备上获取视图,以验证我正在测试的应用程序的视图。我正试图修复其他人的测试代码,所以有些东西实现得并不理想。自动测试的设计方法是导航到每个屏幕,执行视图转储,等待转储发生几秒钟,然后验证该转储与视图应该是什么。如果不一样,他们会等待几秒钟,然后调用一个新的转储。(等待是为了让dump()方法有足够的时间完全执行。)这种转储导致Android View客户端的CPU使用量达到了荒谬的程度(约65-80%)。对

我通过Python使用Android View Client dump()从Android设备上获取视图,以验证我正在测试的应用程序的视图。我正试图修复其他人的测试代码,所以有些东西实现得并不理想。自动测试的设计方法是导航到每个屏幕,执行视图转储,等待转储发生几秒钟,然后验证该转储与视图应该是什么。如果不一样,他们会等待几秒钟,然后调用一个新的转储。(等待是为了让dump()方法有足够的时间完全执行。)这种转储导致Android View客户端的CPU使用量达到了荒谬的程度(约65-80%)。对于如何减少CPU的使用,有人有什么建议吗

我希望仍然使用dump()方法,但可能以前的程序员实现的轮询循环并不理想?他们基本上只是保持轮询,直到发生了一定数量的转储,或者出现了他们正在搜索的视图

如果有一个不同的方法来验证用户界面以及我愿意切换

如有任何建议,将不胜感激。谢谢

(以下是测试代码片段)

def tap_nfc(自身、,
预期的_视图=无,
post_tap_wait=True,
post_tap_alert=无,
原始视图=无,
失败的\u视图=(('text',views.TAP\u FAILURE),),
in_progress_views=(('id',views.TAP_in_progress_id)),
超时按钮=无,
关闭应用程序=错误,
秒=7,
试验次数=5次):
通过打开和关闭NFC,将设备“点击”到相邻的NFC读卡器。
验证预期视图是否在给定的#秒或两个视图内出现
倾倒。NFC阅读器挑剔时可选重试。在找到预期的视图之后,
结束水龙头,等待他们退出。
Args:
预期视图:在给定视图中应可见的可选视图列表或目录
轻敲时间,但轻敲结束后该时间将消失。他们的存在
如果未找到,则断言,当找到时,抽头结束。
格式:[('text',re.compile('sample_text')),
('id','sample_id'),…]
或{'sample_id':'associated_text',…}
默认值:无。
post_tap_wait:可选布尔值,用于确定是否应在以下情况下执行post tap wait:
期望期望的视图自动关闭它们自己。
默认值:True
post_tap_alert:表示要断言的警报的Dict在tap结束后存在。
默认值:无
原始视图:点击前可见的可选视图列表-用于
确定NFC是否完全无法沟通,因为这些观点应该
如果检测到敲击,则立即消失。
默认值:无。
failed_views(失败的视图):可选的视图列表,用于指示操作失败
除NFC连接不良以外的其他原因。
默认值:[('text',uitestview.TAP_FAILURE)]
in_progress_views:可选的视图列表,用于查看点击是否仍处于打开状态
进步。用于检查连接是否中途挂起,是否应重试。
默认值:[('id',uitestview.TAP\u IN\u PROGRESS\u id)]
超时按钮:按顺序按下以重试点击的可选按钮列表
尝试超时-每个格式为(类型、标识符)
默认值:无
关闭应用程序:如果为真,请确保在每次点击尝试之前关闭应用程序。默认为False。
秒数:在断言失败之前搜索预期视图的最小秒数。
默认7。
尝试次数:在找到预期视图之前,可执行的最大点击次数。
'''
timeout\u msg\u dict={Views.msg\u TITLE\u ID:Views.TAP\u timeout\u msg\u TITLE,
Views.MSG\u ID:Views.TAP\u TIMEOUT\u MSG}
timeout\u views=[('text',x)表示timeout\u msg\u dict.values()中的x
#如果预期的_视图以警报(id字典:文本对)的形式传递,请添加它
#在转储视图时添加到允许的警报
允许的\u警报=[超时\u消息\u命令]
如果isinstance(预期视图,dict):
允许的\u警报。追加(预期的\u视图)
如果post_tap_警报不是无:
允许的警报。追加(发布警报)
def句柄_超时_消息():
''如果检测到超时消息,请处理它并返回true,如果未处理,则返回fail。
如果未检测到超时消息,则返回False。
'''
self.device.shell(“svc nfc禁用”)#确保nfc已关闭
如果超时按钮不是无:
#按我们被告知的顺序按每个按钮
对于按钮类型,超时按钮中的按钮标识符:
self.touchOrRaise(按钮类型、按钮标识符、转储延迟=0.5)
其他:
self.fail('点击尝试超时且未提供超时处理')
def句柄\预期的\视图():
''处理预期视图的外观。除非另有说明,否则请等待
当NFC关闭时,他们会自动解散。
'''
如果post_点击_等待:
如果post_tap_警报不是无:
允许的警报=[发布警报]
其他:
允许的\u警报=无
视图\u转储=0
开始时间=time.time()
而self.viewSexister(预期视图):
self.assertOrDump(time.time()-开始时间<7或查看转储<2,
'点击成功屏幕花费的时间太长,无法自行关闭:')
self.dump\u raise\u警报(允许的警报=允许的警报)
视图_转储+=1
如果post_tap_警报不是无:
#允许在此重试一次,以避免在重试之前被抓到一个空白屏幕
def tap_nfc(self,
            expected_views=None,
            post_tap_wait=True,
            post_tap_alert=None,
            original_views=None,
            failed_views=(('text', Views.TAP_FAILURE),),
            in_progress_views=(('id', Views.TAP_IN_PROGRESS_ID),),
            timeout_buttons=None,
            close_app=False,
            seconds=7,
            tries=5):
    ''' 'Tap' the device to an adjacent NFC Reader by turning NFC on and off.
    Verify that the expected views appear within the given # of seconds or within two view
    dumps. Optional retries in case NFC reader is finicky. After finding the expected views,
    end the tap and wait for them to dismiss themselves.
    Args:
      expected_views: Optional list or dict of views that should become visible within the given
              time of tapping, but that will disappear after the tap is ended. Their existence
              is asserted if not found, and when found the tap is ended.
              Format: [('text', re.compile('sample_text')),
                       ('id', 'sample_id'), ...]
                      or { 'sample_id': 'associated_text', ...}
              Default: None.
      post_tap_wait: Optional boolean to determine if a post tap wait should be performed that
              expects the expected views to automatically dismiss themselves.
              Default: True
      post_tap_alert: Dict representing an alert to assert exists after the tap has ended.
              Default: None
      original_views: Optional list of views that are visible before the tap - used to
              determine if the NFC has failed to communicate at all, since those views should
              immediately disappear if a tap was detected.
              Default: None.
      failed_views: Optional list of views that will indicate that the operation failed for a
              reason other than a bad NFC connection.
              Default: [('text', UITestViews.TAP_FAILURE)]
      in_progress_views: Optional list of views to expect to see if the tap is still in
              progress. Used to check if the connection hung mid-way and should be retried.
              Default: [('id', UITestViews.TAP_IN_PROGRESS_ID)]
      timeout_buttons: Optional list of buttons to press in sequence in order to retry a tap
              attempt that timed out - each formatted as (type, identifier)
              Default: None
      close_app: If True, make sure the app is closed before each tap attempt. Default False.
      seconds: minimum # of seconds to search for the expected views before asserting failure.
              Default 7.
      tries: maximum # of tap attempts to perform until expected views are found.
    '''
    timeout_msg_dict = {Views.MSG_TITLE_ID: Views.TAP_TIMEOUT_MSG_TITLE,
                        Views.MSG_ID: Views.TAP_TIMEOUT_MSG}
    timeout_views = [('text', x) for x in timeout_msg_dict.values()]

    # if expected_views is passed in the form of an alert (dictionary of id:text pairs), add it
    # to the allowed alerts when dumping views
    allowed_alerts = [timeout_msg_dict]
    if isinstance(expected_views, dict):
        allowed_alerts.append(expected_views)
    if post_tap_alert is not None:
        allowed_alerts.append(post_tap_alert)

    def handle_timeout_message():
        '''If timeout message detected, handle it and return true, or fail if unhandled.
        If no timeout message detected, return False.
        '''
        self.device.shell('svc nfc disable') # Make sure NFC is off
        if timeout_buttons is not None:
            # Hit each button in sequence that we were told of
            for button_type, button_identifier in timeout_buttons:
                self.touchOrRaise(button_type, button_identifier, dump_delay=0.5)
        else:
            self.fail('TAP ATTEMPT TIMED OUT AND NO TIMEOUT HANDLING PROVIDED')

    def handle_expected_views():
        '''Handle the appearance of the expected views. Unless otherwise specified, wait for
        them to dismiss themselves when NFC is turned off.
        '''
        if post_tap_wait:
            if post_tap_alert is not None:
                allowed_alerts = [post_tap_alert]
            else:
                allowed_alerts = None

            view_dumps = 0
            start_time = time.time()
            while self.viewsExist(expected_views):
                self.assertOrDump(time.time() - start_time < 7 or view_dumps < 2,
                                  'TAP SUCCESS SCREEN TAKING TOO LONG TO DISMISS ITSELF:')
                self.dump_raise_alerts(allowed_alerts=allowed_alerts)
                view_dumps += 1
            if post_tap_alert is not None:
                # Allow for one re-try here, to avoid getting caught with a blank screen before
                # the post-tap alert appears
                if not self.viewsExist(post_tap_alert):
                    self.dump_raise_alerts(allowed_alerts=allowed_alerts)
                self.assertViewsExist(post_tap_alert, 'MISSING POST-NFC TAP ALERT:')
        else:
            # Handle case where our expected views were an alert
            if isinstance(expected_views, dict):
                self.dump_raise_alerts(allowed_alerts=[expected_views])
            else:
                self.dump_raise_alerts()

    def handle_failed_views():
        '''Handle the appearance of failed tap views. Assumes tap had just ended and waits for
        appearance of post-tap explanatory error.
        '''
        view_dumps = 0
        start_time = time.time()
        while self.viewsExist(failed_views):
            # If we've already tried 2 view dumps and waited enough time without seeing a
            # change, stop waiting
            if view_dumps >= 2 and time.time() - start_time > 5:
                break
            self.vc.dump()
            view_dumps += 1
        # If there was no error message given with the fail, it may have left us back on the
        # tap screen post-tap. Exit it so the next test can't hit an issue with the timeout msg.
        if self.vc.findViewWithText(Views.ADD_VEHICLE_TAP_TITLE) is not None:
            self.device.press('BACK')
            self.vc.dump()

        # Raise any currently visible alert
        self.raise_alert('NFC connection established, but operation result was incorrect with' \
                         + ' error message:')

        # If no alert was raised, simply report the error
        self.fail('NFC connection established but operation result was incorrect. No further' \
                  + ' error message detected.')

    status = None
    remaining_tries = tries
    while remaining_tries > 0:
        try:
            # Before we tap, make sure we haven't been timed out and re-navigate if we have
            if self.viewsExist(timeout_views):
                handle_timeout_message()

            # Close the app if we were asked to before tapping
            if close_app:
                self.closeApp()

            # Now make sure we're on the initial page as specified by original_views
            if original_views is not None and not self.viewsExist(original_views):
                self.fail('Unexpected views prior to NFC tap:\n{0}'.format(self.dump_views()))

            # Start tap attempt
            self.device.shell('svc nfc enable')
            tap_start = time.time()

            # Make sure that our screen changed from our original views - if it didn't, that
            # means the NFC tap failed to communicate properly and we need to restart it.
            if original_views is not None:
                time.sleep(2) # Give NFC time to start the connection
                self.dump_raise_alerts(allowed_alerts=allowed_alerts)
                if self.viewsExist(original_views):
                    continue # try new tap

            # Else spend a few seconds waiting for the views to show up.
            view_dumps = 0
            while True:
                if self.viewsExist(timeout_views):
                    break

                # Check for the views we expect
                if expected_views is not None and self.viewsExist(expected_views):
                    status = 'expected views'
                    return

                # Check for the views which define a definitive failure as opposed to just a
                # problem with the NFC connection
                if failed_views is not None and self.viewsExist(failed_views):
                    status = 'failed'
                    return # Just used to get to finally clause where fail is raised post-tap

                # Check if the tap skipped us straight to the post-tap alert without showing us
                # the success views
                if post_tap_alert is not None and self.viewsExist(post_tap_alert):
                    status = 'premature alert'
                    print >> sys.stderr, "WARNING: Success alert was received before we" \
                          + " turned off NFC. It's possible the NFC connection cut out early," \
                          + " so we'll count this as a success, but you should rerun this" \
                          + " activity and make sure it's not skipping the success screen and" \
                          + " going straight to the success alert."
                    return

                # dump is sometimes extraordinarily slow so I'm going to make it require at
                # least 2 of these view dumps, in case the first one eats up the whole timeout.
                if view_dumps >= 2 and time.time() - tap_start > seconds:
                    break

                self.dump_raise_alerts(allowed_alerts=allowed_alerts)
                view_dumps += 1

            if self.viewsExist(timeout_views):
                handle_timeout_message()
                remaining_tries += 1 # Don't count attempts that were cut off by a timeout
                continue

            # If the tap appears to have gotten stuck in the in-progress state, retry
            if in_progress_views is not None and self.viewsExist(in_progress_views):
                continue

            # Otherwise, if we had no expected views, we can count this as a success
            if expected_views is None:
                status = 'success'
                return

            # If this tap appeared to connect normally but ended with neither our expected
            # views nor our failing views, report the result
            self.fail('Tap connected normally but ended with unknown views:\n' \
                      + self.dump_views())
        finally: # Note that continue/return statements execute the finally clause
            remaining_tries -= 1
            # Make sure NFC is turned off no matter what
            self.device.shell('svc nfc disable')

            # Handle post-tap actions based on status, if any are required
            if status == 'expected views':
                handle_expected_views()
            elif status == 'success':
                self.dump_raise_alerts()
            elif status == 'failed':
                handle_failed_views()
            elif status is None:
                # To cover the cases when the state changes while we were about to turn off NFC,
                # we need to re-dump the views and check what the final post-tap state is
                self.dump_raise_alerts(allowed_alerts=allowed_alerts)

                # Handle the end-cases
                if expected_views is not None and self.viewsExist(expected_views):
                    handle_expected_views()
                    return
                elif failed_views is not None and self.viewsExist(failed_views):
                    handle_failed_views()
                    return
                # In a really unfortunate timing case, we might give up and end the tap just
                # as it succeeded, but also have the success screen dismiss itself immediately
                # after we turn off nfc and before we re-dump.
                # In that case, we could now be seeing the post-tap alert
                elif post_tap_alert is not None and self.viewsExist(post_tap_alert):
                    print >> sys.stderr, "WARNING: Success alert was received but the program" \
                          + " missed whether or not the success screen appeared first." \
                          + " Counting this test as a success, but you should rerun it to" \
                          + " make sure the GUI behavior is as expected."
                    return
                # Timeout error will be handled at start of next loop for us
                elif remaining_tries > 0:
                    # If we see the in-progress views, the tap got stuck or we cut it off
                    # mid-way. In either case, we should press back to return to our original
                    # views if we're about to retry
                    if in_progress_views is not None and self.viewsExist(in_progress_views):
                        self.device.press('BACK')
                        self.dump_raise_alerts(allowed_alerts=allowed_alerts)
                        # There's a small case where expected views are a laggy alert and could
                        # have shown up after our view dump after NFC tap ended
                        if expected_views is not None and self.viewsExist(expected_views):
                            handle_expected_views()
                            return

    # If we're on this line, all the tap attempts failed to get an NFC connection
    self.fail('Could not establish proper NFC connection in {0} attempts'.format(tries))