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

Side by Side Diff: chrome/test/mini_installer/test_installer.py

Issue 22480002: Use unittest framework in the Automated Installer Testing Framework. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Try to fix 'old chunk mismatch' error in diff. Created 7 years, 4 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 2013 The Chromium Authors. All rights reserved. 1 # Copyright 2013 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 """This script tests the installer with test cases specified in the config file. 5 """This script tests the installer with test cases specified in the config file.
6 6
7 For each test case, it checks that the machine states after the execution of 7 For each test case, it checks that the machine states after the execution of
8 each command match the expected machine states. For more details, take a look at 8 each command match the expected machine states. For more details, take a look at
9 the design documentation at http://goo.gl/Q0rGM6 9 the design documentation at http://goo.gl/Q0rGM6
10 """ 10 """
11 11
12 import argparse 12 import argparse
13 import json 13 import json
14 import os 14 import os
15 import subprocess 15 import subprocess
16 import unittest
16 17
17 import settings
18 import verifier 18 import verifier
19 19
20 20
21 class Config: 21 class Config:
22 """Describes the machine states, actions, and test cases. 22 """Describes the machine states, actions, and test cases.
23 23
24 A state is a dictionary where each key is a verifier's name and the 24 A state is a dictionary where each key is a verifier's name and the
25 associated value is the input to that verifier. An action is a shorthand for 25 associated value is the input to that verifier. An action is a shorthand for
26 a command. A test is array of alternating state names and action names, 26 a command. A test is array of alternating state names and action names,
27 starting and ending with state names. An instance of this class stores a map 27 starting and ending with state names. An instance of this class stores a map
28 from state names to state objects, a map from action names to commands, and 28 from state names to state objects, a map from action names to commands, and
29 an array of test objects. 29 an array of test objects.
30 """ 30 """
31 def __init__(self): 31 def __init__(self):
32 self.states = {} 32 self.states = {}
33 self.actions = {} 33 self.actions = {}
34 self.tests = [] 34 self.tests = []
35 35
36 36
37 class InstallerTest(unittest.TestCase):
38 """Tests a test case in the config file."""
39
40 def __init__(self, test, config):
41 """Constructor.
42
43 Args:
44 test: An array of alternating state names and action names, starting and
45 ending with state names.
46 config: The Config object.
47 """
48 super(InstallerTest, self).__init__()
49 self.test = test
50 self.config = config
51
52 def runTest(self):
53 """Run the test case."""
54 test = self.test
55
56 # |test| is an array of alternating state names and action names, starting
57 # and ending with state names. Therefore, its length must be odd.
58 self.assertEqual(len(test) % 2, 1, 'The length of test array must be odd')
59
60 self._RunResetCommand()
61
62 self.current_state = test[0]
63 self._VerifyCurrentState()
64
65 for i in range(1, len(test), 2):
66 action = test[i]
67 self._RunCommand(self.config.actions[action])
68
69 self.current_state = test[i + 1]
70 self._VerifyCurrentState()
71
72 def __str__(self):
73 return 'Test: %s' % (' -> '.join(self.test))
gab 2013/08/07 13:03:34 Add a method comment with an example of what this
sukolsak 2013/08/07 21:23:29 Done.
74
75 def shortDescription(self):
76 """Returns None as the short description to suppress its printing.
77
78 The default implementation of this method returns the docstring of the
79 runTest method, which is not useful since it's the same for every test case.
80 The description from the __str__ method is informative enough.
81 """
82 return None
83
84 def failureException(self, msg):
85 """Returns an AssertionError with the current state information.
86
87 The default implementation of this method returns AssertionError(msg).
88 We add the current state information to the message so that we know where
89 the test fails.
90
91 Args:
92 msg: The error message.
93
94 Returns:
95 An AssertionError.
96 """
97 return AssertionError("In state '%s', %s" % (self.current_state, msg))
98
99 def _VerifyCurrentState(self):
100 """Verifies that the current machine states match the expected machine
101 states."""
gab 2013/08/07 13:03:34 s/states/state for both 'states' in this sentence
sukolsak 2013/08/07 21:23:29 Done.
102 verifier.Verify(self.config.states[self.current_state], self)
103
104 def _RunCommand(self, command):
105 subprocess.call(command, shell=True)
106
107 def _RunResetCommand(self):
108 # TODO(sukolsak): Need to figure how exactly we want to reset.
109 pass
110
111
37 def MergePropertyDictionaries(current_property, new_property): 112 def MergePropertyDictionaries(current_property, new_property):
38 """Merges the new property dictionary into the current property dictionary. 113 """Merges the new property dictionary into the current property dictionary.
39 114
40 This is different from general dictionary merging in that, in case there are 115 This is different from general dictionary merging in that, in case there are
41 keys with the same name, we merge values together in the first level, and we 116 keys with the same name, we merge values together in the first level, and we
42 override earlier values in the second level. For more details, take a look at 117 override earlier values in the second level. For more details, take a look at
43 http://goo.gl/uE0RoR 118 http://goo.gl/uE0RoR
44 119
45 Args: 120 Args:
46 current_property: The property dictionary to be modified. 121 current_property: The property dictionary to be modified.
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 config = Config() 168 config = Config()
94 config.tests = config_data['tests'] 169 config.tests = config_data['tests']
95 for state_name, state_property_filenames in config_data['states']: 170 for state_name, state_property_filenames in config_data['states']:
96 config.states[state_name] = ParsePropertyFiles(directory, 171 config.states[state_name] = ParsePropertyFiles(directory,
97 state_property_filenames) 172 state_property_filenames)
98 for action_name, action_command in config_data['actions']: 173 for action_name, action_command in config_data['actions']:
99 config.actions[action_name] = action_command 174 config.actions[action_name] = action_command
100 return config 175 return config
101 176
102 177
103 def VerifyState(config, state):
104 """Verifies that the current machine states match the given machine states.
105
106 Args:
107 config: A Config object.
108 state: The current state.
109 """
110 # TODO(sukolsak): Think of ways of preserving the log when the test fails but
111 # not printing these when the test passes.
112 print settings.PRINT_STATE_PREFIX + state
113 verifier.Verify(config.states[state])
114
115
116 def RunCommand(command):
117 print settings.PRINT_COMMAND_PREFIX + command
118 subprocess.call(command, shell=True)
119
120
121 def RunResetCommand():
122 print settings.PRINT_COMMAND_PREFIX + 'Reset'
123 # TODO(sukolsak): Need to figure how exactly we want to reset.
124
125
126 def Test(config): 178 def Test(config):
127 """Tests the installer using the given Config object. 179 """Tests the installer using the given Config object.
128 180
129 Args: 181 Args:
130 config: A Config object. 182 config: A Config object.
131 """ 183 """
184 suite = unittest.TestSuite()
132 for test in config.tests: 185 for test in config.tests:
133 print settings.PRINT_TEST_PREFIX + ' -> '.join(test) 186 suite.addTest(InstallerTest(test, config))
134 187 unittest.TextTestRunner(verbosity=2).run(suite)
135 # A Test object is an array of alternating state names and action names.
136 # The array starts and ends with states. Therefore, the length must be odd.
137 assert(len(test) % 2 == 1)
138
139 RunResetCommand()
140
141 current_state = test[0]
142 VerifyState(config, current_state)
143 # TODO(sukolsak): Quit the test early if VerifyState fails at any point.
gab 2013/08/07 13:03:34 Bring this TODO in the new test code above.
sukolsak 2013/08/07 21:23:29 The assertions in verifiers will kill the test cas
144
145 for i in range(1, len(test), 2):
146 action = test[i]
147 RunCommand(config.actions[action])
148
149 current_state = test[i + 1]
150 VerifyState(config, current_state)
151 188
152 189
153 def main(): 190 def main():
154 parser = argparse.ArgumentParser(description='Test the installer.') 191 parser = argparse.ArgumentParser(description='Test the installer.')
155 parser.add_argument('config_filename', 192 parser.add_argument('config_filename',
156 help='The relative/absolute path to the config file.') 193 help='The relative/absolute path to the config file.')
157 args = parser.parse_args() 194 args = parser.parse_args()
158 195
159 config = ParseConfigFile(args.config_filename) 196 config = ParseConfigFile(args.config_filename)
160 Test(config) 197 Test(config)
161 198
162 199
163 if __name__ == '__main__': 200 if __name__ == '__main__':
164 main() 201 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698