Merge lp:~rhuddie/ubuntu-autopilot-tests/video_playback_tests into lp:ubuntu-autopilot-tests/ubuntu-experience-tests

Proposed by Richard Huddie
Status: Needs review
Proposed branch: lp:~rhuddie/ubuntu-autopilot-tests/video_playback_tests
Merge into: lp:ubuntu-autopilot-tests/ubuntu-experience-tests
Diff against target: 655 lines (+609/-0)
6 files modified
debian/control (+3/-0)
setup.py (+1/-0)
ubuntu_experience_tests/tests/multimedia/__init__.py (+38/-0)
ubuntu_experience_tests/tests/multimedia/config.ini (+8/-0)
ubuntu_experience_tests/tests/multimedia/test_video_playback.py (+542/-0)
ubuntu_experience_tests/tests/multimedia/video_samples/__init__.py (+17/-0)
To merge this branch: bzr merge lp:~rhuddie/ubuntu-autopilot-tests/video_playback_tests
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Ubuntu Testcase Admins Pending
Review via email: mp+240014@code.launchpad.net

Description of the change

A new test for playing videos in the mediaplayer-app and validating playback is working.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
35. By Richard Huddie

change relative paths to run from tests directory

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
36. By Richard Huddie

update import paths

37. By Richard Huddie

Update default helpers methods and file path

38. By Richard Huddie

use parameters for defaults

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
39. By Richard Huddie

remove config file path and use default instead

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
40. By Richard Huddie

add __init__.py to samples dir

41. By Richard Huddie

add data_files to setup.py

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
42. By Richard Huddie

add file names

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
43. By Richard Huddie

use include_package_data

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
44. By Richard Huddie

read boolean value from ini

45. By Richard Huddie

add MP4 and ini using package_data, exclude src types from video list

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
46. By Richard Huddie

remove unknown --fullscreen option

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
47. By Richard Huddie

change base class and tidy

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Unmerged revisions

47. By Richard Huddie

change base class and tidy

46. By Richard Huddie

remove unknown --fullscreen option

45. By Richard Huddie

add MP4 and ini using package_data, exclude src types from video list

44. By Richard Huddie

read boolean value from ini

43. By Richard Huddie

use include_package_data

42. By Richard Huddie

add file names

41. By Richard Huddie

add data_files to setup.py

40. By Richard Huddie

add __init__.py to samples dir

39. By Richard Huddie

remove config file path and use default instead

38. By Richard Huddie

use parameters for defaults

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/control'
--- debian/control 2014-08-08 06:53:37 +0000
+++ debian/control 2014-11-03 16:07:13 +0000
@@ -22,6 +22,9 @@
22 ubuntu-ui-toolkit-autopilot,22 ubuntu-ui-toolkit-autopilot,
23 unity8-autopilot,23 unity8-autopilot,
24 url-dispatcher-tools,24 url-dispatcher-tools,
25 mediaplayer-app-autopilot,
26 python3-evdev,
27 imagemagick,
25Description: Ubuntu user experience Autopilot tests28Description: Ubuntu user experience Autopilot tests
26 This package provides a set of autopilot tests for testing29 This package provides a set of autopilot tests for testing
27 the inter-app integration under Unity830 the inter-app integration under Unity8
2831
=== modified file 'setup.py'
--- setup.py 2014-06-19 03:06:13 +0000
+++ setup.py 2014-11-03 16:07:13 +0000
@@ -32,4 +32,5 @@
32 license='GPLv3',32 license='GPLv3',
33 packages=setuptools.find_packages(),33 packages=setuptools.find_packages(),
34 test_suite='ubuntu_experience_tests.tests',34 test_suite='ubuntu_experience_tests.tests',
35 package_data={'': ['*.ini', '*.MP4'], },
35)36)
3637
=== added directory 'ubuntu_experience_tests/tests/multimedia'
=== added file 'ubuntu_experience_tests/tests/multimedia/__init__.py'
--- ubuntu_experience_tests/tests/multimedia/__init__.py 1970-01-01 00:00:00 +0000
+++ ubuntu_experience_tests/tests/multimedia/__init__.py 2014-11-03 16:07:13 +0000
@@ -0,0 +1,38 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#
3# Copyright 2014 Canonical Ltd.
4#
5# This file is part of ubuntu-experience-tests.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
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.
15#
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/>
18
19
20import os
21
22DEFAULT_CONFIG_FILE = 'config.ini'
23DEFAULT_SAMPLES_DIR = 'video_samples'
24
25
26def _get_current_dir():
27 """Return the current dir path"""
28 return os.path.dirname(__file__)
29
30
31def get_default_config_file():
32 """Return the path for the default config file"""
33 return os.path.join(_get_current_dir(), DEFAULT_CONFIG_FILE)
34
35
36def get_default_samples_dir():
37 """Return the path for the default samples directory"""
38 return os.path.join(_get_current_dir(), DEFAULT_SAMPLES_DIR)
039
=== added file 'ubuntu_experience_tests/tests/multimedia/config.ini'
--- ubuntu_experience_tests/tests/multimedia/config.ini 1970-01-01 00:00:00 +0000
+++ ubuntu_experience_tests/tests/multimedia/config.ini 2014-11-03 16:07:13 +0000
@@ -0,0 +1,8 @@
1[default]
2sample-dir =
3sample-file =
4sample-interval-sec = 0.5
5sample-check-count = 3
6timeout = 10
7run-all = no
8
09
=== added file 'ubuntu_experience_tests/tests/multimedia/test_video_playback.py'
--- ubuntu_experience_tests/tests/multimedia/test_video_playback.py 1970-01-01 00:00:00 +0000
+++ ubuntu_experience_tests/tests/multimedia/test_video_playback.py 2014-11-03 16:07:13 +0000
@@ -0,0 +1,542 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#
3# Copyright 2014 Canonical Ltd.
4#
5# This file is part of ubuntu-experience-tests.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
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.
15#
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/>
18
19import configparser
20import os
21import re
22import subprocess
23import tempfile
24import time
25from collections import deque
26from threading import Timer
27
28from autopilot import get_test_configuration
29from autopilot.display import Display
30from autopilot.matchers import Eventually
31from mediaplayer_app.emulators.main_window import MainWindow
32from testtools.matchers import Equals
33from ubuntuuitoolkit import emulators as toolkit_emulators
34from ubuntu_experience_tests import tests
35
36
37class ConfigData:
38 """Class to read config data from file and cmd line options"""
39
40 # config keys
41 KEY_SAMPLE_DIR = 'sample-dir'
42 KEY_SAMPLE_FILE = 'sample-file'
43 KEY_SAMPLE_INTERVAL = 'sample-interval-sec'
44 KEY_SAMPLE_CHECK_COUNT = 'sample-check-count'
45 KEY_TIMEOUT = 'timeout'
46 KEY_CONFIG_FILE = 'config-file'
47 KEY_CONFIG_SECTION = 'config-section'
48 KEY_RUN_ALL = 'run-all'
49 KEY_DEFAULT = 'default'
50
51 # Default configuration values
52 DEFAULT_RUN_ALL = False
53 DEFAULT_SAMPLE_INTERVAL = 1
54 DEFAULT_SAMPLE_CHECK_COUNT = 5
55 DEFAULT_TIMEOUT = 0
56 DEFAULT_SAMPLE_FILE = ''
57
58 def __init__(self, cmdline_config):
59 """Init using command line options for config file and section"""
60 # get cmdline options
61 self.cmdline_config = cmdline_config
62 # set default setup parameters
63 self.run_all = False
64 self.config_file = tests.multimedia.get_default_config_file()
65 self.config_section = self.KEY_DEFAULT
66 self.parser = configparser.ConfigParser()
67 # now load config from files and cmdline
68 self.load_config()
69
70 def load_config(self):
71 """Load the test config using command line and file"""
72 # reset the test config parameters
73 self.sample_dir = tests.multimedia.get_default_samples_dir()
74 self.sample_file = self.DEFAULT_SAMPLE_FILE
75 self.sample_interval = self.DEFAULT_SAMPLE_INTERVAL
76 self.sample_check_count = self.DEFAULT_SAMPLE_CHECK_COUNT
77 self.timeout = self.DEFAULT_TIMEOUT
78 # get config file from cmdline options if specified
79 self.get_custom_config_from_cmdline()
80 # now read config from file
81 self.get_test_config_from_file()
82 # finally overwrite config with any cmdline options
83 self.get_test_config_from_cmdline()
84
85 def get_custom_config_from_cmdline(self):
86 """Read the custom config options from cmd line parameters"""
87 # Get config-file and config-section from cmd line options
88 if self.KEY_CONFIG_FILE in self.cmdline_config:
89 self.config_file = self.cmdline_config[self.KEY_CONFIG_FILE]
90 if self.KEY_CONFIG_SECTION in self.cmdline_config:
91 self.config_section = self.cmdline_config[self.KEY_CONFIG_SECTION]
92 # Read the specified config file
93 self.parser.read(self.config_file)
94 # now get run-all parameter. check cmdline first, then file
95 if self.KEY_RUN_ALL in self.cmdline_config:
96 self.run_all = True
97 elif self.KEY_RUN_ALL in self.parser[self.config_section]:
98 if self.parser[self.config_section].getboolean(self.KEY_RUN_ALL):
99 self.run_all = True
100
101 def get_test_config_from_cmdline(self):
102 """Read test parameters from cmd line options"""
103 if self.KEY_SAMPLE_DIR in self.cmdline_config:
104 self.sample_dir = self.cmdline_config[self.KEY_SAMPLE_DIR]
105 self.sample_file = ''
106 if self.KEY_SAMPLE_FILE in self.cmdline_config:
107 self.sample_file = self.cmdline_config[self.KEY_SAMPLE_FILE]
108 # if a file is specified, then remove the directory config,
109 # otherwise this will take priority
110 self.sample_dir = ''
111 if self.KEY_SAMPLE_INTERVAL in self.cmdline_config:
112 self.sample_interval = int(
113 self.cmdline_config[self.KEY_SAMPLE_INTERVAL])
114 if self.KEY_SAMPLE_CHECK_COUNT in self.cmdline_config:
115 self.sample_check_count = int(
116 self.cmdline_config[self.KEY_SAMPLE_CHECK_COUNT])
117 if self.KEY_TIMEOUT in self.cmdline_config:
118 self.timeout = int(self.cmdline_config[self.KEY_TIMEOUT])
119
120 def get_test_config_from_file(self):
121 """Read test parameters from config file"""
122 if self.KEY_SAMPLE_DIR in self.parser[self.config_section]:
123 val = self.parser[self.config_section][self.KEY_SAMPLE_DIR]
124 if len(val) > 0:
125 self.sample_dir = val
126 self.sample_file = ''
127 if self.KEY_SAMPLE_FILE in self.parser[self.config_section]:
128 val = self.parser[self.config_section][self.KEY_SAMPLE_FILE]
129 if len(val) > 0:
130 self.sample_file = val
131 # if a file is specified, then remove the directory config,
132 # otherwise this will take priority
133 self.sample_dir = ''
134 if self.KEY_SAMPLE_INTERVAL in self.parser[self.config_section]:
135 val = self.parser[self.config_section][self.KEY_SAMPLE_INTERVAL]
136 if len(val) > 0:
137 self.sample_interval = float(val)
138 if self.KEY_SAMPLE_CHECK_COUNT in self.parser[self.config_section]:
139 val = self.parser[self.config_section][self.KEY_SAMPLE_CHECK_COUNT]
140 if len(val) > 0:
141 self.sample_check_count = int(val)
142 if self.KEY_TIMEOUT in self.parser[self.config_section]:
143 val = self.parser[self.config_section][self.KEY_TIMEOUT]
144 if len(val) > 0:
145 self.timeout = int(val)
146
147
148class VideoPlaybackTestCase(tests.UbuntuExperienceTestCase):
149 """Autopilot test suite for playing videos in Mediaplayer-app"""
150
151 def setUp(self):
152 """Setup test suite"""
153 super(VideoPlaybackTestCase, self).setUp()
154 self.pointing_device = toolkit_emulators.get_pointing_device()
155 # calculate screen crop area based on device geometry
156 self.crop_area = self.get_crop_area()
157 # create config data using any command line options
158 self.config = ConfigData(get_test_configuration())
159
160 def start_timer(self):
161 """Start a timer if a time limit has been set"""
162 if self.is_timeout_set():
163 self.test_timer = Timer(self.config.timeout, self.on_timeout)
164 self.test_timer.start()
165
166 def cancel_timer_if_active(self):
167 """Cancel timer if it is set and still running"""
168 if self.is_timeout_set() and not self.timeout:
169 self.test_timer.cancel()
170
171 def on_timeout(self):
172 """Timer timeout event handler"""
173 # Flag that a timeout has occured
174 self.timeout = True
175
176 def is_timeout_set(self):
177 """
178 Decide whether a timeout is required
179 :return: True if timeout is set
180 False otherwise
181 """
182 ret = False
183 if self.config.timeout > 0:
184 ret = True
185 return ret
186
187 def open_media_player_app(self, sample_file):
188 """
189 Open media player app with the specified sample file
190 :param sample_file: Path to file to open
191 """
192 app = self.launch_test_application(
193 "mediaplayer-app",
194 sample_file,
195 "--desktop_file_hint="
196 "/usr/share/applications/mediaplayer-app.desktop",
197 app_type='qt')
198 self.player = MainWindow(app).get_player()
199 self.assertThat(self.player.playing, Eventually(Equals(True)))
200
201 def close_media_player_app(self):
202 """Close the running mediaplayer-app instance"""
203 out = subprocess.check_output(['pidof', '-s', 'mediaplayer-app'])
204 pid = out.decode().strip()
205 subprocess.check_call(['kill', '-9', pid])
206
207 def is_playing(self):
208 """
209 Check if the media player is currently playing video
210 :return: True if it is playing, False otherwise
211 """
212 return self.player.playing
213
214 def get_rgba_screenshot(self, target_file):
215 """
216 Take a screenshot in rgba format
217 :return: Path of screenshot rgba file
218 """
219 try:
220 subprocess.check_call([
221 'mirscreencast',
222 '-m', '/run/mir_socket',
223 '-n', '1',
224 '-f', target_file
225 ])
226 except FileNotFoundError as e:
227 e.args += ("The utility 'mirscreencast' is not available.", )
228 raise
229 except subprocess.CalledProcessError as e:
230 e.args += ("Failed to take screenshot.", )
231 raise
232
233 def convert_rgba_image(self, rgba_source_file, target_file):
234 """
235 Convert rgba file to PNG target file
236 :param rgba_source_file: Path to rgba source image
237 :param target_file: Path to PNG target file
238 """
239 try:
240 subprocess.check_call([
241 'convert',
242 '-alpha', 'off',
243 '-depth', '8',
244 '-size', '540x960',
245 'rgba:{}[0]'.format(rgba_source_file),
246 target_file
247 ])
248 except FileNotFoundError as e:
249 e.args += ("'convert' is not available, install imagemagick.", )
250 raise
251 except subprocess.CalledProcessError as e:
252 e.args += ("Failed to convert screenshot to png format.", )
253 raise
254
255 def get_screenshot(self):
256 """
257 Take screen shot and return file path of png file
258 :return: Path of PNG screen image file
259 """
260 timestamp = int(time.time())
261 filename_rgba = 'screenshot-{}.rgba'.format(timestamp)
262 filename_png = 'screenshot-{}.png'.format(timestamp)
263 temp_dir = tempfile.gettempdir()
264 filepath_rgba = os.path.join(temp_dir, filename_rgba)
265 filepath_png = os.path.join(temp_dir, filename_png)
266 self.get_rgba_screenshot(filepath_rgba)
267 self.convert_rgba_image(filepath_rgba, filepath_png)
268 # finished with rgba file so delete it
269 os.remove(filepath_rgba)
270 return filepath_png
271
272 def get_crop_area(self):
273 """
274 Calculate the crop area at centre of screen in pixel format
275 [width]x[height]+[x_start]+[y_start]
276 :return: Crop area measured in pixels
277 """
278 crop_fmt = '{0}x{1}+{2}+{3}'
279 width = 100
280 height = 100
281 display = Display.create()
282 centre_x = display.get_screen_width() // 2
283 centre_y = display.get_screen_height() // 2
284 x_start = centre_x - (width // 2)
285 y_start = centre_y - (height // 2)
286 crop_str = crop_fmt.format(width, height, x_start, y_start)
287 return crop_str
288
289 def crop_screenshot(self, source_file):
290 """
291 Crop the screen shot and return path for cropped image
292 :param source_file: Path of image file to crop
293 :return: Path of cropped image file
294 """
295 split_path = os.path.splitext(source_file)
296 path = split_path[0]
297 ext = split_path[1]
298 crop_file_path = '{0}_crop{1}'.format(path, ext)
299
300 try:
301 subprocess.check_call([
302 'convert',
303 source_file,
304 '-crop', self.crop_area,
305 crop_file_path
306 ])
307 except FileNotFoundError as e:
308 e.args += ("The utility 'convert' is not available.", )
309 raise
310 except subprocess.CalledProcessError as e:
311 e.args += ("Failed to crop screenshot.", )
312 raise
313 return crop_file_path
314
315 def get_average_colour(self, source_file):
316 """
317 Calculate the average colour of the specified image
318 """
319 try:
320 ret = subprocess.check_output([
321 'convert',
322 source_file,
323 '-resize', '1x1',
324 'txt:'
325 ])
326 except FileNotFoundError as e:
327 e.args += ("The utility 'convert' is not available.", )
328 raise
329 except subprocess.CalledProcessError as e:
330 e.args += ("Failed to get average colour.", )
331 raise
332 return self.get_hex_colour_code(ret.decode())
333
334 def get_hex_colour_code(self, colour_string):
335 """
336 Get the hex colour code from the specified colour string
337 :param colour_string: String representing colour output
338 :return: Hex representation of colour code
339 """
340 colour_pattern = re.compile(r'^#.*#(.*?)\s+.*$',
341 re.IGNORECASE | re.DOTALL)
342 hex_code = None
343 match = colour_pattern.search(colour_string)
344 if match:
345 hex_code = match.group(1)
346 return hex_code
347
348 def capture_and_check_frames_whilst_playing(self):
349 """
350 Capture and check screen frames during playback
351 :return: True if playback completes, or timeout is reached.
352 False if the screen is frozen and video doesn't play'
353 """
354 # frame_colours is a FIFO queue which holds the required number of
355 # colour samples
356 frame_colours = deque(maxlen=self.config.sample_check_count)
357 timer_started = False
358 self.timeout = False
359 while self.player.playing:
360 if self.is_timeout_set() and not timer_started:
361 # start the timer if required once playback has started
362 self.start_timer()
363 timer_started = True
364 # take screenshot
365 screenshot = self.get_screenshot()
366 # store the frame colour
367 frame_colours.append(self.calculate_frame_colour(screenshot))
368 # no longer need the screenshot file so delete it
369 os.remove(screenshot)
370 # check frames to make sure playback is working
371 if not self.check_frame_colours(frame_colours):
372 # playback error, so exit now
373 self.cancel_timer_if_active()
374 return False
375 # wait for required interval period, checking for timeouts
376 # at 0.1 second intervals
377 # The sample interval is defined in seconds (e.g. 0.5 sec),
378 # so multiply by 10 to get required number of 0.1 second waits
379 # Note: Sample period could be large (e.g. several minutes)
380 # for long running tests, so there is a need to check for timeouts
381 # between the sample interval.
382 for count in range(int(self.config.sample_interval * 10)):
383 time.sleep(0.1)
384 # check if a timeout has occured
385 if self.timeout:
386 # timeout has triggered, so exit now
387 # this is not considered a failure
388 # no need to cancel the timer as it has triggered
389 return True
390 # playback has completed with no timeout
391 self.cancel_timer_if_active()
392 return True
393
394 def calculate_frame_colour(self, frame):
395 """
396 Calculate the colour of the centre of the specified image
397 :param frame: Path to image file
398 :return: Average colour of centre of image
399 """
400 # crop to the centre of the image
401 crop = self.crop_screenshot(frame)
402 # get colour of cropped area
403 colour = self.get_average_colour(crop)
404 # now delete cropped file
405 os.remove(crop)
406 return colour
407
408 def check_frame_colours(self, frame_colours):
409 """
410 Analyse the frame colours to check that playback is working
411 :param frame_colours: dequeue object containing frame colours
412 :return: True if frame colours are changing
413 False if all the framecolours are the same
414 """
415 frames_ok = True
416 for colour in frame_colours:
417 # count the number of occurances of current colour in the
418 # previous colours
419 if frame_colours.count(colour) is frame_colours.maxlen:
420 # all the frames are same colour, so this is a fail
421 frames_ok = False
422 break
423 return frames_ok
424
425 def is_excluded_file(self, file_path):
426 """
427 Determine whether the specified file is an excluded type
428 :param file_path: Path of the specified file
429 :return: True if the file is an excluded type, false otherwise
430 """
431 # list of file extensions to ignore
432 excluded_list = ['.py', '.pyc', '.py~']
433 file_ext = os.path.splitext(file_path)[1]
434 excluded = False
435 if file_ext in excluded_list:
436 excluded = True
437 return excluded
438
439 def get_sample_files_from_dir(self, sample_dir):
440 """
441 Recursively search the specified directory for files to test
442 :param sample_dir: Top level directory to search
443 :return: List containing path of all sub-files
444 """
445 file_list = []
446 for root, dirs, files in os.walk(sample_dir):
447 for file in files:
448 # remove any excluded types of file
449 if not self.is_excluded_file(file):
450 file_list.append(os.path.abspath(os.path.join(root, file)))
451 return file_list
452
453 def get_sample_file_list(self):
454 """
455 Based on supplied config get the list of files to test
456 :return: List of files required for the current test
457 """
458 # get the list of video sample files to play, based on the test config
459 sample_files = []
460 if self.config.sample_dir:
461 # get the files from the specified directory
462 sample_files = self.get_sample_files_from_dir(
463 self.config.sample_dir)
464 elif self.config.sample_file:
465 # use the specified file
466 sample_files.append(self.config.sample_file)
467 return sample_files
468
469 def play_and_sample_video(self, file_path):
470 """
471 Play the specified sample file in the mediaplayer-app
472 :param file_path: Path to video file to launch in mediaplayer-app
473 :return: True if playback comleted successfully
474 False if playback didn't complete successfully
475 """
476 # launch media player app
477 self.open_media_player_app(file_path)
478 # capture video frames
479 # This call will run until playback is completed
480 # timeout is reached, or a freeze is detected
481 result = self.capture_and_check_frames_whilst_playing()
482 # close the media app
483 self.close_media_player_app()
484 return result
485
486 def print_failures(self, failures):
487 """
488 Print out a list of failed video files
489 :param failures: List containing path of all failed video files
490 """
491 divider = '-----------------------------------------------------------'
492 fail_count = len(failures)
493 if fail_count > 0:
494 print((divider))
495 print(('{} failures:'.format(fail_count)))
496 print((divider))
497 for failure in failures:
498 print((' {}'.format(failure)))
499 print((divider))
500
501 def test_video_playback_from_samples(self):
502 """
503 Test to play video files based on test config
504 """
505 failures = []
506 sections = []
507 if self.config.run_all:
508 # run through every config section in the config file
509 sections = self.config.parser.sections()
510 else:
511 # only use the specified config section
512 sections.append(self.config.config_section)
513
514 for section in sections:
515 # copy the current section into the config
516 self.config.config_section = section
517 # now update config for current section
518 self.config.load_config()
519 # run the test for this section
520 video_files = self.get_sample_file_list()
521 for video in video_files:
522 # play all of the samples before checking results
523 start_time = time.time()
524 result = self.play_and_sample_video(video)
525 if not result:
526 # record failure time
527 end_time = time.time()
528 elapsed = time.gmtime(end_time - start_time)
529 elapsed_str = time.strftime("%H:%M:%S", elapsed)
530 # print time of failure with file name
531 failures.append(' {0} {1}'.format(elapsed_str, video))
532 # take a screenshot of the failure with name of video file
533 # this will be added to the test details by autopilot
534 video_file, video_ext = os.path.splitext(
535 os.path.split(video)[1])
536 screenshot_name = '{0}-{1}{2}'.format(
537 video_file, elapsed_str, video_ext)
538 self.take_screenshot(screenshot_name)
539
540 self.print_failures(failures)
541 # fail the test if there were any failures
542 self.assertThat(len(failures), Equals(0))
0543
=== added directory 'ubuntu_experience_tests/tests/multimedia/video_samples'
=== added file 'ubuntu_experience_tests/tests/multimedia/video_samples/__init__.py'
--- ubuntu_experience_tests/tests/multimedia/video_samples/__init__.py 1970-01-01 00:00:00 +0000
+++ ubuntu_experience_tests/tests/multimedia/video_samples/__init__.py 2014-11-03 16:07:13 +0000
@@ -0,0 +1,17 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#
3# Copyright 2014 Canonical Ltd.
4#
5# This file is part of ubuntu-experience-tests.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License version 3, as published
9# by the Free Software Foundation.
10#
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.
15#
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/>
018
=== added file 'ubuntu_experience_tests/tests/multimedia/video_samples/big_buck_bunny_480p_H264_AAC_25fps_1800K_short.MP4'
1Binary files ubuntu_experience_tests/tests/multimedia/video_samples/big_buck_bunny_480p_H264_AAC_25fps_1800K_short.MP4 1970-01-01 00:00:00 +0000 and ubuntu_experience_tests/tests/multimedia/video_samples/big_buck_bunny_480p_H264_AAC_25fps_1800K_short.MP4 2014-11-03 16:07:13 +0000 differ19Binary files ubuntu_experience_tests/tests/multimedia/video_samples/big_buck_bunny_480p_H264_AAC_25fps_1800K_short.MP4 1970-01-01 00:00:00 +0000 and ubuntu_experience_tests/tests/multimedia/video_samples/big_buck_bunny_480p_H264_AAC_25fps_1800K_short.MP4 2014-11-03 16:07:13 +0000 differ
=== added file 'ubuntu_experience_tests/tests/multimedia/video_samples/big_buck_bunny_720p_H264_AAC_25fps_3400K_short.MP4'
2Binary files ubuntu_experience_tests/tests/multimedia/video_samples/big_buck_bunny_720p_H264_AAC_25fps_3400K_short.MP4 1970-01-01 00:00:00 +0000 and ubuntu_experience_tests/tests/multimedia/video_samples/big_buck_bunny_720p_H264_AAC_25fps_3400K_short.MP4 2014-11-03 16:07:13 +0000 differ20Binary files ubuntu_experience_tests/tests/multimedia/video_samples/big_buck_bunny_720p_H264_AAC_25fps_3400K_short.MP4 1970-01-01 00:00:00 +0000 and ubuntu_experience_tests/tests/multimedia/video_samples/big_buck_bunny_720p_H264_AAC_25fps_3400K_short.MP4 2014-11-03 16:07:13 +0000 differ

Subscribers

People subscribed via source and target branches