Ejemplo n.º 1
0
def _callable_wait_for(refresh_fn, matcher, timeout):
    """Like the patched :meth:`wait_for method`, but for callable objects
    instead of patched variables.

    """
    time_left = timeout
    while True:
        new_value = refresh_fn()
        mismatch = matcher.match(new_value)
        if mismatch:
            failure_msg = mismatch.describe()
        else:
            return

        if time_left >= 1:
            sleep(1)
            time_left -= 1
        else:
            sleep(time_left)
            break

    # can't give a very descriptive message here, especially as refresh_fn
    # is likely to be a lambda.
    raise AssertionError(
        "After %.1f seconds test failed: %s" % (timeout, failure_msg))
Ejemplo n.º 2
0
    def wait_select_single(self, type_name='*', ap_query_timeout=5, **kwargs):
        """Get a proxy object matching some search criteria, retrying if no
        object is found until a timeout is reached.

        This method is identical to the :meth:`select_single` method, except
        that this method will poll the application under test for 10 seconds
        in the event that the search criteria does not match anything.

        This method will return single proxy object from the introspection
        tree, with type equal to *type_name* and (optionally) matching the
        keyword filters present in *kwargs*.

        You must specify either *type_name*, keyword filters or both.

        This method searches recursively from the proxy object this method is
        called on. Calling :meth:`select_single` on the application (root)
        proxy object will search the entire tree. Calling
        :meth:`select_single` on an object in the tree will only search it's
        descendants.

        Example usage::

            app.wait_select_single('QPushButton', objectName='clickme')
            # returns a QPushButton whose 'objectName' property is 'clickme'.
            # will poll the application until such an object exists, or will
            # raise StateNotFoundError after 10 seconds.

        If nothing is returned from the query, this method raises
        StateNotFoundError after *ap_query_timeout* seconds.

        :param type_name: Either a string naming the type you want, or a class
            of the appropriate type (the latter case is for overridden emulator
            classes).

        :param ap_query_timeout: Time in seconds to wait for search criteria
            to match.

        :raises ValueError: if the query returns more than one item. *If
            you want more than one item, use select_many instead*.

        :raises ValueError: if neither *type_name* or keyword filters are
            provided.

        :raises StateNotFoundError: if the requested object was not found.

        .. seealso::
            Tutorial Section :ref:`custom_proxy_classes`

        """
        if ap_query_timeout <= 0:
            return self._select_single(type_name, **kwargs)

        for i in range(ap_query_timeout):
            try:
                return self._select_single(type_name, **kwargs)
            except StateNotFoundError:
                sleep(1)
                self.refresh_state()
        raise StateNotFoundError(type_name, **kwargs)
Ejemplo n.º 3
0
def _do_timeout(timeout):
    time_elapsed = 0.0
    while timeout - time_elapsed > 0.0:
        yield time_elapsed
        time_to_sleep = min(timeout - time_elapsed, 1.0)
        sleep(time_to_sleep)
        time_elapsed += time_to_sleep
    yield time_elapsed
Ejemplo n.º 4
0
    def is_moving(self, gap_interval=0.1):
        """Check if the element is moving.

        :param gap_interval: Time in seconds to wait before
            re-inquiring the object co-ordinates to be able
            to evaluate if, the element has moved.

        :return: True, if the element is moving, otherwise False.
        """
        x1, y1, h1, w1 = self._get_default_dbus_object().globalRect
        sleep(gap_interval)
        x2, y2, h2, w2 = self._get_secondary_dbus_object().globalRect

        return x1 != x2 or y1 != y2
Ejemplo n.º 5
0
    def wait_get_children_by_type(self,
                                  type_name='*',
                                  ap_query_timeout=5,
                                  **kwargs):
        if ap_query_timeout <= 0:
            return self.get_children_by_type(type_name, **kwargs)

        for i in range(ap_query_timeout):
            try:
                result = self.get_children_by_type(type_name, **kwargs)

                if not result:
                    raise ValueError()

            except (StateNotFoundError, ValueError):
                sleep(1)

        raise StateNotFoundError(type_name, **kwargs)
Ejemplo n.º 6
0
    def wait_until_destroyed(self, timeout=10):
        """Block until this object is destroyed in the application.

        Block until the object this instance is a proxy for has been destroyed
        in the applicaiton under test. This is commonly used to wait until a
        UI component has been destroyed.

        :param timeout: The number of seconds to wait for the object to be
            destroyed. If not specified, defaults to 10 seconds.
        :raises RuntimeError: if the method timed out.

        """
        for i in range(timeout):
            try:
                self._get_new_state()
                sleep(1)
            except StateNotFoundError:
                return
        else:
            raise RuntimeError("Object was not destroyed after %d seconds" %
                               timeout)
Ejemplo n.º 7
0
    def wait_select_many(self,
                         type_name='*',
                         ap_query_timeout=5,
                         ap_result_count=1,
                         ap_result_sort_keys=None,
                         **kwargs):
        """Get a list of nodes from the introspection tree, with type equal to
        *type_name* and (optionally) matching the keyword filters present in
        *kwargs*.

        This method is identical to the :meth:`select_many` method, except
        that this method will poll the application under test for
        *ap_query_timeout* seconds in the event that the search result count
        is not greater than or equal to *ap_result_count*.

        You must specify either *type_name*, keyword filters or both.

        This method searches recursively from the instance this method is
        called on. Calling :meth:`wait_select_many` on the application (root)
        proxy object will search the entire tree. Calling
        :meth:`wait_select_many` on an object in the tree will only search
        it's descendants.

        Example Usage::

            app.wait_select_many(
                'QPushButton',
                ap_query_timeout=5,
                ap_result_count=2,
                enabled=True
            )
            # returns at least 2 QPushButtons that are enabled, within
            # 5 seconds.

        .. warning::
            The order in which objects are returned is not guaranteed. It is
            bad practise to write tests that depend on the order in which
            this method returns objects. (see :ref:`object_ordering` for more
            information).

        :param type_name: Either a string naming the type you want, or a class
            of the appropriate type (the latter case is for overridden emulator
            classes).

        :param ap_query_timeout: Time in seconds to wait for search criteria
            to match.

        :param ap_result_count: Minimum number of results to return.

        :param ap_result_sort_keys: list of object properties to sort the
            query result with (sort key priority starts with element 0 as
            highest priority and then descends down the list).

        :raises ValueError: if neither *type_name* or keyword filters are
            provided. Also raises, if search result count does not match the
            number specified by *ap_result_count* within *ap_query_timeout*
            seconds.

        .. seealso::
            Tutorial Section :ref:`custom_proxy_classes`

        """
        exception_message = 'Failed to find the requested number of elements.'

        if ap_query_timeout <= 0:
            instances = self._select_many(type_name, **kwargs)
            if len(instances) < ap_result_count:
                raise ValueError(exception_message)
            return sort_by_keys(instances, ap_result_sort_keys)

        for i in range(ap_query_timeout):
            instances = self._select_many(type_name, **kwargs)
            if len(instances) >= ap_result_count:
                return sort_by_keys(instances, ap_result_sort_keys)
            sleep(1)
        raise ValueError(exception_message)
Ejemplo n.º 8
0
    def wait_for(self, expected_value, timeout=10):
        """Wait up to 10 seconds for our value to change to
        *expected_value*.

        *expected_value* can be a testtools.matcher. Matcher subclass (like
        LessThan, for example), or an ordinary value.

        This works by refreshing the value using repeated dbus calls.

        :raises AssertionError: if the attribute was not equal to the
         expected value after 10 seconds.

        :raises RuntimeError: if the attribute you called this on was not
         constructed as part of an object.

        """
        # It's guaranteed that our value is up to date, since __getattr__
        # calls refresh_state. This if statement stops us waiting if the
        # value is already what we expect:
        if self == expected_value:
            return

        if self.name is None or self.parent is None:
            raise RuntimeError(
                "This variable was not constructed as part of "
                "an object. The wait_for method cannot be used."
            )

        def make_unicode(value):
            if isinstance(value, bytes):
                return value.decode('utf8')
            return value

        if hasattr(expected_value, 'expected'):
            expected_value.expected = make_unicode(expected_value.expected)

        # unfortunately not all testtools matchers derive from the Matcher
        # class, so we can't use issubclass, isinstance for this:
        match_fun = getattr(expected_value, 'match', None)
        is_matcher = match_fun and callable(match_fun)
        if not is_matcher:
            expected_value = Equals(expected_value)

        time_left = timeout
        while True:
            # TODO: These next three lines are duplicated from the parent...
            # can we just have this code once somewhere?
            _, new_state = self.parent._get_new_state()
            new_state = translate_state_keys(new_state)
            new_value = new_state[self.name][1:]
            if len(new_value) == 1:
                new_value = make_unicode(new_value[0])
            # Support for testtools.matcher classes:
            mismatch = expected_value.match(new_value)
            if mismatch:
                failure_msg = mismatch.describe()
            else:
                self.parent._set_properties(new_state)
                return

            if time_left >= 1:
                sleep(1)
                time_left -= 1
            else:
                sleep(time_left)
                break

        raise AssertionError(
            "After %.1f seconds test on %s.%s failed: %s" % (
                timeout, self.parent.__class__.__name__, self.name,
                failure_msg))