From d6ee85317f93898fe34a129da8bf55b193d29f64 Mon Sep 17 00:00:00 2001 From: Duncan McGreggor Date: Mon, 21 Nov 2011 19:59:50 -0800 Subject: [PATCH] First steps towards consolidating testing infrastructure This commit begins to implement blueprint consolidate-testing-infrastructure by adding a 'testing' subpackage and moving some modules into it. Change-Id: I04bf860bc386bd2016e7dbc5a6f6ef7379a855bb --- HACKING.rst | 184 ++++++++++++++++++++++++++++++++++++++++ nova/test.py | 4 +- nova/testing/README.rst | 44 ++++++++++ 3 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 HACKING.rst create mode 100644 nova/testing/README.rst diff --git a/HACKING.rst b/HACKING.rst new file mode 100644 index 000000000..d9d0f41a6 --- /dev/null +++ b/HACKING.rst @@ -0,0 +1,184 @@ +Nova Style Commandments +======================= + +- Step 1: Read http://www.python.org/dev/peps/pep-0008/ +- Step 2: Read http://www.python.org/dev/peps/pep-0008/ again +- Step 3: Read on + + +General +------- +- Put two newlines between top-level code (funcs, classes, etc) +- Put one newline between methods in classes and anywhere else +- Do not write "except:", use "except Exception:" at the very least +- Include your name with TODOs as in "#TODO(termie)" +- Do not name anything the same name as a built-in or reserved word + + +Imports +------- +- Do not import objects, only modules +- Do not import more than one module per line +- Do not make relative imports +- Order your imports by the full module path +- Organize your imports according to the following template + +Example:: + + # vim: tabstop=4 shiftwidth=4 softtabstop=4 + {{stdlib imports in human alphabetical order}} + \n + {{third-party lib imports in human alphabetical order}} + \n + {{nova imports in human alphabetical order}} + \n + \n + {{begin your code}} + + +Human Alphabetical Order Examples +--------------------------------- +Example:: + + import httplib + import logging + import random + import StringIO + import time + import unittest + + import eventlet + import webob.exc + + import nova.api.ec2 + from nova.api import openstack + from nova.auth import users + import nova.flags + from nova.endpoint import cloud + from nova import test + + +Docstrings +---------- +Example:: + + """A one line docstring looks like this and ends in a period.""" + + + """A multiline docstring has a one-line summary, less than 80 characters. + + Then a new paragraph after a newline that explains in more detail any + general information about the function, class or method. Example usages + are also great to have here if it is a complex class for function. After + you have finished your descriptions add an extra newline and close the + quotations. + + When writing the docstring for a class, an extra line should be placed + after the closing quotations. For more in-depth explanations for these + decisions see http://www.python.org/dev/peps/pep-0257/ + + If you are going to describe parameters and return values, use Sphinx, the + appropriate syntax is as follows. + + :param foo: the foo parameter + :param bar: the bar parameter + :returns: return_type -- description of the return value + :returns: description of the return value + :raises: AttributeError, KeyError + + """ + + +Dictionaries/Lists +------------------ +If a dictionary (dict) or list object is longer than 80 characters, its items +should be split with newlines. Embedded iterables should have their items +indented. Additionally, the last item in the dictionary should have a trailing +comma. This increases readability and simplifies future diffs. + +Example:: + + my_dictionary = { + "image": { + "name": "Just a Snapshot", + "size": 2749573, + "properties": { + "user_id": 12, + "arch": "x86_64", + }, + "things": [ + "thing_one", + "thing_two", + ], + "status": "ACTIVE", + }, + } + + +Calling Methods +--------------- +Calls to methods 80 characters or longer should format each argument with +newlines. This is not a requirement, but a guideline:: + + unnecessarily_long_function_name('string one', + 'string two', + kwarg1=constants.ACTIVE, + kwarg2=['a', 'b', 'c']) + + +Rather than constructing parameters inline, it is better to break things up:: + + list_of_strings = [ + 'what_a_long_string', + 'not as long', + ] + + dict_of_numbers = { + 'one': 1, + 'two': 2, + 'twenty four': 24, + } + + object_one.call_a_method('string three', + 'string four', + kwarg1=list_of_strings, + kwarg2=dict_of_numbers) + + +Internationalization (i18n) Strings +----------------------------------- +In order to support multiple languages, we have a mechanism to support +automatic translations of exception and log strings. + +Example:: + + msg = _("An error occurred") + raise HTTPBadRequest(explanation=msg) + +If you have a variable to place within the string, first internationalize the +template string then do the replacement. + +Example:: + + msg = _("Missing parameter: %s") % ("flavor",) + LOG.error(msg) + +If you have multiple variables to place in the string, use keyword parameters. +This helps our translators reorder parameters when needed. + +Example:: + + msg = _("The server with id %(s_id)s has no key %(m_key)s") + LOG.error(msg % {"s_id": "1234", "m_key": "imageId"}) + + +Creating Unit Tests +------------------- +For every new feature, unit tests should be created that both test and +(implicitly) document the usage of said feature. If submitting a patch for a +bug that had no unit test, a new passing unit test should be added. If a +submitted bug fix does have a unit test, be sure to add a new one that fails +without the patch and passes with the patch. + +For more information on creating unit tests and utilizing the testing +infrastructure in OpenStack Nova, please read nova/testing/README.rst. diff --git a/nova/test.py b/nova/test.py index 6c565f53d..448af047e 100644 --- a/nova/test.py +++ b/nova/test.py @@ -35,12 +35,12 @@ import nova.image.fake import shutil import stubout -from nova import fakerabbit from nova import flags from nova import log from nova import rpc from nova import utils from nova import service +from nova.testing.fake import rabbit from nova.virt import fake @@ -142,7 +142,7 @@ class TestCase(unittest.TestCase): finally: # Clean out fake_rabbit's queue if we used it if FLAGS.fake_rabbit: - fakerabbit.reset_all() + rabbit.reset_all() if FLAGS.connection_type == 'fake': if hasattr(fake.FakeConnection, '_instance'): diff --git a/nova/testing/README.rst b/nova/testing/README.rst new file mode 100644 index 000000000..036f1c77d --- /dev/null +++ b/nova/testing/README.rst @@ -0,0 +1,44 @@ +===================================== +OpenStack Nova Testing Infrastructure +===================================== + +A note of clarification is in order, to help those who are new to testing in +OpenStack nova: + +- actual unit tests are created in the "tests" directory; +- the "testing" directory is used to house the infrastructure needed to support + testing in OpenStack Nova. + +This README file attempts to provide current and prospective contributors with +everything they need to know in order to start creating unit tests and +utilizing the convenience code provided in nova.testing. + +Note: the content for the rest of this file will be added as the work items in +the following blueprint are completed: + https://blueprints.launchpad.net/nova/+spec/consolidate-testing-infrastructure + + +Test Types: Unit vs. Functional vs. Integration +----------------------------------------------- + +TBD + +Writing Unit Tests +------------------ + +TBD + +Using Fakes +~~~~~~~~~~~ + +TBD + +Writing Functional Tests +------------------------ + +TBD + +Writing Integration Tests +------------------------- + +TBD