Merge lp:~canonical-platform-qa/ubuntu-system-tests/test_receive_sms into lp:ubuntu-system-tests
- test_receive_sms
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Richard Huddie |
Approved revision: | 116 |
Merged at revision: | 121 |
Proposed branch: | lp:~canonical-platform-qa/ubuntu-system-tests/test_receive_sms |
Merge into: | lp:ubuntu-system-tests |
Prerequisite: | lp:~canonical-platform-qa/ubuntu-system-tests/crendentials |
Diff against target: |
573 lines (+500/-0) 8 files modified
README.rst (+7/-0) debian/tests/control (+2/-0) ubuntu_system_tests/config.py (+14/-0) ubuntu_system_tests/helpers/addressbook/dbus_service.py (+84/-0) ubuntu_system_tests/helpers/telephony.py (+197/-0) ubuntu_system_tests/helpers/unity8/notifications.py (+41/-0) ubuntu_system_tests/tests/base.py (+26/-0) ubuntu_system_tests/tests/test_messaging.py (+129/-0) |
To merge this branch: | bzr merge lp:~canonical-platform-qa/ubuntu-system-tests/test_receive_sms |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Approve | |
Richard Huddie (community) | Approve | ||
Brendan Donegan (community) | Approve | ||
Sergio Cazzolato | Approve | ||
Review via email: mp+260545@code.launchpad.net |
Commit message
Test and framework for receiving an SMS
Description of the change
Add the sanity test for receiving an SMS and the supporting helpers
Note that the phone number cannot be queried from the SIM in all circumstances so we have to have it as a config option.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:99
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 100. By Brendan Donegan
-
Notifications helpers
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:100
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 101. By Brendan Donegan
-
Remove TODO comment
- 102. By Brendan Donegan
-
Update to/from_number config help text
- 103. By Brendan Donegan
-
Update README with info on getting telephony service access
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:101
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:103
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Richard Huddie (rhuddie) wrote : | # |
This is looking good. I managed to get it working after a few problems (see comments below).
Also, some flake8 errors:
./ubuntu_
./ubuntu_
./ubuntu_
./ubuntu_
./ubuntu_
./ubuntu_
./ubuntu_
./ubuntu_
./ubuntu_
- 104. By Brendan Donegan
-
Fix flake8 issues in telephony helpers
- 105. By Brendan Donegan
-
Rename to_number to device_phone_number and from_number to telephony_
service_ number
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:105
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 106. By Brendan Donegan
-
Remove stray print statement
- 107. By Brendan Donegan
-
Added last bits of test and addressed last comments
Brendan Donegan (brendan-donegan) wrote : | # |
Made a lot of updates, let's see what the Jenkins job comes back with.
Brendan Donegan (brendan-donegan) wrote : | # |
Response to diff comments
Brendan Donegan (brendan-donegan) wrote : | # |
Btw there is some new code at the end of the test to pay attention to, particularly to delete the message - maybe that should be done in a different way, not using the UI?
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:107
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Sergio Cazzolato (sergio-j-cazzolato) wrote : | # |
2 comments inline
- 108. By Brendan Donegan
-
Comment up the test code
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:108
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Brendan Donegan (brendan-donegan) wrote : | # |
Spoke to renato - since the dbus API is essentially private it could potentially change and break at any time - however the only public and supported way is using the C++ API. Writing bindings is laborious and fraught with danger, so I'd prefer to stick with using the DBus API. I would point out that this code was initially written nearly a year ago and still works as is so it's not as unstable as it might sound initially.
- 109. By Brendan Donegan
-
Merged from trunk
- 110. By Brendan Donegan
-
Fix flake8 issue
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:110
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Sergio Cazzolato (sergio-j-cazzolato) : | # |
Brendan Donegan (brendan-donegan) wrote : | # |
Tested again to make sure it works, and it does. If no further objections, we can top-approve?
Richard Huddie (rhuddie) wrote : | # |
This looks really good, I ran the test fine.
Just 1 comment below about skipping the test if no sim inserted.
- 111. By Brendan Donegan
-
Skip test_receive_sms if no SIM is inserted
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:111
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 112. By Brendan Donegan
-
Merged from trunk
Brendan Donegan (brendan-donegan) wrote : | # |
Skip added, tested both with and without SIM inserted, all works properly. Just wait for the Jenkins job to return clean and we can top-approve I guess
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:112
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 113. By Brendan Donegan
-
Revert removal of restart_unity
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:113
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 114. By Brendan Donegan
-
Remove _ensure_
application_ closed from test_messaging.py
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:114
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 115. By Brendan Donegan
-
typo in ensure_
application_ closed
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:115
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 116. By Richard Huddie
-
Temporarily remove use of tap_on notification method to improve reliability.
Richard Huddie (rhuddie) wrote : | # |
Re-tested on mako with the notification change to improve reliability. Works fine.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:116
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'README.rst' |
2 | --- README.rst 2015-05-27 20:21:41 +0000 |
3 | +++ README.rst 2015-06-04 15:20:03 +0000 |
4 | @@ -92,6 +92,13 @@ |
5 | To do this you need to be part of the platform-qa group on people.canonical.com |
6 | and have shell access there. |
7 | |
8 | +Set up telephony service access (currently Twilio) |
9 | +-------------------------------------------------- |
10 | + |
11 | +To run tests that use telephony service you will need an account on Twilio.com. Please |
12 | +email qa-team@lists.canonical.com and they will set up a sub-account with its own API |
13 | +credentials and an initial test number, as well as instructions on adding more. |
14 | + |
15 | Copy data files to the testbed |
16 | ------------------------------ |
17 | |
18 | |
19 | === modified file 'debian/tests/control' |
20 | --- debian/tests/control 2015-05-26 16:23:26 +0000 |
21 | +++ debian/tests/control 2015-06-04 15:20:03 +0000 |
22 | @@ -4,12 +4,14 @@ |
23 | Depends: address-book-app-autopilot (>=0.2+15.04.20150226-0ubuntu1), |
24 | camera-app-autopilot, |
25 | exiftool, |
26 | + messaging-app-autopilot, |
27 | oxideqt-chromedriver, |
28 | python3-autopilot, |
29 | python3-dbus, |
30 | python3-debian, |
31 | python3-gi, |
32 | python3-testtools, |
33 | + python3-requests, |
34 | python3-selenium, |
35 | subunit, |
36 | ubuntu-keyboard-autopilot, |
37 | |
38 | === modified file 'ubuntu_system_tests/config.py' |
39 | --- ubuntu_system_tests/config.py 2015-05-27 15:55:44 +0000 |
40 | +++ ubuntu_system_tests/config.py 2015-06-04 15:20:03 +0000 |
41 | @@ -54,6 +54,20 @@ |
42 | 'bluetooth_device_name', |
43 | help_string='Name of a nearby bluetooth pairing device'), |
44 | options.Option( |
45 | + 'device_phone_number', |
46 | + help_string="The phone number of the device to which calls " |
47 | + "and messages should be directed. This must " |
48 | + "be formatted exactly as you would dial it " |
49 | + "normally."), |
50 | + options.Option( |
51 | + 'telephony_service_number', |
52 | + help_string="The phone number to call and message from " |
53 | + "in the telephony service. In Twilio go to " |
54 | + "https://www.twilio.com/user/account/" |
55 | + "phone-numbers/incoming and click on the number " |
56 | + "you want to use, then copy the 'Phone Number' " |
57 | + "field exactly."), |
58 | + options.Option( |
59 | # this is a private key, that will not be exported to |
60 | # autopilot directly |
61 | '_twilio_account_sid', default=options.MANDATORY, |
62 | |
63 | === added file 'ubuntu_system_tests/helpers/addressbook/dbus_service.py' |
64 | --- ubuntu_system_tests/helpers/addressbook/dbus_service.py 1970-01-01 00:00:00 +0000 |
65 | +++ ubuntu_system_tests/helpers/addressbook/dbus_service.py 2015-06-04 15:20:03 +0000 |
66 | @@ -0,0 +1,84 @@ |
67 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
68 | + |
69 | +# |
70 | +# Ubuntu System Tests |
71 | +# Copyright (C) 2015 Canonical |
72 | +# |
73 | +# This program is free software: you can redistribute it and/or modify |
74 | +# it under the terms of the GNU General Public License version 3, |
75 | +# as published by the Free Software Foundation. |
76 | +# |
77 | +# This program is distributed in the hope that it will be useful, |
78 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
79 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
80 | +# GNU General Public License for more details. |
81 | +# |
82 | +# You should have received a copy of the GNU General Public License |
83 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
84 | +# |
85 | + |
86 | +import dbus |
87 | +import re |
88 | + |
89 | + |
90 | +DBUS_NAME_PIM = 'com.canonical.pim' |
91 | +DBUS_IFACE_ADDRESS_BOOK = 'com.canonical.pim.AddressBook' |
92 | +DBUS_IFACE_ADDRESS_BOOKVIEW = 'com.canonical.pim.AddressBookView' |
93 | +DBUS_OBJECT_ADDRESS_BOOK = '/com/canonical/pim/AddressBook' |
94 | + |
95 | + |
96 | +class ContactsDbusService: |
97 | + def __init__(self): |
98 | + self.bus = None |
99 | + self.addr = None |
100 | + self.addr_iface = None |
101 | + self.bus = dbus.SessionBus() |
102 | + self.addr = self.bus.get_object( |
103 | + DBUS_NAME_PIM, DBUS_OBJECT_ADDRESS_BOOK) |
104 | + self.addr_iface = dbus.Interface( |
105 | + self.addr, dbus_interface=DBUS_IFACE_ADDRESS_BOOK) |
106 | + |
107 | + def query_contacts(self, fields='', query='', sources=[]): |
108 | + view_path = self.addr_iface.query(fields, query, []) |
109 | + view = self.bus.get_object( |
110 | + DBUS_NAME_PIM, view_path) |
111 | + view_iface = dbus.Interface( |
112 | + view, dbus_interface=DBUS_IFACE_ADDRESS_BOOKVIEW) |
113 | + contacts = view_iface.contactsDetails([], 0, -1) |
114 | + view.close() |
115 | + return contacts |
116 | + |
117 | + def update_contact(self, vcard): |
118 | + return self.addr_iface.updateContacts([vcard]) |
119 | + |
120 | + def create_contact(self, vcard): |
121 | + return self.addr_iface.createContact(vcard, "") |
122 | + |
123 | + def delete_contact(self, ids): |
124 | + return self.addr_iface.removeContacts(ids) |
125 | + |
126 | + def get_vcard_uid(self, vcard): |
127 | + """ |
128 | + Return the UID of the provided vcard |
129 | + :param vcard: vcard formatted data |
130 | + :return: uid value from vcard, else None |
131 | + """ |
132 | + uid_pattern = re.compile(r'^UID:(?P<uid>\S*)\r?$', |
133 | + re.MULTILINE | re.IGNORECASE) |
134 | + uid = None |
135 | + match = uid_pattern.search(vcard) |
136 | + if match: |
137 | + uid = match.group('uid') |
138 | + return uid |
139 | + |
140 | + def delete_all_contacts(self): |
141 | + """ |
142 | + Delete all contacts using the dbus service |
143 | + """ |
144 | + uids = [] |
145 | + contacts = self.query_contacts() |
146 | + for contact in contacts: |
147 | + uid = self.get_vcard_uid(contact) |
148 | + if uid: |
149 | + uids.append(uid) |
150 | + self.delete_contact(uids) |
151 | |
152 | === added file 'ubuntu_system_tests/helpers/telephony.py' |
153 | --- ubuntu_system_tests/helpers/telephony.py 1970-01-01 00:00:00 +0000 |
154 | +++ ubuntu_system_tests/helpers/telephony.py 2015-06-04 15:20:03 +0000 |
155 | @@ -0,0 +1,197 @@ |
156 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
157 | + |
158 | +# |
159 | +# Ubuntu Sanity Tests |
160 | +# Copyright (C) 2015 Canonical |
161 | +# |
162 | +# This program is free software: you can redistribute it and/or modify |
163 | +# it under the terms of the GNU General Public License as published by |
164 | +# the Free Software Foundation, either version 3 of the License, or |
165 | +# (at your option) any later version. |
166 | +# |
167 | +# This program is distributed in the hope that it will be useful, |
168 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
169 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
170 | +# GNU General Public License for more details. |
171 | +# |
172 | +# You should have received a copy of the GNU General Public License |
173 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
174 | +# |
175 | + |
176 | +import functools |
177 | +import logging |
178 | +import requests |
179 | + |
180 | +from requests.auth import HTTPBasicAuth |
181 | + |
182 | +logger = logging.getLogger(__name__) |
183 | + |
184 | +TWILIO_API_URL = "https://api.twilio.com/2010-04-01" |
185 | + |
186 | + |
187 | +class Telephony: |
188 | + |
189 | + def __init__(self, credentials, backend='twilio'): |
190 | + self._backend = _get_backend(backend)(credentials) |
191 | + |
192 | + def send_sms(self, to, from_, message): |
193 | + return self._backend.send_sms(to, from_, message) |
194 | + |
195 | + def get_sent_sms(self, to, from_, date): |
196 | + return self._backend.get_sent_sms(to, from_, date) |
197 | + |
198 | + def send_mms(self, to, from_, message, media): |
199 | + return self._backend.send_mms(to, from_, message, media) |
200 | + |
201 | + def make_phonecall(self, to, from_, hangup_timeout, voice_message): |
202 | + return self._backend.make_phonecall(to, from_, hangup_timeout, |
203 | + voice_message) |
204 | + |
205 | + |
206 | +NeedBackendError = functools.partial( |
207 | + NotImplementedError, |
208 | + "This class cannot be instantiated. Please use a specific backend." |
209 | +) |
210 | + |
211 | + |
212 | +class TelephonyBackend: |
213 | + |
214 | + def __init__(self, credentials): |
215 | + """ |
216 | + :param credentials: dictionary containing the required credential |
217 | + details specific for the backend. |
218 | + |
219 | + :raises ValueError: if any required credential details are missing. |
220 | + |
221 | + """ |
222 | + raise NeedBackendError() |
223 | + |
224 | + def send_sms(self, to, from_, message): |
225 | + raise NeedBackendError() |
226 | + |
227 | + def get_sent_sms(self, to, from_, date): |
228 | + raise NeedBackendError() |
229 | + |
230 | + def send_mms(self, to, from_, message, media): |
231 | + raise NeedBackendError() |
232 | + |
233 | + def make_phonecall(self, to, from_, hangup_timeout, voice_message): |
234 | + # Only a suggestion, not sure specifics what are required. |
235 | + raise NeedBackendError() |
236 | + |
237 | + |
238 | +class TwilioBackend(TelephonyBackend): |
239 | + """Backend that utilises the Twilio service. |
240 | + |
241 | + Required credentials are: |
242 | + - AccountSid: This represents the account id |
243 | + - AuthToken: This is the token used to authenticate the request against |
244 | + the account (Note: It must be kept secret!). |
245 | + |
246 | + """ |
247 | + |
248 | + def __init__(self, credentials): |
249 | + _raise_if_required_credentials_missing( |
250 | + credentials, 'AccountSid', 'AuthToken') |
251 | + self._account_sid = credentials['AccountSid'] |
252 | + self._account_auth = credentials['AuthToken'] |
253 | + self._http_auth = HTTPBasicAuth(self._account_sid, self._account_auth) |
254 | + |
255 | + def send_sms(self, to, from_, message): |
256 | + # Ensure recipient number meets expectations |
257 | + # (i.e. https://www.twilio.com/docs/api/rest/sending-messages#post 'To' |
258 | + # field details.) |
259 | + _raise_if_number_doesnt_look_valid(to) |
260 | + _raise_if_number_doesnt_look_valid(from_) |
261 | + url = self._get_api_url('Messages') |
262 | + params = {'From': from_, 'To': to, 'Body': message} |
263 | + response = requests.post(url, data=params, auth=self._http_auth) |
264 | + if not response.ok: |
265 | + logger.error(response.text) |
266 | + return response.ok |
267 | + |
268 | + def get_sent_sms(self, to, from_, time): |
269 | + _raise_if_number_doesnt_look_valid(to) |
270 | + _raise_if_number_doesnt_look_valid(from_) |
271 | + url = self.get_api_url('Messages') |
272 | + params = {'From': from_, 'To': to, 'DateSent': str(time.date)} |
273 | + response = requests.get(url, data=params, auth=self._http_auth) |
274 | + for message in response.json()['messages']: |
275 | + print(message) |
276 | + |
277 | + def send_mms(self, number, message, media): |
278 | + _raise_if_number_doesnt_look_valid(number) |
279 | + url = self._get_api_url('Messages') # NOQA |
280 | + |
281 | + def make_phonecall(self, number, hangup_timeout, voice_message): |
282 | + _raise_if_number_doesnt_look_valid(number) |
283 | + url = self._get_api_url('Calls') # NOQA |
284 | + |
285 | + def _get_api_url(self, action): |
286 | + """Return API URL to post to.""" |
287 | + api_url = TWILIO_API_URL + '/Accounts/{sid}/{action}.json'.format( |
288 | + sid=self._account_sid, |
289 | + action=action |
290 | + ) |
291 | + return api_url |
292 | + |
293 | + |
294 | +class FakeBackend(TelephonyBackend): |
295 | + """A verified fake for use with testing. |
296 | + |
297 | + Does not make any calls to external resources nor does it intiate any |
298 | + actual calls/messages. |
299 | + |
300 | + """ |
301 | + pass |
302 | + |
303 | + |
304 | +def _make_rest_request(url, params, auth_details): |
305 | + """Return request object containing the results of the REST request.""" |
306 | + # i.e. r = requests.post(....) |
307 | + # return r or should we check the status code here and raise an exception |
308 | + # if it's not what's expected (could be another arg.) |
309 | + pass |
310 | + |
311 | + |
312 | +def _get_backend(backend): |
313 | + """Return the requested backend class |
314 | + |
315 | + :raises ValueError: if the requested backend was not found. |
316 | + |
317 | + """ |
318 | + # i.e. return TwiloBackend (well, smarter than that) |
319 | + # The register (or whatever) could be a lot nicer too. |
320 | + |
321 | + backend_register = dict( |
322 | + twilio=TwilioBackend, |
323 | + fake=FakeBackend, |
324 | + ) |
325 | + return backend_register[backend] |
326 | + |
327 | + |
328 | +def _raise_if_number_doesnt_look_valid(number): |
329 | + """Ensure number looks valid (i.e. E.164 format). |
330 | + |
331 | + Does not ensure the number is in service etc. |
332 | + """ |
333 | + pass |
334 | + |
335 | + |
336 | +def _raise_if_required_credentials_missing(credentials, *required_keys): |
337 | + """Raise ValueError if any required keys are absent from credentials. |
338 | + |
339 | + The exception string will include a description of which keys are missing. |
340 | + |
341 | + """ |
342 | + missing_keys = [] |
343 | + for key in required_keys: |
344 | + if credentials.get(key, None) is None: |
345 | + missing_keys.append(key) |
346 | + |
347 | + if missing_keys: |
348 | + raise ValueError( |
349 | + "Missing required credential detail{plural}: '{details}'".format( |
350 | + plural='s' if len(missing_keys) > 1 else '', |
351 | + details=', '.join(missing_keys)) |
352 | + ) |
353 | |
354 | === added file 'ubuntu_system_tests/helpers/unity8/notifications.py' |
355 | --- ubuntu_system_tests/helpers/unity8/notifications.py 1970-01-01 00:00:00 +0000 |
356 | +++ ubuntu_system_tests/helpers/unity8/notifications.py 2015-06-04 15:20:03 +0000 |
357 | @@ -0,0 +1,41 @@ |
358 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
359 | + |
360 | +# |
361 | +# Ubuntu System Tests |
362 | +# Copyright (C) 2015 Canonical |
363 | +# |
364 | +# This program is free software: you can redistribute it and/or modify |
365 | +# it under the terms of the GNU General Public License version 3, |
366 | +# as published by the Free Software Foundation. |
367 | +# |
368 | +# This program is distributed in the hope that it will be useful, |
369 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
370 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
371 | +# GNU General Public License for more details. |
372 | +# |
373 | +# You should have received a copy of the GNU General Public License |
374 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
375 | +# |
376 | + |
377 | + |
378 | +import ubuntuuitoolkit |
379 | + |
380 | +from ubuntu_system_tests.helpers.autopilot import override_proxy_timeout |
381 | + |
382 | + |
383 | +class Notifications(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase): |
384 | + |
385 | + def get_current_notification(self): |
386 | + with override_proxy_timeout(self, 60): |
387 | + return self.wait_select_single( |
388 | + 'Notification', |
389 | + objectName='notification1' |
390 | + ) |
391 | + |
392 | + |
393 | +class Notification(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase): |
394 | + |
395 | + def tap_on(self): |
396 | + self.pointing_device.click_object( |
397 | + self.select_single(objectName="interactiveArea") |
398 | + ) |
399 | |
400 | === modified file 'ubuntu_system_tests/tests/base.py' |
401 | --- ubuntu_system_tests/tests/base.py 2015-06-03 17:04:45 +0000 |
402 | +++ ubuntu_system_tests/tests/base.py 2015-06-04 15:20:03 +0000 |
403 | @@ -32,6 +32,7 @@ |
404 | from unity8 import process_helpers |
405 | from unity8.shell.emulators import dash |
406 | |
407 | +from ubuntu_system_tests import config |
408 | from ubuntu_system_tests.helpers import unity8 |
409 | from ubuntu_system_tests.helpers.unity8 import shell |
410 | |
411 | @@ -88,3 +89,28 @@ |
412 | def ensure_application_closed(self, app_name): |
413 | """Stop the app before unity8 is restarted so it's not orphaned.""" |
414 | subprocess.call(['ubuntu-app-stop', app_name]) |
415 | + |
416 | + |
417 | +class BaseTelephonyTestCase(BaseUbuntuSystemTestCase): |
418 | + """Base class to be used for all telephony tests.""" |
419 | + |
420 | + def setUp(self): |
421 | + """Base class setUp method.""" |
422 | + super().setUp() |
423 | + self.config_stack = config.get_device_config_stack() |
424 | + |
425 | + def get_telephony_service_account_id(self): |
426 | + """Return account id for telephony service.""" |
427 | + return self.config_stack.get('_twilio_account_sid') |
428 | + |
429 | + def get_telephony_service_auth_token(self): |
430 | + """Return auth token for telephony service.""" |
431 | + return self.config_stack.get('_twilio_auth_token') |
432 | + |
433 | + def get_telephony_service_number(self): |
434 | + """Return the number to call and message from.""" |
435 | + return self.config_stack.get('telephony_service_number') |
436 | + |
437 | + def get_device_phone_number(self): |
438 | + """Return the number to send messages and calls to.""" |
439 | + return self.config_stack.get('device_phone_number') |
440 | |
441 | === added file 'ubuntu_system_tests/tests/test_messaging.py' |
442 | --- ubuntu_system_tests/tests/test_messaging.py 1970-01-01 00:00:00 +0000 |
443 | +++ ubuntu_system_tests/tests/test_messaging.py 2015-06-04 15:20:03 +0000 |
444 | @@ -0,0 +1,129 @@ |
445 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
446 | + |
447 | +# |
448 | +# Ubuntu System Tests |
449 | +# Copyright (C) 2015 Canonical |
450 | +# |
451 | +# This program is free software: you can redistribute it and/or modify |
452 | +# it under the terms of the GNU General Public License version 3, |
453 | +# as published by the Free Software Foundation. |
454 | +# |
455 | +# This program is distributed in the hope that it will be useful, |
456 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
457 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
458 | +# GNU General Public License for more details. |
459 | +# |
460 | +# You should have received a copy of the GNU General Public License |
461 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
462 | +# |
463 | + |
464 | +import uuid |
465 | + |
466 | +from autopilot.matchers import Eventually |
467 | +from messaging_app import emulators as messaging_emulators |
468 | +from testtools import skipUnless |
469 | +from testtools.matchers import Equals |
470 | +from ubuntuuitoolkit import emulators as toolkit_emulators |
471 | + |
472 | +from ubuntu_system_tests.helpers.addressbook import dbus_service |
473 | +from ubuntu_system_tests.helpers import autopilot as autopilot_helpers |
474 | +from ubuntu_system_tests.helpers import ofono |
475 | +from ubuntu_system_tests.helpers.telephony import Telephony |
476 | +from ubuntu_system_tests.helpers.unity8 import notifications # NOQA |
477 | +from ubuntu_system_tests.tests import base |
478 | + |
479 | +CONTACT_NAME = 'Fulano de Tal' |
480 | + |
481 | + |
482 | +class MessagingTestCase(base.BaseTelephonyTestCase): |
483 | + |
484 | + @skipUnless(ofono.is_sim_inserted(ignore_phonesim=True), 'No SIM inserted') |
485 | + def setUp(self): |
486 | + super().setUp() |
487 | + self.unity_proxy = self.launch_unity() |
488 | + self.unity_proxy.unlock() |
489 | + |
490 | + def _get_messaging_app_proxy(self): |
491 | + """Return messaging app proxy object from existing process.""" |
492 | + return autopilot_helpers.get_proxy_object_for_existing_process( |
493 | + 'messaging-app', |
494 | + toolkit_emulators.UbuntuUIToolkitEmulatorBase) |
495 | + |
496 | + def _create_temporary_contact(self): |
497 | + """ |
498 | + Create a contact in the address book using the dbus service |
499 | + and remove it in the cleanup step. |
500 | + """ |
501 | + vcard = """ |
502 | +BEGIN:VCARD |
503 | +VERSION:3.0 |
504 | +FN:{name} |
505 | +TEL;TYPE=CELL:{number} |
506 | +END:VCARD""".format(name=CONTACT_NAME, |
507 | + number=self.get_telephony_service_number()) |
508 | + self.addressbook_dbus = dbus_service.ContactsDbusService() |
509 | + contact_vcard = self.addressbook_dbus.create_contact(vcard) |
510 | + contact_uid = self.addressbook_dbus.get_vcard_uid(contact_vcard) |
511 | + self.addCleanup(self.addressbook_dbus.delete_contact, [contact_uid]) |
512 | + |
513 | + def _get_notifications_list(self): |
514 | + return self.unity_proxy.select_single( |
515 | + 'Notifications', |
516 | + objectName='notificationList' |
517 | + ) |
518 | + |
519 | + def test_receive_sms_from_contact(self): |
520 | + """ |
521 | + Prerequisite: A contact in the address book with the number you |
522 | + are sending from |
523 | + 1. From another device send an SMS to the phone number of a SIM |
524 | + card that is in the SUT |
525 | + - A notification appears containing the senders |
526 | + name and the message content. |
527 | + 2. Tap on the message notification before it disappears |
528 | + - The messaging application is opened showing all |
529 | + messages received by that sender. The message |
530 | + just sent should appear at the bottom. |
531 | + """ |
532 | + self._create_temporary_contact() |
533 | + # Get the notifications list first as we don't want to |
534 | + # waste precious time waiting for this call to return |
535 | + notifications_list = self._get_notifications_list() |
536 | + credentials = {'AccountSid': self.get_telephony_service_account_id(), |
537 | + 'AuthToken': self.get_telephony_service_auth_token()} |
538 | + tel = Telephony(credentials) |
539 | + # We use a UUID as the message body so that we know the message |
540 | + # that is received is the same one we sent. |
541 | + message_body = str(uuid.uuid1()) |
542 | + sent = tel.send_sms(self.get_device_phone_number(), |
543 | + self.get_telephony_service_number(), |
544 | + message_body) |
545 | + self.assertTrue(sent, 'The SMS was not sent succesfully by the ' |
546 | + 'telephony service.') |
547 | + # Tap on indicator when it appears and check the contents are |
548 | + # correct - message body is displayed and contact name is shown |
549 | + sms_notification = notifications_list.get_current_notification() |
550 | + self.assertThat(sms_notification.summary, |
551 | + Eventually(Equals('Message from {contact}'.format( |
552 | + contact='Fulano de Tal')))) |
553 | + self.assertThat(sms_notification.body, |
554 | + Eventually(Equals(message_body))) |
555 | + # Open the messaging app by tapping on the notification. |
556 | + # Due to launchpad.net/bugs/1457629 the following tap_on() method can |
557 | + # fail due to CPO inheritance problems in Autopilot. |
558 | + # A workaround is to select and press the object directly in the test. |
559 | + # This should be removed as soon as the Autopilot CPO bug is fixed. |
560 | + # sms_notification.tap_on() |
561 | + sms_notification.pointing_device.click_object( |
562 | + sms_notification.select_single(objectName="interactiveArea")) |
563 | + |
564 | + messaging_app = self._get_messaging_app_proxy() |
565 | + self.addCleanup(self.ensure_application_closed, 'messaging-app') |
566 | + main_view = messaging_app.select_single(messaging_emulators.MainView) |
567 | + # Confirm that the message is displayed and the header title |
568 | + # is the name of the contact |
569 | + main_view.get_message(message_body) |
570 | + self.assertThat(main_view.get_header().title, |
571 | + Eventually(Equals(CONTACT_NAME))) |
572 | + # Delete the message |
573 | + main_view.delete_message(message_body) |
FAILED: Continuous integration, rev:99 /code.launchpad .net/~canonical -platform- qa/ubuntu- system- tests/test_ receive_ sms/+merge/ 260545/ +edit-commit- message
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http:// s-jenkins. ubuntu- ci:8080/ job/ubuntu- sanity- tests-ci/ 263/ s-jenkins. ubuntu- ci:8080/ job/ubuntu- sanity- tests-wily- amd64-ci/ 34/console s-jenkins. ubuntu- ci:8080/ job/ubuntu- sanity- tests-wily- armhf-ci/ 34/console s-jenkins. ubuntu- ci:8080/ job/ubuntu- sanity- tests-wily- i386-ci/ 34/console
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- sanity- tests-ci/ 263/rebuild
http://