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

Side by Side Diff: build/android/pylib/instrumentation/instrumentation_test_instance.py

Issue 938883002: [Android] Rework instrumentation test skipping and result generation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 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 pickle 7 import pickle
8 import re 8 import re
9 import sys 9 import sys
10 10
11 from pylib import cmd_helper 11 from pylib import cmd_helper
12 from pylib import constants 12 from pylib import constants
13 from pylib import flag_changer 13 from pylib import flag_changer
14 from pylib.base import base_test_result 14 from pylib.base import base_test_result
15 from pylib.base import test_instance 15 from pylib.base import test_instance
16 from pylib.instrumentation import test_result 16 from pylib.instrumentation import test_result
17 from pylib.instrumentation import instrumentation_parser 17 from pylib.instrumentation import instrumentation_parser
18 from pylib.utils import apk_helper 18 from pylib.utils import apk_helper
19 from pylib.utils import md5sum 19 from pylib.utils import md5sum
20 from pylib.utils import proguard 20 from pylib.utils import proguard
21 21
22 sys.path.append( 22 sys.path.append(
23 os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', 'common')) 23 os.path.join(constants.DIR_SOURCE_ROOT, 'build', 'util', 'lib', 'common'))
24 import unittest_util 24 import unittest_util
25 25
26 # Ref: http://developer.android.com/reference/android/app/Activity.html
27 _ACTIVITY_RESULT_CANCELED = 0
28 _ACTIVITY_RESULT_OK = -1
29
26 _DEFAULT_ANNOTATIONS = [ 30 _DEFAULT_ANNOTATIONS = [
27 'Smoke', 'SmallTest', 'MediumTest', 'LargeTest', 31 'Smoke', 'SmallTest', 'MediumTest', 'LargeTest',
28 'EnormousTest', 'IntegrationTest'] 32 'EnormousTest', 'IntegrationTest']
29 _NATIVE_CRASH_RE = re.compile('native crash', re.IGNORECASE) 33 _NATIVE_CRASH_RE = re.compile('native crash', re.IGNORECASE)
30 _PICKLE_FORMAT_VERSION = 10 34 _PICKLE_FORMAT_VERSION = 10
31 35
32 36
33 # TODO(jbudorick): Make these private class methods of 37 # TODO(jbudorick): Make these private class methods of
34 # InstrumentationTestInstance once the instrumentation test_runner is 38 # InstrumentationTestInstance once the instrumentation test_runner is
35 # deprecated. 39 # deprecated.
(...skipping 11 matching lines...) Expand all
47 - the status code as an integer 51 - the status code as an integer
48 - the bundle dump as a dict mapping string keys to a list of 52 - the bundle dump as a dict mapping string keys to a list of
49 strings, one for each line. 53 strings, one for each line.
50 """ 54 """
51 parser = instrumentation_parser.InstrumentationParser(raw_output) 55 parser = instrumentation_parser.InstrumentationParser(raw_output)
52 statuses = list(parser.IterStatus()) 56 statuses = list(parser.IterStatus())
53 code, bundle = parser.GetResult() 57 code, bundle = parser.GetResult()
54 return (code, bundle, statuses) 58 return (code, bundle, statuses)
55 59
56 60
57 def GenerateTestResult(test_name, instr_statuses, start_ms, duration_ms): 61 def GenerateTestResults(
58 """Generate the result of |test| from |instr_statuses|. 62 result_code, result_bundle, statuses, start_ms, duration_ms):
63 """Generate test results from |statuses|.
59 64
60 Args: 65 Args:
61 test_name: The name of the test as "class#method" 66 result_code: The overall status code as an integer.
62 instr_statuses: A list of 2-tuples containing: 67 result_bundle: The summary bundle dump as a dict.
68 statuses: A list of 2-tuples containing:
63 - the status code as an integer 69 - the status code as an integer
64 - the bundle dump as a dict mapping string keys to string values 70 - the bundle dump as a dict mapping string keys to string values
65 Note that this is the same as the third item in the 3-tuple returned by 71 Note that this is the same as the third item in the 3-tuple returned by
66 |_ParseAmInstrumentRawOutput|. 72 |_ParseAmInstrumentRawOutput|.
67 start_ms: The start time of the test in milliseconds. 73 start_ms: The start time of the test in milliseconds.
68 duration_ms: The duration of the test in milliseconds. 74 duration_ms: The duration of the test in milliseconds.
75
69 Returns: 76 Returns:
70 An InstrumentationTestResult object. 77 A list containing an instance of InstrumentationTestResult for each test
78 parsed.
71 """ 79 """
72 log = ''
73 result_type = base_test_result.ResultType.UNKNOWN
74 80
75 for status_code, bundle in instr_statuses: 81 results = []
82
83 current_result = None
84
85 for status_code, bundle in statuses:
86 test_class = bundle.get('class', '')
87 test_method = bundle.get('test', '')
88 if test_class and test_method:
89 test_name = '%s#%s' % (test_class, test_method)
90 else:
91 continue
92
76 if status_code == instrumentation_parser.STATUS_CODE_START: 93 if status_code == instrumentation_parser.STATUS_CODE_START:
77 pass 94 if current_result:
78 elif status_code == instrumentation_parser.STATUS_CODE_OK: 95 results.append(current_result)
79 bundle_test = '%s#%s' % (bundle.get('class', ''), bundle.get('test', '')) 96 current_result = test_result.InstrumentationTestResult(
80 skipped = bundle.get('test_skipped', '') 97 test_name, base_test_result.ResultType.UNKNOWN, start_ms, duration_ms)
98 else:
99 if status_code == instrumentation_parser.STATUS_CODE_OK:
100 if bundle.get('test_skipped', '').lower() in ('true', '1', 'yes'):
101 current_result.SetType(base_test_result.ResultType.SKIP)
102 elif current_result.GetType() == base_test_result.ResultType.UNKNOWN:
103 current_result.SetType(base_test_result.ResultType.PASS)
104 else:
105 if status_code not in (instrumentation_parser.STATUS_CODE_ERROR,
106 instrumentation_parser.STATUS_CODE_FAILURE):
107 logging.error('Unrecognized status code %d. Handling as an error.',
108 status_code)
109 current_result.SetType(base_test_result.ResultType.FAIL)
110 if 'stack' in bundle:
111 current_result.SetLog(bundle['stack'])
81 112
82 if (test_name == bundle_test and 113 if current_result:
83 result_type == base_test_result.ResultType.UNKNOWN): 114 if current_result.GetType() == base_test_result.ResultType.UNKNOWN:
84 result_type = base_test_result.ResultType.PASS 115 crashed = (result_code == _ACTIVITY_RESULT_CANCELED
85 elif skipped.lower() in ('true', '1', 'yes'): 116 and any(_NATIVE_CRASH_RE.search(l)
86 result_type = base_test_result.ResultType.SKIP 117 for l in result_bundle.itervalues()))
87 logging.info('Skipped ' + test_name) 118 if crashed:
88 else: 119 current_result.SetType(base_test_result.ResultType.CRASH)
89 if status_code not in (instrumentation_parser.STATUS_CODE_ERROR,
90 instrumentation_parser.STATUS_CODE_FAILURE):
91 logging.error('Unrecognized status code %d. Handling as an error.',
92 status_code)
93 result_type = base_test_result.ResultType.FAIL
94 if 'stack' in bundle:
95 log = bundle['stack']
96 120
97 return test_result.InstrumentationTestResult( 121 results.append(current_result)
98 test_name, result_type, start_ms, duration_ms, log=log) 122
123 return results
99 124
100 125
101 class InstrumentationTestInstance(test_instance.TestInstance): 126 class InstrumentationTestInstance(test_instance.TestInstance):
102 127
103 def __init__(self, args, isolate_delegate, error_func): 128 def __init__(self, args, isolate_delegate, error_func):
104 super(InstrumentationTestInstance, self).__init__() 129 super(InstrumentationTestInstance, self).__init__()
105 130
106 self._apk_under_test = None 131 self._apk_under_test = None
107 self._package_info = None 132 self._package_info = None
108 self._test_apk = None 133 self._test_apk = None
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 a = dict(c['annotations']) 439 a = dict(c['annotations'])
415 a.update(m['annotations']) 440 a.update(m['annotations'])
416 inflated_tests.append({ 441 inflated_tests.append({
417 'class': c['class'], 442 'class': c['class'],
418 'method': m['method'], 443 'method': m['method'],
419 'annotations': a, 444 'annotations': a,
420 }) 445 })
421 return inflated_tests 446 return inflated_tests
422 447
423 @staticmethod 448 @staticmethod
424 def GenerateMultiTestResult(errors, statuses):
425 results = []
426 skip_counter = 1
427 for status_code, bundle in statuses:
428 if status_code != instrumentation_parser.STATUS_CODE_START:
429 # TODO(rnephew): Make skipped tests still output test name. This is only
430 # there to give skipped tests a unique name so they are counted
431 if 'test_skipped' in bundle:
432 test_name = str(skip_counter)
433 skip_counter += 1
434 else:
435 test_name = '%s#%s' % (bundle.get('class', ''),
436 bundle.get('test', ''))
437
438 results.append(
439 GenerateTestResult(test_name, [(status_code, bundle)], 0, 0))
440 for error in errors.itervalues():
441 if _NATIVE_CRASH_RE.search(error):
442 results.append(
443 base_test_result.BaseTestResult(
444 'Crash detected', base_test_result.ResultType.CRASH))
445
446 return results
447
448 @staticmethod
449 def ParseAmInstrumentRawOutput(raw_output): 449 def ParseAmInstrumentRawOutput(raw_output):
450 return ParseAmInstrumentRawOutput(raw_output) 450 return ParseAmInstrumentRawOutput(raw_output)
451 451
452 @staticmethod 452 @staticmethod
453 def GenerateTestResult(test_name, instr_statuses, start_ms, duration_ms): 453 def GenerateTestResults(
454 return GenerateTestResult(test_name, instr_statuses, start_ms, duration_ms) 454 result_code, result_bundle, statuses, start_ms, duration_ms):
455 return GenerateTestResults(result_code, result_bundle, statuses,
456 start_ms, duration_ms)
455 457
456 #override 458 #override
457 def TearDown(self): 459 def TearDown(self):
458 if self._isolate_delegate: 460 if self._isolate_delegate:
459 self._isolate_delegate.Clear() 461 self._isolate_delegate.Clear()
460 462
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698