1
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
3
# Autopilot Functional Test Tool
4
# Copyright (C) 2012-2013 Canonical
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program. If not, see <http://www.gnu.org/licenses/>.
26
from tempfile import mktemp
27
from testtools import skipIf
28
from testtools.matchers import Equals, NotEquals, raises, LessThan, GreaterThan
30
from autopilot import platform
31
from autopilot.testcase import AutopilotTestCase
32
from autopilot.introspection.dbus import StateNotFoundError
35
@skipIf(platform.model() != "Desktop", "Only suitable on Desktop (WinMocker)")
36
class DbusQueryTests(AutopilotTestCase):
37
"""A collection of dbus query tests for autopilot."""
39
def start_fully_featured_app(self):
40
"""Create an application that includes menus and other nested
65
"Contents": "TextEdit"
69
json.dump(window_spec, open(file_path, 'w'))
70
self.addCleanup(os.remove, file_path)
72
return self.launch_test_application(
73
'window-mocker', file_path, app_type="qt")
75
def test_select_single_selects_only_available_object(self):
76
"""Must be able to select a single unique object."""
77
app = self.start_fully_featured_app()
78
main_window = app.select_single('QMainWindow')
79
self.assertThat(main_window, NotEquals(None))
81
def test_can_select_parent_of_root(self):
82
"""Must be able to select the parent of the root object."""
83
root = self.start_fully_featured_app()
84
root_parent = root.get_parent()
85
self.assertThat(root.id, Equals(root_parent.id))
87
def test_can_select_parent_of_normal_node(self):
88
root = self.start_fully_featured_app()
89
main_window = root.select_single('QMainWindow')
90
window_parent = main_window.get_parent()
91
self.assertThat(window_parent.id, Equals(root.id))
93
def test_single_select_on_object(self):
94
"""Must be able to select a single unique child of an object."""
95
app = self.start_fully_featured_app()
96
main_win = app.select_single('QMainWindow')
97
menu_bar = main_win.select_single('QMenuBar')
98
self.assertThat(menu_bar, NotEquals(None))
100
def test_select_multiple_on_object_returns_all(self):
101
"""Must be able to select all child objects."""
102
app = self.start_fully_featured_app()
103
main_win = app.select_single('QMainWindow')
104
menu_bar = main_win.select_single('QMenuBar')
105
menus = menu_bar.select_many('QMenu')
106
self.assertThat(len(menus), Equals(2))
108
def test_select_multiple_on_object_with_parameter(self):
109
"""Must be able to select a specific object determined by a
113
app = self.start_fully_featured_app()
114
main_win = app.select_single('QMainWindow')
115
menu_bar = main_win.select_single('QMenuBar')
116
help_menu = menu_bar.select_many('QMenu', title='Help')
117
self.assertThat(len(help_menu), Equals(1))
118
self.assertThat(help_menu[0].title, Equals('Help'))
120
def test_select_single_on_object_with_param(self):
121
"""Must only select a single unique object using a parameter."""
122
app = self.start_fully_featured_app()
123
main_win = app.select_single('QMainWindow')
124
menu_bar = main_win.select_single('QMenuBar')
125
help_menu = menu_bar.select_single('QMenu', title='Help')
126
self.assertThat(help_menu, NotEquals(None))
127
self.assertThat(help_menu.title, Equals('Help'))
129
def test_select_many_uses_unique_object(self):
130
"""Given 2 objects of the same type with childen, selection on one will
131
only get its children.
134
app = self.start_fully_featured_app()
135
main_win = app.select_single('QMainWindow')
136
menu_bar = main_win.select_single('QMenuBar')
137
help_menu = menu_bar.select_single('QMenu', title='Help')
138
actions = help_menu.select_many('QAction')
139
self.assertThat(len(actions), Equals(5))
141
def test_select_single_no_name_no_parameter_raises_exception(self):
142
app = self.start_fully_featured_app()
143
fn = lambda: app.select_single()
144
self.assertThat(fn, raises(TypeError))
146
def test_select_single_no_match_raises_exception(self):
147
app = self.start_fully_featured_app()
148
match_fn = lambda: app.select_single("QMadeupType")
149
self.assertThat(match_fn, raises(StateNotFoundError('QMadeupType')))
151
def test_select_single_parameters_only(self):
152
app = self.start_fully_featured_app()
153
main_win = app.select_single('QMainWindow')
154
titled_help = main_win.select_single(title='Help')
155
self.assertThat(titled_help, NotEquals(None))
156
self.assertThat(titled_help.title, Equals('Help'))
158
def test_select_single_parameters_no_match_raises_exception(self):
159
app = self.start_fully_featured_app()
160
match_fn = lambda: app.select_single(title="Non-existant object")
163
raises(StateNotFoundError('*', title="Non-existant object"))
166
def test_select_single_returning_multiple_raises(self):
167
app = self.start_fully_featured_app()
168
fn = lambda: app.select_single('QMenu')
169
self.assertThat(fn, raises(ValueError))
171
def test_select_many_no_name_no_parameter_raises_exception(self):
172
app = self.start_fully_featured_app()
173
fn = lambda: app.select_single()
174
self.assertThat(fn, raises(TypeError))
176
def test_select_many_only_using_parameters(self):
177
app = self.start_fully_featured_app()
178
many_help_menus = app.select_many(title='Help')
179
self.assertThat(len(many_help_menus), Equals(1))
181
def test_select_many_with_no_parameter_matches_returns_empty_list(self):
182
app = self.start_fully_featured_app()
183
failed_match = app.select_many('QMenu', title='qwerty')
184
self.assertThat(failed_match, Equals([]))
186
def test_wait_select_single_succeeds_quickly(self):
187
app = self.start_fully_featured_app()
189
main_window = app.wait_select_single('QMainWindow')
191
self.assertThat(main_window, NotEquals(None))
192
self.assertThat(abs(end_time - start_time), LessThan(1))
194
def test_wait_select_single_fails_slowly(self):
195
app = self.start_fully_featured_app()
197
fn = lambda: app.wait_select_single('QMadeupType')
198
self.assertThat(fn, raises(StateNotFoundError('QMadeupType')))
200
self.assertThat(abs(end_time - start_time), GreaterThan(9))
201
self.assertThat(abs(end_time - start_time), LessThan(11))
204
@skipIf(platform.model() != "Desktop", "Only suitable on Desktop (WinMocker)")
205
class DbusCustomBusTests(AutopilotTestCase):
206
"""Test the ability to use custom dbus buses during a test."""
209
self.dbus_bus_addr = self._enable_custom_dbus_bus()
210
super(DbusCustomBusTests, self).setUp()
212
def _enable_custom_dbus_bus(self):
213
p = subprocess.Popen(['dbus-launch'], stdout=subprocess.PIPE,
214
universal_newlines=True)
215
output = p.communicate()
216
results = output[0].split("\n")
217
dbus_pid = int(results[1].split("=")[1])
218
dbus_address = results[0].split("=", 1)[1]
220
kill_dbus = lambda pid: os.killpg(pid, signal.SIGTERM)
221
self.addCleanup(kill_dbus, dbus_pid)
225
def _start_mock_app(self, dbus_bus):
227
"Contents": "TextEdit"
231
json.dump(window_spec, open(file_path, 'w'))
232
self.addCleanup(os.remove, file_path)
234
return self.launch_test_application(
241
def test_can_use_custom_dbus_bus(self):
242
app = self._start_mock_app(self.dbus_bus_addr)
243
self.assertThat(app, NotEquals(None))