Merge lp:~chris.gagnon/autopilot/select_many_length into lp:~autopilot/autopilot/temp-dev

Proposed by Chris Gagnon
Status: Work in progress
Proposed branch: lp:~chris.gagnon/autopilot/select_many_length
Merge into: lp:~autopilot/autopilot/temp-dev
Diff against target: 138 lines (+117/-0)
2 files modified
autopilot/introspection/dbus.py (+85/-0)
autopilot/tests/functional/test_dbus_query.py (+32/-0)
To merge this branch: bzr merge lp:~chris.gagnon/autopilot/select_many_length
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Christopher Lee Pending
Leo Arias Pending
Thomi Richards Pending
Autopilot Hackers Pending
Review via email: mp+220858@code.launchpad.net

Commit message

add length param to select_many, it will wait for a specified number of objects to be found

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:488
http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-ci/126/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-utopic-amd64-ci/87
        deb: http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-utopic-amd64-ci/87/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-utopic-armhf-ci/87
        deb: http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-utopic-armhf-ci/87/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-utopic-i386-ci/87
        deb: http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-utopic-i386-ci/87/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic-autopilot/133
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic-touch/114
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic-autopilot/137
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/533
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/533/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/882
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/882/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/6683
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/7641

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/autopilot-autopilot-temp-dev-ci/126/rebuild

review: Approve (continuous-integration)
Revision history for this message
Chris Gagnon (chris.gagnon) wrote :

We might want to make this it's own function, what if a qml property's name is length?

something like wait_select_many(6, 'Label', visible=True)

instead of this merge proposal's select_many('Label', length=6 visible=True)

let me know what you think.

489. By Chris Gagnon

Their might be a length kwarg, use wait_select_many instead

490. By Chris Gagnon

undo doc string in select_many which moved to wait_select_many

491. By Chris Gagnon

update to doc string

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

PASSED: Continuous integration, rev:491
http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-ci/128/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-utopic-amd64-ci/89
        deb: http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-utopic-amd64-ci/89/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-utopic-armhf-ci/89
        deb: http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-utopic-armhf-ci/89/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-utopic-i386-ci/89
        deb: http://jenkins.qa.ubuntu.com/job/autopilot-autopilot-temp-dev-utopic-i386-ci/89/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic-autopilot/135
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-utopic-touch/116
    SUCCESS: http://jenkins.qa.ubuntu.com/job/autopilot-testrunner-otto-utopic-autopilot/165
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/535
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-amd64/535/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/884
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-utopic-armhf/884/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-runner-mako/6710
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/7670

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/autopilot-autopilot-temp-dev-ci/128/rebuild

review: Approve (continuous-integration)
Revision history for this message
Thomi Richards (thomir-deactivatedaccount) wrote :

Hmm, I'm not sure about this.

I'm concerned that we're adding a parameter to the existing API, making it harder to use, and harder to understand.

I wonder if we can achieve this with a matcher instead? How about something like:

--
from testtools.matchers import AfterProcessing, HasLength

self.assertThat(
    AfterProcessing(lambda: proxy.select_many('Foo')),
    Eventually(HasLength(5))
)
--

Revision history for this message
Chris Gagnon (chris.gagnon) wrote :

I want to use this in a custom proxy object, so we can't use assertThat

Revision history for this message
Chris Gagnon (chris.gagnon) wrote :

thomi mentioned this test https://github.com/testing-cabal/testtools/pull/70 so I'll work on getting this abandon merge request in.

Unmerged revisions

491. By Chris Gagnon

update to doc string

490. By Chris Gagnon

undo doc string in select_many which moved to wait_select_many

489. By Chris Gagnon

Their might be a length kwarg, use wait_select_many instead

488. By Chris Gagnon

add length param to select_many to wait for specified number of objects to be returned

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'autopilot/introspection/dbus.py'
2--- autopilot/introspection/dbus.py 2014-05-13 05:03:21 +0000
3+++ autopilot/introspection/dbus.py 2014-05-25 06:43:18 +0000
4@@ -302,6 +302,91 @@
5 raise
6 sleep(1)
7
8+ def wait_select_many(
9+ self,
10+ num_of_objects_to_wait_for,
11+ type_name='*',
12+ **kwargs
13+ ):
14+ """Wait for a number of objects from the introspection tree,
15+ retrying until the specified number of objects to wait for are found
16+
17+ This method is used in the same way :meth:`select_many` method, except
18+ that this method will poll the application under test for 10 seconds.
19+ It should be used only when you need to wait for a specific number of
20+ objects matching *type_name* and (optionally) matching the keywordi
21+ filters present in *kwargs*.
22+
23+ You must specify num_of_objects_to_wait_for and either *type_name*,
24+ keyword filters or both.
25+
26+ This method searches recursively from the instance this method is
27+ called on. Calling :meth:`wait_select_many` on the application (root)
28+ proxy object will search the entire tree. Calling
29+ :meth:`wait_select_many` on an object in the tree will only search
30+ it's descendants.
31+
32+ Example Usage::
33+
34+ app.wait_select_many(5, 'QPushButton', enabled=True)
35+ # returns a list of QPushButtons that are enabled, when 5
36+ # enabled QPushButtons are found.
37+
38+ As mentioned above, this method searches the object tree recursively::
39+
40+ file_menu = app.select_one('QMenu', title='File')
41+ file_menu.wait_select_many(5, 'QAction')
42+ # returns a list of QAction objects who appear below file_menu in
43+ # the object tree when 5 Action objects appear below file_menu.
44+
45+ .. warning::
46+ The order in which objects are returned is not guaranteed. It is
47+ bad practise to write tests that depend on the order in which
48+ this method returns objects. (see :ref:`object_ordering` for more
49+ information).
50+
51+ If you only want to get one item, use :meth:`wait_select_single`
52+ instead.
53+
54+ :param type_name: Either a string naming the type you want, or a class
55+ of the appropriate type (the latter case is for overridden emulator
56+ classes).
57+ :param num_of_objects_to_wait_for: the number of objects in query to
58+ wait for
59+
60+ :raises ValueError: if neither *type_name* or keyword filters are
61+ provided.
62+
63+ :raises RuntimeError: if the specified number of objects are not
64+ found after waiting for them.
65+
66+ .. seealso::
67+ Tutorial Section :ref:`custom_proxy_classes`
68+
69+ """
70+ type_name_str = get_type_name(type_name)
71+ new_query = self._query.select_descendant(
72+ type_name_str,
73+ kwargs
74+ )
75+ _logger.debug(
76+ "Selecting objects of %s with attributes: %r",
77+ 'any type'
78+ if type_name_str == '*' else 'type ' + type_name_str, kwargs
79+ )
80+ for i in range(self._poll_time):
81+ instances = self._execute_query(new_query)
82+ if len(instances) == num_of_objects_to_wait_for:
83+ return instances
84+ sleep(1)
85+ raise RuntimeError(
86+ "Not enough objects were found. "
87+ "Number of objects found {}, expected length={}".format(
88+ len(instances),
89+ num_of_objects_to_wait_for
90+ )
91+ )
92+
93 def select_many(self, type_name='*', **kwargs):
94 """Get a list of nodes from the introspection tree, with type equal to
95 *type_name* and (optionally) matching the keyword filters present in
96
97=== modified file 'autopilot/tests/functional/test_dbus_query.py'
98--- autopilot/tests/functional/test_dbus_query.py 2014-04-28 12:05:31 +0000
99+++ autopilot/tests/functional/test_dbus_query.py 2014-05-25 06:43:18 +0000
100@@ -138,6 +138,38 @@
101 actions = help_menu.select_many('QAction')
102 self.assertThat(len(actions), Equals(5))
103
104+ def test_wait_select_many_is_not_enough_raises_runtime_error(self):
105+ """wait_select_many must return RunTimeError when number of objects
106+ to wait for is greater than number of instances returned
107+
108+ """
109+ app = self.start_fully_featured_app()
110+ main_win = app.select_single('QMainWindow')
111+ menu_bar = main_win.select_single('QMenuBar')
112+ help_menu = menu_bar.select_single('QMenu', title='Help')
113+ actions = help_menu.select_many('QAction')
114+ self.assertThat(len(actions), Equals(5))
115+ fn = lambda: help_menu.wait_select_many(6, 'QAction')
116+ self.assertThat(fn, raises(RuntimeError))
117+
118+ def test_wait_select_many_finds_all_objects(self):
119+ app = self.start_fully_featured_app()
120+ main_win = app.select_single('QMainWindow')
121+ menu_bar = main_win.select_single('QMenuBar')
122+ help_menu = menu_bar.select_single('QMenu', title='Help')
123+ actions = help_menu.wait_select_many(5, 'QAction')
124+ self.assertThat(len(actions), Equals(5))
125+
126+ def test_wait_select_many_no_parameters_raises_exception(self):
127+ app = self.start_fully_featured_app()
128+ fn = lambda: app.wait_select_many()
129+ self.assertThat(fn, raises(TypeError))
130+
131+ def test_wait_select_many_no_name_no_parameter_raises_exception(self):
132+ app = self.start_fully_featured_app()
133+ fn = lambda: app.wait_select_many(5)
134+ self.assertThat(fn, raises(ValueError))
135+
136 def test_select_single_no_name_no_parameter_raises_exception(self):
137 app = self.start_fully_featured_app()
138 fn = lambda: app.select_single()

Subscribers

People subscribed via source and target branches