source: gtest-1.7.0/test/gtest_shuffle_test.py@ 12756

Last change on this file since 12756 was 12746, checked in by hock@…, 11 years ago

integrated the Google Testing Framework (gtest)

and wrote an Hello World test, to ensure the framework is working..

  • Property svn:executable set to *
File size: 12.3 KB
Line 
1#!/usr/bin/env python
2#
3# Copyright 2009 Google Inc. All Rights Reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9# * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following disclaimer
13# in the documentation and/or other materials provided with the
14# distribution.
15# * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31"""Verifies that test shuffling works."""
32
33__author__ = 'wan@google.com (Zhanyong Wan)'
34
35import os
36import gtest_test_utils
37
38# Command to run the gtest_shuffle_test_ program.
39COMMAND = gtest_test_utils.GetTestExecutablePath('gtest_shuffle_test_')
40
41# The environment variables for test sharding.
42TOTAL_SHARDS_ENV_VAR = 'GTEST_TOTAL_SHARDS'
43SHARD_INDEX_ENV_VAR = 'GTEST_SHARD_INDEX'
44
45TEST_FILTER = 'A*.A:A*.B:C*'
46
47ALL_TESTS = []
48ACTIVE_TESTS = []
49FILTERED_TESTS = []
50SHARDED_TESTS = []
51
52SHUFFLED_ALL_TESTS = []
53SHUFFLED_ACTIVE_TESTS = []
54SHUFFLED_FILTERED_TESTS = []
55SHUFFLED_SHARDED_TESTS = []
56
57
58def AlsoRunDisabledTestsFlag():
59 return '--gtest_also_run_disabled_tests'
60
61
62def FilterFlag(test_filter):
63 return '--gtest_filter=%s' % (test_filter,)
64
65
66def RepeatFlag(n):
67 return '--gtest_repeat=%s' % (n,)
68
69
70def ShuffleFlag():
71 return '--gtest_shuffle'
72
73
74def RandomSeedFlag(n):
75 return '--gtest_random_seed=%s' % (n,)
76
77
78def RunAndReturnOutput(extra_env, args):
79 """Runs the test program and returns its output."""
80
81 environ_copy = os.environ.copy()
82 environ_copy.update(extra_env)
83
84 return gtest_test_utils.Subprocess([COMMAND] + args, env=environ_copy).output
85
86
87def GetTestsForAllIterations(extra_env, args):
88 """Runs the test program and returns a list of test lists.
89
90 Args:
91 extra_env: a map from environment variables to their values
92 args: command line flags to pass to gtest_shuffle_test_
93
94 Returns:
95 A list where the i-th element is the list of tests run in the i-th
96 test iteration.
97 """
98
99 test_iterations = []
100 for line in RunAndReturnOutput(extra_env, args).split('\n'):
101 if line.startswith('----'):
102 tests = []
103 test_iterations.append(tests)
104 elif line.strip():
105 tests.append(line.strip()) # 'TestCaseName.TestName'
106
107 return test_iterations
108
109
110def GetTestCases(tests):
111 """Returns a list of test cases in the given full test names.
112
113 Args:
114 tests: a list of full test names
115
116 Returns:
117 A list of test cases from 'tests', in their original order.
118 Consecutive duplicates are removed.
119 """
120
121 test_cases = []
122 for test in tests:
123 test_case = test.split('.')[0]
124 if not test_case in test_cases:
125 test_cases.append(test_case)
126
127 return test_cases
128
129
130def CalculateTestLists():
131 """Calculates the list of tests run under different flags."""
132
133 if not ALL_TESTS:
134 ALL_TESTS.extend(
135 GetTestsForAllIterations({}, [AlsoRunDisabledTestsFlag()])[0])
136
137 if not ACTIVE_TESTS:
138 ACTIVE_TESTS.extend(GetTestsForAllIterations({}, [])[0])
139
140 if not FILTERED_TESTS:
141 FILTERED_TESTS.extend(
142 GetTestsForAllIterations({}, [FilterFlag(TEST_FILTER)])[0])
143
144 if not SHARDED_TESTS:
145 SHARDED_TESTS.extend(
146 GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
147 SHARD_INDEX_ENV_VAR: '1'},
148 [])[0])
149
150 if not SHUFFLED_ALL_TESTS:
151 SHUFFLED_ALL_TESTS.extend(GetTestsForAllIterations(
152 {}, [AlsoRunDisabledTestsFlag(), ShuffleFlag(), RandomSeedFlag(1)])[0])
153
154 if not SHUFFLED_ACTIVE_TESTS:
155 SHUFFLED_ACTIVE_TESTS.extend(GetTestsForAllIterations(
156 {}, [ShuffleFlag(), RandomSeedFlag(1)])[0])
157
158 if not SHUFFLED_FILTERED_TESTS:
159 SHUFFLED_FILTERED_TESTS.extend(GetTestsForAllIterations(
160 {}, [ShuffleFlag(), RandomSeedFlag(1), FilterFlag(TEST_FILTER)])[0])
161
162 if not SHUFFLED_SHARDED_TESTS:
163 SHUFFLED_SHARDED_TESTS.extend(
164 GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
165 SHARD_INDEX_ENV_VAR: '1'},
166 [ShuffleFlag(), RandomSeedFlag(1)])[0])
167
168
169class GTestShuffleUnitTest(gtest_test_utils.TestCase):
170 """Tests test shuffling."""
171
172 def setUp(self):
173 CalculateTestLists()
174
175 def testShufflePreservesNumberOfTests(self):
176 self.assertEqual(len(ALL_TESTS), len(SHUFFLED_ALL_TESTS))
177 self.assertEqual(len(ACTIVE_TESTS), len(SHUFFLED_ACTIVE_TESTS))
178 self.assertEqual(len(FILTERED_TESTS), len(SHUFFLED_FILTERED_TESTS))
179 self.assertEqual(len(SHARDED_TESTS), len(SHUFFLED_SHARDED_TESTS))
180
181 def testShuffleChangesTestOrder(self):
182 self.assert_(SHUFFLED_ALL_TESTS != ALL_TESTS, SHUFFLED_ALL_TESTS)
183 self.assert_(SHUFFLED_ACTIVE_TESTS != ACTIVE_TESTS, SHUFFLED_ACTIVE_TESTS)
184 self.assert_(SHUFFLED_FILTERED_TESTS != FILTERED_TESTS,
185 SHUFFLED_FILTERED_TESTS)
186 self.assert_(SHUFFLED_SHARDED_TESTS != SHARDED_TESTS,
187 SHUFFLED_SHARDED_TESTS)
188
189 def testShuffleChangesTestCaseOrder(self):
190 self.assert_(GetTestCases(SHUFFLED_ALL_TESTS) != GetTestCases(ALL_TESTS),
191 GetTestCases(SHUFFLED_ALL_TESTS))
192 self.assert_(
193 GetTestCases(SHUFFLED_ACTIVE_TESTS) != GetTestCases(ACTIVE_TESTS),
194 GetTestCases(SHUFFLED_ACTIVE_TESTS))
195 self.assert_(
196 GetTestCases(SHUFFLED_FILTERED_TESTS) != GetTestCases(FILTERED_TESTS),
197 GetTestCases(SHUFFLED_FILTERED_TESTS))
198 self.assert_(
199 GetTestCases(SHUFFLED_SHARDED_TESTS) != GetTestCases(SHARDED_TESTS),
200 GetTestCases(SHUFFLED_SHARDED_TESTS))
201
202 def testShuffleDoesNotRepeatTest(self):
203 for test in SHUFFLED_ALL_TESTS:
204 self.assertEqual(1, SHUFFLED_ALL_TESTS.count(test),
205 '%s appears more than once' % (test,))
206 for test in SHUFFLED_ACTIVE_TESTS:
207 self.assertEqual(1, SHUFFLED_ACTIVE_TESTS.count(test),
208 '%s appears more than once' % (test,))
209 for test in SHUFFLED_FILTERED_TESTS:
210 self.assertEqual(1, SHUFFLED_FILTERED_TESTS.count(test),
211 '%s appears more than once' % (test,))
212 for test in SHUFFLED_SHARDED_TESTS:
213 self.assertEqual(1, SHUFFLED_SHARDED_TESTS.count(test),
214 '%s appears more than once' % (test,))
215
216 def testShuffleDoesNotCreateNewTest(self):
217 for test in SHUFFLED_ALL_TESTS:
218 self.assert_(test in ALL_TESTS, '%s is an invalid test' % (test,))
219 for test in SHUFFLED_ACTIVE_TESTS:
220 self.assert_(test in ACTIVE_TESTS, '%s is an invalid test' % (test,))
221 for test in SHUFFLED_FILTERED_TESTS:
222 self.assert_(test in FILTERED_TESTS, '%s is an invalid test' % (test,))
223 for test in SHUFFLED_SHARDED_TESTS:
224 self.assert_(test in SHARDED_TESTS, '%s is an invalid test' % (test,))
225
226 def testShuffleIncludesAllTests(self):
227 for test in ALL_TESTS:
228 self.assert_(test in SHUFFLED_ALL_TESTS, '%s is missing' % (test,))
229 for test in ACTIVE_TESTS:
230 self.assert_(test in SHUFFLED_ACTIVE_TESTS, '%s is missing' % (test,))
231 for test in FILTERED_TESTS:
232 self.assert_(test in SHUFFLED_FILTERED_TESTS, '%s is missing' % (test,))
233 for test in SHARDED_TESTS:
234 self.assert_(test in SHUFFLED_SHARDED_TESTS, '%s is missing' % (test,))
235
236 def testShuffleLeavesDeathTestsAtFront(self):
237 non_death_test_found = False
238 for test in SHUFFLED_ACTIVE_TESTS:
239 if 'DeathTest.' in test:
240 self.assert_(not non_death_test_found,
241 '%s appears after a non-death test' % (test,))
242 else:
243 non_death_test_found = True
244
245 def _VerifyTestCasesDoNotInterleave(self, tests):
246 test_cases = []
247 for test in tests:
248 [test_case, _] = test.split('.')
249 if test_cases and test_cases[-1] != test_case:
250 test_cases.append(test_case)
251 self.assertEqual(1, test_cases.count(test_case),
252 'Test case %s is not grouped together in %s' %
253 (test_case, tests))
254
255 def testShuffleDoesNotInterleaveTestCases(self):
256 self._VerifyTestCasesDoNotInterleave(SHUFFLED_ALL_TESTS)
257 self._VerifyTestCasesDoNotInterleave(SHUFFLED_ACTIVE_TESTS)
258 self._VerifyTestCasesDoNotInterleave(SHUFFLED_FILTERED_TESTS)
259 self._VerifyTestCasesDoNotInterleave(SHUFFLED_SHARDED_TESTS)
260
261 def testShuffleRestoresOrderAfterEachIteration(self):
262 # Get the test lists in all 3 iterations, using random seed 1, 2,
263 # and 3 respectively. Google Test picks a different seed in each
264 # iteration, and this test depends on the current implementation
265 # picking successive numbers. This dependency is not ideal, but
266 # makes the test much easier to write.
267 [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
268 GetTestsForAllIterations(
269 {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]))
270
271 # Make sure running the tests with random seed 1 gets the same
272 # order as in iteration 1 above.
273 [tests_with_seed1] = GetTestsForAllIterations(
274 {}, [ShuffleFlag(), RandomSeedFlag(1)])
275 self.assertEqual(tests_in_iteration1, tests_with_seed1)
276
277 # Make sure running the tests with random seed 2 gets the same
278 # order as in iteration 2 above. Success means that Google Test
279 # correctly restores the test order before re-shuffling at the
280 # beginning of iteration 2.
281 [tests_with_seed2] = GetTestsForAllIterations(
282 {}, [ShuffleFlag(), RandomSeedFlag(2)])
283 self.assertEqual(tests_in_iteration2, tests_with_seed2)
284
285 # Make sure running the tests with random seed 3 gets the same
286 # order as in iteration 3 above. Success means that Google Test
287 # correctly restores the test order before re-shuffling at the
288 # beginning of iteration 3.
289 [tests_with_seed3] = GetTestsForAllIterations(
290 {}, [ShuffleFlag(), RandomSeedFlag(3)])
291 self.assertEqual(tests_in_iteration3, tests_with_seed3)
292
293 def testShuffleGeneratesNewOrderInEachIteration(self):
294 [tests_in_iteration1, tests_in_iteration2, tests_in_iteration3] = (
295 GetTestsForAllIterations(
296 {}, [ShuffleFlag(), RandomSeedFlag(1), RepeatFlag(3)]))
297
298 self.assert_(tests_in_iteration1 != tests_in_iteration2,
299 tests_in_iteration1)
300 self.assert_(tests_in_iteration1 != tests_in_iteration3,
301 tests_in_iteration1)
302 self.assert_(tests_in_iteration2 != tests_in_iteration3,
303 tests_in_iteration2)
304
305 def testShuffleShardedTestsPreservesPartition(self):
306 # If we run M tests on N shards, the same M tests should be run in
307 # total, regardless of the random seeds used by the shards.
308 [tests1] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
309 SHARD_INDEX_ENV_VAR: '0'},
310 [ShuffleFlag(), RandomSeedFlag(1)])
311 [tests2] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
312 SHARD_INDEX_ENV_VAR: '1'},
313 [ShuffleFlag(), RandomSeedFlag(20)])
314 [tests3] = GetTestsForAllIterations({TOTAL_SHARDS_ENV_VAR: '3',
315 SHARD_INDEX_ENV_VAR: '2'},
316 [ShuffleFlag(), RandomSeedFlag(25)])
317 sorted_sharded_tests = tests1 + tests2 + tests3
318 sorted_sharded_tests.sort()
319 sorted_active_tests = []
320 sorted_active_tests.extend(ACTIVE_TESTS)
321 sorted_active_tests.sort()
322 self.assertEqual(sorted_active_tests, sorted_sharded_tests)
323
324if __name__ == '__main__':
325 gtest_test_utils.Main()
Note: See TracBrowser for help on using the repository browser.