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
This commit is contained in:
		@@ -1,9 +1,9 @@
 | 
			
		||||
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
 | 
			
		||||
- 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
 | 
			
		||||
@@ -23,7 +23,8 @@ 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
 | 
			
		||||
@@ -37,7 +38,8 @@ Imports
 | 
			
		||||
 | 
			
		||||
Human Alphabetical Order Examples
 | 
			
		||||
---------------------------------
 | 
			
		||||
::
 | 
			
		||||
Example::
 | 
			
		||||
 | 
			
		||||
  import httplib
 | 
			
		||||
  import logging
 | 
			
		||||
  import random
 | 
			
		||||
@@ -58,6 +60,8 @@ Human Alphabetical Order Examples
 | 
			
		||||
 | 
			
		||||
Docstrings
 | 
			
		||||
----------
 | 
			
		||||
Example::
 | 
			
		||||
 | 
			
		||||
  """A one line docstring looks like this and ends in a period."""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -87,34 +91,34 @@ Docstrings
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
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:
 | 
			
		||||
Example::
 | 
			
		||||
 | 
			
		||||
    my_dictionary = {
 | 
			
		||||
        "image": {
 | 
			
		||||
            "name": "Just a Snapshot",
 | 
			
		||||
            "size": 2749573,
 | 
			
		||||
            "properties": {
 | 
			
		||||
                 "user_id": 12,
 | 
			
		||||
                 "arch": "x86_64",
 | 
			
		||||
            },
 | 
			
		||||
            "things": [
 | 
			
		||||
                "thing_one",
 | 
			
		||||
                "thing_two",
 | 
			
		||||
            ],
 | 
			
		||||
            "status": "ACTIVE",
 | 
			
		||||
        },
 | 
			
		||||
    }
 | 
			
		||||
  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.
 | 
			
		||||
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',
 | 
			
		||||
@@ -122,7 +126,7 @@ Calling Methods
 | 
			
		||||
                                     kwarg2=['a', 'b', 'c'])
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  Rather than constructing parameters inline, it is better to break things up:
 | 
			
		||||
Rather than constructing parameters inline, it is better to break things up::
 | 
			
		||||
 | 
			
		||||
    list_of_strings = [
 | 
			
		||||
        'what_a_long_string',
 | 
			
		||||
@@ -143,23 +147,38 @@ Calling Methods
 | 
			
		||||
 | 
			
		||||
Internationalization (i18n) Strings
 | 
			
		||||
-----------------------------------
 | 
			
		||||
  In order to support multiple languages, we have a mechanism to support
 | 
			
		||||
  automatic translations of exception and log strings.
 | 
			
		||||
In order to support multiple languages, we have a mechanism to support
 | 
			
		||||
automatic translations of exception and log strings.
 | 
			
		||||
 | 
			
		||||
Example::
 | 
			
		||||
 | 
			
		||||
  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.
 | 
			
		||||
If you have a variable to place within the string, first internationalize the
 | 
			
		||||
template string then do the replacement.
 | 
			
		||||
 | 
			
		||||
Example::
 | 
			
		||||
 | 
			
		||||
  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.
 | 
			
		||||
If you have multiple variables to place in the string, use keyword parameters.
 | 
			
		||||
This helps our translators reorder parameters when needed.
 | 
			
		||||
 | 
			
		||||
Example::
 | 
			
		||||
 | 
			
		||||
  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.
 | 
			
		||||
@@ -72,7 +72,7 @@ LOG = logging.getLogger("nova.ldapdriver")
 | 
			
		||||
if FLAGS.memcached_servers:
 | 
			
		||||
    import memcache
 | 
			
		||||
else:
 | 
			
		||||
    from nova import fakememcache as memcache
 | 
			
		||||
    from nova.testing.fake import memcache
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# TODO(vish): make an abstract base class with the same public methods
 | 
			
		||||
 
 | 
			
		||||
@@ -82,7 +82,7 @@ LOG = logging.getLogger('nova.auth.manager')
 | 
			
		||||
if FLAGS.memcached_servers:
 | 
			
		||||
    import memcache
 | 
			
		||||
else:
 | 
			
		||||
    from nova import fakememcache as memcache
 | 
			
		||||
    from nova.testing.fake import memcache
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AuthBase(object):
 | 
			
		||||
 
 | 
			
		||||
@@ -41,9 +41,9 @@ import greenlet
 | 
			
		||||
 | 
			
		||||
from nova import context
 | 
			
		||||
from nova import exception
 | 
			
		||||
from nova import fakerabbit
 | 
			
		||||
from nova import flags
 | 
			
		||||
from nova.rpc.common import RemoteError, LOG
 | 
			
		||||
from nova.testing import fake
 | 
			
		||||
 | 
			
		||||
# Needed for tests
 | 
			
		||||
eventlet.monkey_patch()
 | 
			
		||||
@@ -71,7 +71,7 @@ class Connection(carrot_connection.BrokerConnection):
 | 
			
		||||
                          virtual_host=FLAGS.rabbit_virtual_host)
 | 
			
		||||
 | 
			
		||||
            if FLAGS.fake_rabbit:
 | 
			
		||||
                params['backend_cls'] = fakerabbit.Backend
 | 
			
		||||
                params['backend_cls'] = fake.rabbit.Backend
 | 
			
		||||
 | 
			
		||||
            # NOTE(vish): magic is fun!
 | 
			
		||||
            # pylint: disable=W0142
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										44
									
								
								nova/testing/README.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								nova/testing/README.rst
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										0
									
								
								nova/testing/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								nova/testing/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										2
									
								
								nova/testing/fake/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								nova/testing/fake/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
import memcache
 | 
			
		||||
import rabbit
 | 
			
		||||
@@ -26,7 +26,7 @@ from eventlet import greenthread
 | 
			
		||||
from nova import log as logging
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
LOG = logging.getLogger("nova.fakerabbit")
 | 
			
		||||
LOG = logging.getLogger("nova.testing.fake.rabbit")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
EXCHANGES = {}
 | 
			
		||||
@@ -41,17 +41,18 @@
 | 
			
		||||
"""Unittest runner for Nova.
 | 
			
		||||
 | 
			
		||||
To run all tests
 | 
			
		||||
    python run_tests.py
 | 
			
		||||
 | 
			
		||||
To run a single test:
 | 
			
		||||
    python run_tests.py test_compute:ComputeTestCase.test_run_terminate
 | 
			
		||||
    python nova/testing/runner.py
 | 
			
		||||
 | 
			
		||||
To run a single test module:
 | 
			
		||||
    python run_tests.py test_compute
 | 
			
		||||
    python nova/testing/runner.py test_compute
 | 
			
		||||
 | 
			
		||||
    or
 | 
			
		||||
 | 
			
		||||
    python run_tests.py api.test_wsgi
 | 
			
		||||
    python nova/testing/runner.py api.test_wsgi
 | 
			
		||||
 | 
			
		||||
To run a single test:
 | 
			
		||||
    python nova/testing/runner.py \
 | 
			
		||||
        test_compute:ComputeTestCase.test_run_terminate
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
@@ -336,8 +337,7 @@ class NovaTestRunner(core.TextTestRunner):
 | 
			
		||||
        return result_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    eventlet.monkey_patch()
 | 
			
		||||
def run():
 | 
			
		||||
    logging.setup()
 | 
			
		||||
    # If any argument looks like a test name but doesn't have "nova.tests" in
 | 
			
		||||
    # front of it, automatically add that so we don't have to type as much
 | 
			
		||||
@@ -363,3 +363,8 @@ if __name__ == '__main__':
 | 
			
		||||
                            config=c,
 | 
			
		||||
                            show_elapsed=show_elapsed)
 | 
			
		||||
    sys.exit(not core.run(config=c, testRunner=runner, argv=argv))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    eventlet.monkey_patch()
 | 
			
		||||
    run()
 | 
			
		||||
		Reference in New Issue
	
	Block a user