summaryrefslogtreecommitdiffstats
path: root/chrome/test
diff options
context:
space:
mode:
authorsukolsak@chromium.org <sukolsak@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-12 20:09:26 +0000
committersukolsak@chromium.org <sukolsak@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-12 20:09:26 +0000
commit04dbc630c1d32852c458e6b1a63820d09355623d (patch)
treead9dbd37da189d1d7dad249fa8df119e2796b4d7 /chrome/test
parentee4f02b5e5e72e324e13ed6a95172b0c451a5e61 (diff)
downloadchromium_src-04dbc630c1d32852c458e6b1a63820d09355623d.zip
chromium_src-04dbc630c1d32852c458e6b1a63820d09355623d.tar.gz
chromium_src-04dbc630c1d32852c458e6b1a63820d09355623d.tar.bz2
Use unittest framework in the Automated Installer Testing Framework.
NOTRY=True BUG=264859 TEST= 1) Uninstall Chrome. 2) Put mini_installer.exe in the same folder as test_installer.py. 3) Run "python test_installer.py config\config.config". 4) The script will install Chrome and then uninstall Chrome. At each state, it will check that a registry entry for Chrome exists (or doesn't exist). You should see output similar to the following: "Test: clean -> install chrome -> chrome_installed -> uninstall chrome -> clean ... ok ---------------------------------------------------------------------- Ran 1 test in 12.345s" Review URL: https://chromiumcodereview.appspot.com/22480002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@217059 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/test')
-rw-r--r--chrome/test/mini_installer/config/chrome_installed.prop2
-rw-r--r--chrome/test/mini_installer/config/chrome_not_installed.prop2
-rw-r--r--chrome/test/mini_installer/registry_verifier.py64
-rw-r--r--chrome/test/mini_installer/settings.py8
-rw-r--r--chrome/test/mini_installer/test_installer.py133
-rw-r--r--chrome/test/mini_installer/verifier.py14
6 files changed, 124 insertions, 99 deletions
diff --git a/chrome/test/mini_installer/config/chrome_installed.prop b/chrome/test/mini_installer/config/chrome_installed.prop
index 289b47d..9db2a19 100644
--- a/chrome/test/mini_installer/config/chrome_installed.prop
+++ b/chrome/test/mini_installer/config/chrome_installed.prop
@@ -1,6 +1,6 @@
{
"RegistryEntries": {
"HKEY_CURRENT_USER\\Software\\Google\\Update\\Clients\\{8A69D345-D564-463c-AFF1-A69D9E530F96}":
- {"expected": true}
+ {"exists": true}
}
}
diff --git a/chrome/test/mini_installer/config/chrome_not_installed.prop b/chrome/test/mini_installer/config/chrome_not_installed.prop
index 6e024ef..a9f7685 100644
--- a/chrome/test/mini_installer/config/chrome_not_installed.prop
+++ b/chrome/test/mini_installer/config/chrome_not_installed.prop
@@ -1,6 +1,6 @@
{
"RegistryEntries": {
"HKEY_CURRENT_USER\\Software\\Google\\Update\\Clients\\{8A69D345-D564-463c-AFF1-A69D9E530F96}":
- {"expected": false}
+ {"exists": false}
}
}
diff --git a/chrome/test/mini_installer/registry_verifier.py b/chrome/test/mini_installer/registry_verifier.py
index ceac20d..da7909e 100644
--- a/chrome/test/mini_installer/registry_verifier.py
+++ b/chrome/test/mini_installer/registry_verifier.py
@@ -4,20 +4,20 @@
import _winreg
-import settings
-
def VerifyRegistryEntries(entries):
- """Verifies that the current registry matches the specified criteria."""
- for key, entry in entries.iteritems():
- # TODO(sukolsak): Use unittest framework instead of prints.
- if VerifyRegistryEntry(key, entry):
- print 'Passed'
- else:
- print 'Failed'
+ """Verifies that the current registry matches the specified criteria.
+
+ Args:
+ entries: A dictionary whose keys are registry keys and values are
+ expectation dictionaries.
+ """
+ for key, expectation in entries.iteritems():
+ VerifyRegistryEntry(key, expectation)
def RootKeyConstant(key):
+ """Converts a root registry key string into a _winreg.HKEY_* constant."""
if key == 'HKEY_CLASSES_ROOT':
return _winreg.HKEY_CLASSES_ROOT
if key == 'HKEY_CURRENT_USER':
@@ -26,39 +26,31 @@ def RootKeyConstant(key):
return _winreg.HKEY_LOCAL_MACHINE
if key == 'HKEY_USERS':
return _winreg.HKEY_USERS
- # TODO(sukolsak): Use unittest framework instead of exceptions.
- raise Exception('Unknown registry key')
+ raise KeyError("Unknown root registry key '%s'" % key)
+
+def VerifyRegistryEntry(key, expectation):
+ """Verifies a registry key according to the |expectation|.
-def VerifyRegistryEntry(key, entry):
- """Verifies that a registry entry exists or doesn't exist and has
- the specified value.
+ The |expectation| specifies whether or not the registry key should exist
+ (under 'exists') and optionally specifies an expected 'value' for the key.
Args:
key: Name of the registry key.
- entry: A dictionary with the following keys and values:
- 'expected' a boolean indicating whether the registry entry exists.
- 'value' (optional) a string representing the value of the registry entry.
-
- Returns:
- A boolean indicating whether the registry entry matches the criteria.
+ expectation: A dictionary with the following keys and values:
+ 'exists' a boolean indicating whether the registry entry should exist.
+ 'value' (optional) a string representing the expected value for
+ the key.
"""
- expected = entry['expected']
- # TODO(sukolsak): Debug prints to be removed later.
- print settings.PRINT_VERIFIER_PREFIX + key,
- if expected:
- print 'exists...',
- else:
- print "doesn't exist...",
root_key, sub_key = key.split('\\', 1)
try:
- reg_key = _winreg.OpenKey(RootKeyConstant(root_key),
- sub_key, 0, _winreg.KEY_READ)
+ # Query the Windows registry for the registry key. It will throw a
+ # WindowsError if the key doesn't exist.
+ _ = _winreg.OpenKey(RootKeyConstant(root_key), sub_key, 0, _winreg.KEY_READ)
except WindowsError:
- return not expected
- if not expected:
- return False
- if 'value' in entry:
- # TODO(sukolsak): implement value
- pass
- return True
+ # Key doesn't exist. See that it matches the expectation.
+ assert not expectation['exists'], 'Registry entry %s is missing' % key
+ return
+ # The key exists, see that it matches the expectation.
+ assert expectation['exists'], 'Registry entry %s exists' % key
+ # TODO(sukolsak): Verify the expected value.
diff --git a/chrome/test/mini_installer/settings.py b/chrome/test/mini_installer/settings.py
deleted file mode 100644
index 9c04a8b..0000000
--- a/chrome/test/mini_installer/settings.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-PRINT_TEST_PREFIX = "Testing: "
-PRINT_COMMAND_PREFIX = " * Command: "
-PRINT_STATE_PREFIX = " * State: "
-PRINT_VERIFIER_PREFIX = " - Verify that "
diff --git a/chrome/test/mini_installer/test_installer.py b/chrome/test/mini_installer/test_installer.py
index a59bf91..a983478 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__':
diff --git a/chrome/test/mini_installer/verifier.py b/chrome/test/mini_installer/verifier.py
index 7b0fae6..8a735ba 100644
--- a/chrome/test/mini_installer/verifier.py
+++ b/chrome/test/mini_installer/verifier.py
@@ -4,12 +4,20 @@
import registry_verifier
+
def Verify(property):
- """Verifies that the current machine states match the property object."""
+ """Verifies that the current machine states match the property dictionary.
+
+ A property dictionary is a dictionary where each key is a verifier's name and
+ the associated value is the input to that verifier. For details about the
+ input format for each verifier, take a look at http://goo.gl/1P85WL
+
+ Args:
+ property: A property dictionary.
+ """
for verifier_name, value in property.iteritems():
if verifier_name == 'RegistryEntries':
registry_verifier.VerifyRegistryEntries(value)
else:
# TODO(sukolsak): Implement other verifiers
- # TODO(sukolsak): Use unittest framework instead of exceptions.
- raise Exception('Unknown verifier')
+ raise KeyError('Unknown verifier %s' % verifier_name)