Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Side by Side Diff: build/android/pylib/local/device/local_device_instrumentation_test_run.py

Issue 2786773002: (Reland) Add failure screenshots and images to results detail. (Closed)
Patch Set: (Reland) Add failure screenshots and images to results detail. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import logging 5 import logging
6 import os 6 import os
7 import posixpath 7 import posixpath
8 import re 8 import re
9 import time 9 import time
10 10
11 from devil.android import device_errors 11 from devil.android import device_errors
12 from devil.android import flag_changer 12 from devil.android import flag_changer
13 from devil.android.sdk import shared_prefs 13 from devil.android.sdk import shared_prefs
14 from devil.utils import reraiser_thread 14 from devil.utils import reraiser_thread
15 from pylib import valgrind_tools 15 from pylib import valgrind_tools
16 from pylib.android import logdog_logcat_monitor 16 from pylib.android import logdog_logcat_monitor
17 from pylib.base import base_test_result 17 from pylib.base import base_test_result
18 from pylib.instrumentation import instrumentation_test_instance 18 from pylib.instrumentation import instrumentation_test_instance
19 from pylib.local.device import local_device_environment 19 from pylib.local.device import local_device_environment
20 from pylib.local.device import local_device_test_run 20 from pylib.local.device import local_device_test_run
21 from pylib.utils import google_storage_helper
21 from pylib.utils import logdog_helper 22 from pylib.utils import logdog_helper
22 from py_trace_event import trace_event 23 from py_trace_event import trace_event
23 from py_utils import contextlib_ext 24 from py_utils import contextlib_ext
25 from py_utils import tempfile_ext
24 import tombstones 26 import tombstones
25 27
26 _TAG = 'test_runner_py' 28 _TAG = 'test_runner_py'
27 29
28 TIMEOUT_ANNOTATIONS = [ 30 TIMEOUT_ANNOTATIONS = [
29 ('Manual', 10 * 60 * 60), 31 ('Manual', 10 * 60 * 60),
30 ('IntegrationTest', 30 * 60), 32 ('IntegrationTest', 30 * 60),
31 ('External', 10 * 60), 33 ('External', 10 * 60),
32 ('EnormousTest', 10 * 60), 34 ('EnormousTest', 10 * 60),
33 ('LargeTest', 5 * 60), 35 ('LargeTest', 5 * 60),
34 ('MediumTest', 3 * 60), 36 ('MediumTest', 3 * 60),
35 ('SmallTest', 1 * 60), 37 ('SmallTest', 1 * 60),
36 ] 38 ]
37 39
38 LOGCAT_FILTERS = ['*:e', 'chromium:v', 'cr_*:v'] 40 LOGCAT_FILTERS = ['*:e', 'chromium:v', 'cr_*:v']
39 41
42
40 # TODO(jbudorick): Make this private once the instrumentation test_runner is 43 # TODO(jbudorick): Make this private once the instrumentation test_runner is
41 # deprecated. 44 # deprecated.
42 def DidPackageCrashOnDevice(package_name, device): 45 def DidPackageCrashOnDevice(package_name, device):
43 # Dismiss any error dialogs. Limit the number in case we have an error 46 # Dismiss any error dialogs. Limit the number in case we have an error
44 # loop or we are failing to dismiss. 47 # loop or we are failing to dismiss.
45 try: 48 try:
46 for _ in xrange(10): 49 for _ in xrange(10):
47 package = device.DismissCrashDialogIfNeeded() 50 package = device.DismissCrashDialogIfNeeded()
48 if not package: 51 if not package:
49 return False 52 return False
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 if r.GetType() == base_test_result.ResultType.UNKNOWN: 373 if r.GetType() == base_test_result.ResultType.UNKNOWN:
371 r.SetType(base_test_result.ResultType.CRASH) 374 r.SetType(base_test_result.ResultType.CRASH)
372 375
373 # Handle failures by: 376 # Handle failures by:
374 # - optionally taking a screenshot 377 # - optionally taking a screenshot
375 # - logging the raw output at INFO level 378 # - logging the raw output at INFO level
376 # - clearing the application state while persisting permissions 379 # - clearing the application state while persisting permissions
377 if any(r.GetType() not in (base_test_result.ResultType.PASS, 380 if any(r.GetType() not in (base_test_result.ResultType.PASS,
378 base_test_result.ResultType.SKIP) 381 base_test_result.ResultType.SKIP)
379 for r in results): 382 for r in results):
380 if self._test_instance.screenshot_dir: 383 with contextlib_ext.Optional(
381 file_name = '%s-%s.png' % ( 384 tempfile_ext.NamedTemporaryDirectory(),
382 test_display_name, 385 self._test_instance.screenshot_dir is None and
383 time.strftime('%Y%m%dT%H%M%S', time.localtime())) 386 self._test_instance.gs_results_bucket) as screenshot_dir:
384 saved_dir = device.TakeScreenshot( 387 screenshot_dir = self._test_instance.screenshot_dir or screenshot_dir
the real yoland 2017/05/03 22:23:38 nit: screenshot_host_dir
mikecase (-- gone --) 2017/05/03 22:45:18 Done
385 os.path.join(self._test_instance.screenshot_dir, file_name)) 388 if screenshot_dir:
386 logging.info( 389 file_name = '%s-%s.png' % (
387 'Saved screenshot for %s to %s.', 390 test_display_name,
388 test_display_name, saved_dir) 391 time.strftime('%Y%m%dT%H%M%S', time.localtime()))
the real yoland 2017/05/03 22:23:38 same as below, should this just use UTC time?
mikecase (-- gone --) 2017/05/03 22:45:18 Done
392 screenshot_file = device.TakeScreenshot(
393 os.path.join(screenshot_dir, file_name))
394 logging.info(
395 'Saved screenshot for %s to %s.',
396 test_display_name, screenshot_file)
397 if self._test_instance.gs_results_bucket:
398 link = google_storage_helper.upload(
399 google_storage_helper.unique_name('screenshot', device=device),
400 screenshot_file,
401 bucket=self._test_instance.gs_results_bucket + '/screenshots')
402 for result in results:
403 result.SetLink('failure_screenshot', link)
404
389 logging.info('detected failure in %s. raw output:', test_display_name) 405 logging.info('detected failure in %s. raw output:', test_display_name)
390 for l in output: 406 for l in output:
391 logging.info(' %s', l) 407 logging.info(' %s', l)
392 if (not self._env.skip_clear_data 408 if (not self._env.skip_clear_data
393 and self._test_instance.package_info): 409 and self._test_instance.package_info):
394 permissions = ( 410 permissions = (
395 self._test_instance.apk_under_test.GetPermissions() 411 self._test_instance.apk_under_test.GetPermissions()
396 if self._test_instance.apk_under_test 412 if self._test_instance.apk_under_test
397 else None) 413 else None)
398 device.ClearApplicationState(self._test_instance.package_info.package, 414 device.ClearApplicationState(self._test_instance.package_info.package,
399 permissions=permissions) 415 permissions=permissions)
400
401 else: 416 else:
402 logging.debug('raw output from %s:', test_display_name) 417 logging.debug('raw output from %s:', test_display_name)
403 for l in output: 418 for l in output:
404 logging.debug(' %s', l) 419 logging.debug(' %s', l)
405 if self._test_instance.coverage_directory: 420 if self._test_instance.coverage_directory:
406 device.PullFile(coverage_directory, 421 device.PullFile(coverage_directory,
407 self._test_instance.coverage_directory) 422 self._test_instance.coverage_directory)
408 device.RunShellCommand( 423 device.RunShellCommand(
409 'rm -f %s' % posixpath.join(coverage_directory, '*'), 424 'rm -f %s' % posixpath.join(coverage_directory, '*'),
410 check_return=True, shell=True) 425 check_return=True, shell=True)
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 if k in annotations: 469 if k in annotations:
455 timeout = v 470 timeout = v
456 break 471 break
457 else: 472 else:
458 logging.warning('Using default 1 minute timeout for %s', test_name) 473 logging.warning('Using default 1 minute timeout for %s', test_name)
459 timeout = 60 474 timeout = 60
460 475
461 timeout *= cls._GetTimeoutScaleFromAnnotations(annotations) 476 timeout *= cls._GetTimeoutScaleFromAnnotations(annotations)
462 477
463 return timeout 478 return timeout
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698