Index: chrome/test/mini_installer/test_installer.py |
diff --git a/chrome/test/mini_installer/test_installer.py b/chrome/test/mini_installer/test_installer.py |
index a59bf9164074f3706728b0b4042490dfee34f2c3..a98347872fc40a67f87d6a81dcd9808cdaa8c708 100644 |
--- a/chrome/test/mini_installer/test_installer.py |
+++ b/chrome/test/mini_installer/test_installer.py |
@@ -13,20 +13,20 @@ import argparse |
import json |
import os |
import subprocess |
+import unittest |
-import settings |
import verifier |
class Config: |
"""Describes the machine states, actions, and test cases. |
- A state is a dictionary where each key is a verifier's name and the |
- associated value is the input to that verifier. An action is a shorthand for |
- a command. A test is array of alternating state names and action names, |
- starting and ending with state names. An instance of this class stores a map |
- from state names to state objects, a map from action names to commands, and |
- an array of test objects. |
+ Attributes: |
+ states: A dictionary where each key is a state name and the associated value |
+ is a property dictionary describing that state. |
+ actions: A dictionary where each key is an action name and the associated |
+ value is the action's command. |
+ tests: An array of test cases. |
""" |
def __init__(self): |
self.states = {} |
@@ -34,6 +34,77 @@ class Config: |
self.tests = [] |
+class InstallerTest(unittest.TestCase): |
+ """Tests a test case in the config file.""" |
+ |
+ def __init__(self, test, config): |
+ """Constructor. |
+ |
+ Args: |
+ test: An array of alternating state names and action names, starting and |
+ ending with state names. |
+ config: The Config object. |
+ """ |
+ super(InstallerTest, self).__init__() |
+ self._test = test |
+ self._config = config |
+ |
+ def __str__(self): |
+ """Returns a string representing the test case. |
+ |
+ Returns: |
+ A string created by joining state names and action names together with |
+ ' -> ', for example, 'Test: clean -> install chrome -> chrome_installed'. |
+ """ |
+ return 'Test: %s' % (' -> '.join(self._test)) |
+ |
+ def runTest(self): |
+ """Run the test case.""" |
+ # |test| is an array of alternating state names and action names, starting |
+ # and ending with state names. Therefore, its length must be odd. |
+ self.assertEqual(1, len(self._test) % 2, |
+ 'The length of test array must be odd') |
+ |
+ # TODO(sukolsak): run a reset command that puts the machine in clean state. |
+ |
+ state = self._test[0] |
+ self._VerifyState(state) |
+ |
+ # Starting at index 1, we loop through pairs of (action, state). |
+ for i in range(1, len(self._test), 2): |
+ action = self._test[i] |
+ self._RunCommand(self._config.actions[action]) |
+ |
+ state = self._test[i + 1] |
+ self._VerifyState(state) |
+ |
+ def shortDescription(self): |
+ """Overridden from unittest.TestCase. |
+ |
+ We return None as the short description to suppress its printing. |
+ The default implementation of this method returns the docstring of the |
+ runTest method, which is not useful since it's the same for every test case. |
+ The description from the __str__ method is informative enough. |
+ """ |
+ return None |
+ |
+ def _VerifyState(self, state): |
+ """Verifies that the current machine state matches a given state. |
+ |
+ Args: |
+ state: A state name. |
+ """ |
+ try: |
+ verifier.Verify(self._config.states[state]) |
+ except AssertionError as e: |
+ # If an AssertionError occurs, we intercept it and add the state name |
+ # to the error message so that we know where the test fails. |
+ raise AssertionError("In state '%s', %s" % (state, e)) |
+ |
+ def _RunCommand(self, command): |
+ subprocess.call(command, shell=True) |
+ |
+ |
def MergePropertyDictionaries(current_property, new_property): |
"""Merges the new property dictionary into the current property dictionary. |
@@ -100,54 +171,16 @@ def ParseConfigFile(filename): |
return config |
-def VerifyState(config, state): |
- """Verifies that the current machine states match the given machine states. |
- |
- Args: |
- config: A Config object. |
- state: The current state. |
- """ |
- # TODO(sukolsak): Think of ways of preserving the log when the test fails but |
- # not printing these when the test passes. |
- print settings.PRINT_STATE_PREFIX + state |
- verifier.Verify(config.states[state]) |
- |
- |
-def RunCommand(command): |
- print settings.PRINT_COMMAND_PREFIX + command |
- subprocess.call(command, shell=True) |
- |
- |
-def RunResetCommand(): |
- print settings.PRINT_COMMAND_PREFIX + 'Reset' |
- # TODO(sukolsak): Need to figure how exactly we want to reset. |
- |
- |
-def Test(config): |
+def RunTests(config): |
"""Tests the installer using the given Config object. |
Args: |
config: A Config object. |
""" |
+ suite = unittest.TestSuite() |
for test in config.tests: |
- print settings.PRINT_TEST_PREFIX + ' -> '.join(test) |
- |
- # A Test object is an array of alternating state names and action names. |
- # The array starts and ends with states. Therefore, the length must be odd. |
- assert(len(test) % 2 == 1) |
- |
- RunResetCommand() |
- |
- current_state = test[0] |
- VerifyState(config, current_state) |
- # TODO(sukolsak): Quit the test early if VerifyState fails at any point. |
- |
- for i in range(1, len(test), 2): |
- action = test[i] |
- RunCommand(config.actions[action]) |
- |
- current_state = test[i + 1] |
- VerifyState(config, current_state) |
+ suite.addTest(InstallerTest(test, config)) |
+ unittest.TextTestRunner(verbosity=2).run(suite) |
def main(): |
@@ -157,7 +190,7 @@ def main(): |
args = parser.parse_args() |
config = ParseConfigFile(args.config_filename) |
- Test(config) |
+ RunTests(config) |
if __name__ == '__main__': |