view tests/unit.py @ 102:c530f6265deb

allow extensible configuration; also start using deepcopy heavily since otherwise you have artefacts
author Jeff Hammel <jhammel@mozilla.com>
date Tue, 01 May 2012 10:33:37 -0700
parents 0804a706d6bf
children a2184db43fe2
line wrap: on
line source

#!/usr/bin/env python

"""
unit tests
"""

import configuration
import os
import sys
import tempfile
import unittest

try:
    import json
except ImportError:
    import simplejson as json

from example import ExampleConfiguration # example configuration to test

# globals
here = os.path.dirname(os.path.abspath(__file__))

class ConfigurationUnitTest(unittest.TestCase):

    def test_cli(self):
        """test command line interface"""

        example = ExampleConfiguration()

        # parse command line arguments
        options, args = example.parse_args(['-a', 'ts', '--develop', '-e', '/home/jhammel/bin/firefox'])

        # ensure that the options appropriately get set
        self.assertEqual(bool(args), False) # no arguments
        self.assertEqual(options.develop, True)
        self.assertEqual(options.activeTests, ['ts'])
        self.assertEqual(options.browser_path, '/home/jhammel/bin/firefox')

        # ensure that the configuration appropriately gets updated
        self.assertEqual(example.config['develop'], True)
        self.assertEqual(example.config['activeTests'], ['ts'])
        self.assertEqual(example.config['browser_path'], '/home/jhammel/bin/firefox')

    def test_configuration_providers(self):
        """test file-based configuration providers"""
        # requires json/simplejson to be installed

        example = ExampleConfiguration()

        # see what providers you got
        json_provider = example.configuration_provider('json')
        self.assertTrue(isinstance(json_provider, configuration.JSON))

        # serialize to a temporary file
        filename = tempfile.mktemp(suffix='.json')
        self.assertEqual(example.filename2format(filename), 'json')
        self.assertFalse(os.path.exists(filename))
        config = {'browser_path': '/home/jhammel/bin/firefox',
                  'activeTests':  ['ts']}
        example(config)
        config['test_timeout'] = 1200 # default
        config['preferences'] = {"browser.bookmarks.max_backups": 0,
                                 "browser.cache.disk.smart_size.enabled": False}

        # ensure they are equal
        self.assertEqual(config, example.config)
        example.serialize(filename)
        self.assertTrue(os.path.exists(filename))
        serialized = json.loads(file(filename).read())
        self.assertEqual(serialized, config)

        # deserialize
        deserialized = example.deserialize(filename)
        self.assertEqual(deserialized, config)

        # cleanup
        if os.path.exists(filename):
            os.remove(filename)

    def test_missing_values(self):
        """ensure that Configuration raises a missing value exception"""

        example = ExampleConfiguration()

        # monkey-patch the error method from optparse.OptionParser
        error_msg = []
        def error(msg):
            error_msg.append(msg)
        example.error = error

        # trigger it
        example.parse_args(args=[])
        self.assertEqual(error_msg, ['Parameter browser_path is required but not present'])

    def test_required(self):
        """ensure you have to have required values"""

        example = ExampleConfiguration()

        # ensure you get an exception
        missingvalueexception = None
        try:
            example()
        except configuration.MissingValueException, e:
            missingvalueexception = e
        self.assertTrue(isinstance(e, configuration.MissingValueException))


    def test_multiple_configurations(self):
        """test having multiple configurations"""

        # simple override
        args1 = ['-e', '/opt/bin/firefox']

        # simple serialized file
        json_file = os.path.join(here, 'base.json')
        assert os.path.exists(json_file)
        json_config = json.loads(file(json_file).read())

        # parse the json file
        example = ExampleConfiguration()
        example.parse_args([json_file])
        self.assertEqual(example.config, json_config)

        # parse the json file with overrides
        example = ExampleConfiguration()
        example.parse_args([json_file] + args1)
        config = json_config.copy()
        config['browser_path'] = '/opt/bin/firefox'
        self.assertEqual(example.config, config)

        # it shouldn't matter in which order the arguments are
        example = ExampleConfiguration()
        example.parse_args(args1 + [json_file])
        self.assertEqual(example.config, config)

        # Now a tricky case:
        # the default value for test_timeout is 1200:
        example = ExampleConfiguration()
        self.assertEqual(example.options['test_timeout']['default'], 1200)
        # The value from base.json is 60:
        self.assertEqual(json_config['test_timeout'], 60)
        self.assertEqual(config['test_timeout'], 60)
        # but we can override it back from the "command line"
        example.parse_args(args1 + [json_file, '--test_timeout', '1200'])
        config['test_timeout'] = 1200
        self.assertEqual(example.config, config)

    def test_extend(self):

        # default preferences
        example = ExampleConfiguration()
        default_prefs = {"browser.bookmarks.max_backups": 0,
                         "browser.cache.disk.smart_size.enabled": False}
        example.parse_args(['-a', 'ts', '-e', '/opt/bin/firefox'])
        self.assertEqual(example.config['preferences'], default_prefs)

        # now extend them
        example = ExampleConfiguration()
        default_prefs['network.dns.ipv4OnlyDomains'] = 'localhost'
        tf = tempfile.mktemp()
        f = file(tf, 'w')
        f.write(json.dumps({'preferences': {'network.dns.ipv4OnlyDomains': 'localhost'}}))
        f.close()
        example.parse_args(['-a', 'ts', '-e', '/opt/bin/firefox', tf])
        self.assertEqual(example.config['preferences'], default_prefs)
        os.remove(tf)

if __name__ == '__main__':
    unittest.main()