Просмотр клиентского дампа загрузки процессора - PullRequest
0 голосов
/ 18 мая 2018

Я использую функцию Android View Client dump () через Python для извлечения Views с устройства Android, чтобы проверить Views для моего приложения, которое я тестирую.Я пытаюсь исправить чужой тестовый код, чтобы некоторые вещи не были реализованы в идеале.Способ, которым были разработаны автоматизированные тесты, состоит в том, чтобы перейти к каждому экрану, выполнить дамп View, подождать несколько секунд, пока дамп произойдет, и затем проверить этот дамп с тем, каким должен быть View.Если это не то же самое, тогда они ждут пару секунд и вызывают новый дамп.(Ожидание должно дать время для полного выполнения метода dump ().) Этот сброс вызывает смехотворное использование ЦП (~ 65-80%) клиентом Android View.Будет ли у кого-нибудь предложение о том, как уменьшить использование процессора?

Я бы хотел использовать метод dump (), но, может быть, цикл опроса, который реализовал предыдущий программист, не идеален?Они в основном просто продолжают опрос, пока не произойдет установленное количество дампов или не появится представление, которое они ищут

Если есть и другой способ проверки пользовательского интерфейса, я открыт для переключения.

Любые предложения будут с благодарностью.Спасибо!

(Ниже приведен фрагмент кода теста)

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))
...