OLD | NEW |
1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 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 os | 5 import os |
6 import string | 6 import string |
7 import tempfile | 7 import tempfile |
8 import unittest | 8 import unittest |
9 import json | 9 import json |
10 | 10 |
11 import mock | 11 import mock |
12 | 12 |
13 from telemetry import project_config | 13 from telemetry import project_config |
14 from telemetry.core import util | 14 from telemetry.core import util |
15 from telemetry.testing import browser_test_runner | 15 from telemetry.testing import browser_test_runner |
16 | 16 |
17 | 17 |
18 class BrowserTestRunnerTest(unittest.TestCase): | 18 class BrowserTestRunnerTest(unittest.TestCase): |
19 | 19 |
20 def baseTest(self, mockInitDependencyManager, test_filter, | 20 def baseTest(self, mockInitDependencyManager, test_filter, |
21 failures, successes): | 21 failures, successes, test_name='SimpleTest'): |
22 options = browser_test_runner.TestRunOptions() | 22 options = browser_test_runner.TestRunOptions() |
23 options.verbosity = 0 | 23 options.verbosity = 0 |
24 config = project_config.ProjectConfig( | 24 config = project_config.ProjectConfig( |
25 top_level_dir=os.path.join(util.GetTelemetryDir(), 'examples'), | 25 top_level_dir=os.path.join(util.GetTelemetryDir(), 'examples'), |
26 client_configs=['a', 'b', 'c'], | 26 client_configs=['a', 'b', 'c'], |
27 benchmark_dirs=[ | 27 benchmark_dirs=[ |
28 os.path.join(util.GetTelemetryDir(), 'examples', 'browser_tests')] | 28 os.path.join(util.GetTelemetryDir(), 'examples', 'browser_tests')] |
29 ) | 29 ) |
30 temp_file = tempfile.NamedTemporaryFile(delete=False) | 30 temp_file = tempfile.NamedTemporaryFile(delete=False) |
31 temp_file.close() | 31 temp_file.close() |
32 temp_file_name = temp_file.name | 32 temp_file_name = temp_file.name |
33 try: | 33 try: |
34 browser_test_runner.Run( | 34 browser_test_runner.Run( |
35 config, options, | 35 config, options, |
36 ['SimpleTest', | 36 [test_name, |
37 '--write-abbreviated-json-results-to=%s' % temp_file_name, | 37 '--write-abbreviated-json-results-to=%s' % temp_file_name, |
38 '--test-filter=%s' % test_filter]) | 38 '--test-filter=%s' % test_filter]) |
39 mockInitDependencyManager.assert_called_with(['a', 'b', 'c']) | 39 mockInitDependencyManager.assert_called_with(['a', 'b', 'c']) |
40 with open(temp_file_name) as f: | 40 with open(temp_file_name) as f: |
41 test_result = json.load(f) | 41 test_result = json.load(f) |
42 self.assertEquals(test_result['failures'], failures) | 42 self.assertEquals(test_result['failures'], failures) |
43 self.assertEquals(test_result['successes'], successes) | 43 self.assertEquals(test_result['successes'], successes) |
44 self.assertEquals(test_result['valid'], True) | 44 self.assertEquals(test_result['valid'], True) |
45 finally: | 45 finally: |
46 os.remove(temp_file_name) | 46 os.remove(temp_file_name) |
47 | 47 |
48 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') | 48 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') |
49 def testJsonOutputFormatNegativeFilter(self, mockInitDependencyManager): | 49 def testJsonOutputFormatNegativeFilter(self, mockInitDependencyManager): |
50 self.baseTest( | 50 self.baseTest( |
51 mockInitDependencyManager, '^(add|multiplier).*', | 51 mockInitDependencyManager, '^(add|multiplier).*', |
52 ['browser_tests.simple_numeric_test.SimpleTest.add_1_and_2', | 52 ['add_1_and_2', |
53 'browser_tests.simple_numeric_test.SimpleTest.add_7_and_3', | 53 'add_7_and_3', |
54 'browser_tests.simple_numeric_test.SimpleTest.multiplier_simple_2'], | 54 'multiplier_simple_2'], |
55 ['browser_tests.simple_numeric_test.SimpleTest.add_2_and_3', | 55 ['add_2_and_3', |
56 'browser_tests.simple_numeric_test.SimpleTest.multiplier_simple', | 56 'multiplier_simple', |
57 'browser_tests.simple_numeric_test.SimpleTest.multiplier_simple_3']) | 57 'multiplier_simple_3']) |
| 58 |
| 59 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') |
| 60 def testJsonOutputWhenSetupClassFailed(self, mockInitDependencyManager): |
| 61 self.baseTest( |
| 62 mockInitDependencyManager, '.*', |
| 63 ['setUpClass (browser_tests.failed_tests.SetUpClassFailedTest)'], |
| 64 [], test_name='SetUpClassFailedTest') |
| 65 |
| 66 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') |
| 67 def testJsonOutputWhenTearDownClassFailed(self, mockInitDependencyManager): |
| 68 self.baseTest( |
| 69 mockInitDependencyManager, '.*', |
| 70 ['tearDownClass (browser_tests.failed_tests.TearDownClassFailedTest)'], |
| 71 sorted(['dummy_test_%i' %i for i in xrange(0, 100)]), |
| 72 test_name='TearDownClassFailedTest') |
58 | 73 |
59 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') | 74 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') |
60 def testJsonOutputFormatPositiveFilter(self, mockInitDependencyManager): | 75 def testJsonOutputFormatPositiveFilter(self, mockInitDependencyManager): |
61 self.baseTest( | 76 self.baseTest( |
62 mockInitDependencyManager, '(TestSimple|TestException).*', | 77 mockInitDependencyManager, '(TestSimple|TestException).*', |
63 ['browser_tests.simple_numeric_test.SimpleTest.TestException', | 78 ['TestException', 'TestSimple'], []) |
64 'browser_tests.simple_numeric_test.SimpleTest.TestSimple'], | |
65 []) | |
66 | 79 |
67 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') | 80 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') |
68 def testExecutingTestsInSortedOrder(self, mockInitDependencyManager): | 81 def testExecutingTestsInSortedOrder(self, mockInitDependencyManager): |
69 alphabetical_tests = [] | 82 alphabetical_tests = [] |
70 prefix = 'browser_tests.simple_numeric_test.SimpleTest.Alphabetical_' | 83 prefix = 'Alphabetical_' |
71 for i in xrange(20): | 84 for i in xrange(20): |
72 alphabetical_tests.append(prefix + str(i)) | 85 alphabetical_tests.append(prefix + str(i)) |
73 for c in string.uppercase[:26]: | 86 for c in string.uppercase[:26]: |
74 alphabetical_tests.append(prefix + c) | 87 alphabetical_tests.append(prefix + c) |
75 for c in string.lowercase[:26]: | 88 for c in string.lowercase[:26]: |
76 alphabetical_tests.append(prefix + c) | 89 alphabetical_tests.append(prefix + c) |
77 alphabetical_tests.sort() | 90 alphabetical_tests.sort() |
78 self.baseTest( | 91 self.baseTest( |
79 mockInitDependencyManager, 'Alphabetical', [], alphabetical_tests) | 92 mockInitDependencyManager, 'Alphabetical', [], alphabetical_tests) |
80 | 93 |
81 def shardingRangeTestHelper(self, total_shards, num_tests): | 94 def shardingRangeTestHelper(self, total_shards, num_tests): |
82 shard_ranges = [] | 95 shard_ranges = [] |
83 for shard_index in xrange(0, total_shards): | 96 for shard_index in xrange(0, total_shards): |
84 shard_ranges.append(browser_test_runner.TestRangeForShard( | 97 shard_ranges.append(browser_test_runner._TestRangeForShard( |
85 total_shards, shard_index, num_tests)) | 98 total_shards, shard_index, num_tests)) |
86 # Make assertions about ranges | 99 # Make assertions about ranges |
87 num_tests_run = 0 | 100 num_tests_run = 0 |
88 for i in xrange(0, len(shard_ranges)): | 101 for i in xrange(0, len(shard_ranges)): |
89 cur_range = shard_ranges[i] | 102 cur_range = shard_ranges[i] |
90 if i < num_tests: | 103 if i < num_tests: |
91 self.assertGreater(cur_range[1], cur_range[0]) | 104 self.assertGreater(cur_range[1], cur_range[0]) |
92 num_tests_run += (cur_range[1] - cur_range[0]) | 105 num_tests_run += (cur_range[1] - cur_range[0]) |
93 else: | 106 else: |
94 # Not enough tests to go around all of the shards. | 107 # Not enough tests to go around all of the shards. |
(...skipping 16 matching lines...) Expand all Loading... |
111 def testShardsWithDivisibleNumTests(self, _): | 124 def testShardsWithDivisibleNumTests(self, _): |
112 for total_shards in xrange(1, 6): | 125 for total_shards in xrange(1, 6): |
113 self.shardingRangeTestHelper(total_shards, 8) | 126 self.shardingRangeTestHelper(total_shards, 8) |
114 | 127 |
115 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') | 128 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') |
116 def testShardBoundaryConditions(self, _): | 129 def testShardBoundaryConditions(self, _): |
117 self.shardingRangeTestHelper(1, 0) | 130 self.shardingRangeTestHelper(1, 0) |
118 self.shardingRangeTestHelper(1, 1) | 131 self.shardingRangeTestHelper(1, 1) |
119 self.shardingRangeTestHelper(2, 1) | 132 self.shardingRangeTestHelper(2, 1) |
120 | 133 |
121 def baseShardingTest(self, total_shards, shard_index, failures, successes): | 134 def baseShardingTest(self, total_shards, shard_index, failures, successes, |
| 135 opt_abbr_input_json_file=None, |
| 136 opt_test_filter='', |
| 137 opt_filter_tests_after_sharding=False): |
122 options = browser_test_runner.TestRunOptions() | 138 options = browser_test_runner.TestRunOptions() |
123 options.verbosity = 0 | 139 options.verbosity = 0 |
124 config = project_config.ProjectConfig( | 140 config = project_config.ProjectConfig( |
125 top_level_dir=os.path.join(util.GetTelemetryDir(), 'examples'), | 141 top_level_dir=os.path.join(util.GetTelemetryDir(), 'examples'), |
126 client_configs=['a', 'b', 'c'], | 142 client_configs=['a', 'b', 'c'], |
127 benchmark_dirs=[ | 143 benchmark_dirs=[ |
128 os.path.join(util.GetTelemetryDir(), 'examples', 'browser_tests')] | 144 os.path.join(util.GetTelemetryDir(), 'examples', 'browser_tests')] |
129 ) | 145 ) |
130 temp_file = tempfile.NamedTemporaryFile(delete=False) | 146 temp_file = tempfile.NamedTemporaryFile(delete=False) |
131 temp_file.close() | 147 temp_file.close() |
132 temp_file_name = temp_file.name | 148 temp_file_name = temp_file.name |
| 149 opt_args = [] |
| 150 if opt_abbr_input_json_file: |
| 151 opt_args += [ |
| 152 '--read-abbreviated-json-results-from=%s' % opt_abbr_input_json_file] |
| 153 if opt_test_filter: |
| 154 opt_args += [ |
| 155 '--test-filter=%s' % opt_test_filter] |
| 156 if opt_filter_tests_after_sharding: |
| 157 opt_args += ['--filter-tests-after-sharding'] |
133 try: | 158 try: |
134 browser_test_runner.Run( | 159 browser_test_runner.Run( |
135 config, options, | 160 config, options, |
136 ['SimpleShardingTest', | 161 ['SimpleShardingTest', |
137 '--write-abbreviated-json-results-to=%s' % temp_file_name, | 162 '--write-abbreviated-json-results-to=%s' % temp_file_name, |
138 '--total-shards=%d' % total_shards, | 163 '--total-shards=%d' % total_shards, |
139 '--shard-index=%d' % shard_index]) | 164 '--shard-index=%d' % shard_index] + opt_args) |
140 with open(temp_file_name) as f: | 165 with open(temp_file_name) as f: |
141 test_result = json.load(f) | 166 test_result = json.load(f) |
142 self.assertEquals(test_result['failures'], failures) | 167 self.assertEquals(test_result['failures'], failures) |
143 self.assertEquals(test_result['successes'], successes) | 168 self.assertEquals(test_result['successes'], successes) |
144 self.assertEquals(test_result['valid'], True) | 169 self.assertEquals(test_result['valid'], True) |
145 finally: | 170 finally: |
146 os.remove(temp_file_name) | 171 os.remove(temp_file_name) |
147 | 172 |
148 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') | 173 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') |
149 def testShardedTestRun(self, _): | 174 def testShardedTestRun(self, _): |
150 self.baseShardingTest(3, 0, [], [ | 175 self.baseShardingTest(3, 0, [], [ |
151 'browser_tests.simple_sharding_test.SimpleShardingTest.Test1', | 176 'Test1', |
152 'browser_tests.simple_sharding_test.SimpleShardingTest.Test2', | 177 'Test2', |
153 'browser_tests.simple_sharding_test.SimpleShardingTest.Test3', | 178 'Test3', |
154 'browser_tests.simple_sharding_test.SimpleShardingTest.passing_test_0', | 179 'passing_test_0', |
155 'browser_tests.simple_sharding_test.SimpleShardingTest.passing_test_1', | 180 'passing_test_1', |
156 ]) | 181 ]) |
157 self.baseShardingTest(3, 1, [], [ | 182 self.baseShardingTest(3, 1, [], [ |
158 'browser_tests.simple_sharding_test.SimpleShardingTest.passing_test_2', | 183 'passing_test_2', |
159 'browser_tests.simple_sharding_test.SimpleShardingTest.passing_test_3', | 184 'passing_test_3', |
160 'browser_tests.simple_sharding_test.SimpleShardingTest.passing_test_4', | 185 'passing_test_4', |
161 'browser_tests.simple_sharding_test.SimpleShardingTest.passing_test_5', | 186 'passing_test_5', |
162 ]) | 187 ]) |
163 self.baseShardingTest(3, 2, [], [ | 188 self.baseShardingTest(3, 2, [], [ |
164 'browser_tests.simple_sharding_test.SimpleShardingTest.passing_test_6', | 189 'passing_test_6', |
165 'browser_tests.simple_sharding_test.SimpleShardingTest.passing_test_7', | 190 'passing_test_7', |
166 'browser_tests.simple_sharding_test.SimpleShardingTest.passing_test_8', | 191 'passing_test_8', |
167 'browser_tests.simple_sharding_test.SimpleShardingTest.passing_test_9', | 192 'passing_test_9', |
168 ]) | 193 ]) |
| 194 |
| 195 def writeMockTestResultsFile(self): |
| 196 mock_test_results = { |
| 197 'passes': [ |
| 198 'Test1', |
| 199 'Test2', |
| 200 'Test3', |
| 201 'passing_test_0', |
| 202 'passing_test_1', |
| 203 'passing_test_2', |
| 204 'passing_test_3', |
| 205 'passing_test_4', |
| 206 'passing_test_5', |
| 207 'passing_test_6', |
| 208 'passing_test_7', |
| 209 'passing_test_8', |
| 210 'passing_test_9', |
| 211 ], |
| 212 'failures': [], |
| 213 'valid': True, |
| 214 'times': { |
| 215 'Test1': 3.0, |
| 216 'Test2': 3.0, |
| 217 'Test3': 3.0, |
| 218 'passing_test_0': 3.0, |
| 219 'passing_test_1': 2.0, |
| 220 'passing_test_2': 2.0, |
| 221 'passing_test_3': 2.0, |
| 222 'passing_test_4': 2.0, |
| 223 'passing_test_5': 1.0, |
| 224 'passing_test_6': 1.0, |
| 225 'passing_test_7': 1.0, |
| 226 'passing_test_8': 1.0, |
| 227 'passing_test_9': 0.5, |
| 228 } |
| 229 } |
| 230 temp_file = tempfile.NamedTemporaryFile(delete=False) |
| 231 temp_file.close() |
| 232 temp_file_name = temp_file.name |
| 233 with open(temp_file_name, 'w') as f: |
| 234 json.dump(mock_test_results, f) |
| 235 return temp_file_name |
| 236 |
| 237 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') |
| 238 def testSplittingShardsByTimes(self, _): |
| 239 temp_file_name = self.writeMockTestResultsFile() |
| 240 # It seems that the sorting order of the first four tests above is: |
| 241 # passing_test_0, Test1, Test2, Test3 |
| 242 # This is probably because the relative order of the "fixed" tests |
| 243 # (starting with "Test") and the generated ones ("passing_") is |
| 244 # not well defined, and the sorting is stable afterward. The |
| 245 # expectations have been adjusted for this fact. |
| 246 try: |
| 247 self.baseShardingTest( |
| 248 4, 0, [], |
| 249 ['passing_test_0', 'passing_test_1', |
| 250 'passing_test_5', 'passing_test_9'], |
| 251 temp_file_name) |
| 252 self.baseShardingTest( |
| 253 4, 1, [], |
| 254 ['Test1', 'passing_test_2', 'passing_test_6'], |
| 255 temp_file_name) |
| 256 self.baseShardingTest( |
| 257 4, 2, [], |
| 258 ['Test2', 'passing_test_3', 'passing_test_7'], |
| 259 temp_file_name) |
| 260 self.baseShardingTest( |
| 261 4, 3, [], |
| 262 ['Test3', 'passing_test_4', 'passing_test_8'], |
| 263 temp_file_name) |
| 264 finally: |
| 265 os.remove(temp_file_name) |
| 266 |
| 267 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') |
| 268 def testFilteringAfterSharding(self, _): |
| 269 temp_file_name = self.writeMockTestResultsFile() |
| 270 try: |
| 271 self.baseShardingTest( |
| 272 4, 1, [], |
| 273 ['Test1', 'passing_test_2', 'passing_test_6'], |
| 274 temp_file_name, |
| 275 opt_test_filter='(Test1|passing_test_2|passing_test_6)', |
| 276 opt_filter_tests_after_sharding=True) |
| 277 finally: |
| 278 os.remove(temp_file_name) |
| 279 |
| 280 @mock.patch('telemetry.internal.util.binary_manager.InitDependencyManager') |
| 281 def testMedianComputation(self, _): |
| 282 self.assertEquals(2.0, browser_test_runner._MedianTestTime( |
| 283 {'test1': 2.0, 'test2': 7.0, 'test3': 1.0})) |
| 284 self.assertEquals(2.0, browser_test_runner._MedianTestTime( |
| 285 {'test1': 2.0})) |
| 286 self.assertEquals(0.0, browser_test_runner._MedianTestTime({})) |
| 287 self.assertEqual(4.0, browser_test_runner._MedianTestTime( |
| 288 {'test1': 2.0, 'test2': 6.0, 'test3': 1.0, 'test4': 8.0})) |
| 289 |
OLD | NEW |