refactor functional test base class to no inherit from tempest_lib
Test base classes inheriting outside the existing source tree to anything higher up the stack than testtools is really an anti pattern. It makes it *far* less clear what is going on. We really need to own and understand our base class setup for tests. This does that unwind, so that we only now call out to tempest_lib in specific ways (like building clients, using decorators). The timeout and log capture pieces are pulled inline. At the end of this we end up with a base test that defines: - self.client - a Nova API client - self.flavor - a workable flavor for booting guests - self.image - a workable image for booting guests - self.cli_clients - tempest_lib cli clients Change-Id: I716be51d7d1825a757934298f06b2f04d64cf0dd
This commit is contained in:
parent
5eab1430f2
commit
420dc2884a
|
@ -12,10 +12,44 @@
|
|||
|
||||
import os
|
||||
|
||||
from tempest_lib.cli import base
|
||||
import fixtures
|
||||
import tempest_lib.cli.base
|
||||
import testtools
|
||||
|
||||
import novaclient.client
|
||||
|
||||
|
||||
class ClientTestBase(base.ClientTestBase):
|
||||
# The following are simple filter functions that filter our available
|
||||
# image / flavor list so that they can be used in standard testing.
|
||||
def pick_flavor(flavors):
|
||||
"""Given a flavor list pick a reasonable one."""
|
||||
for flavor in flavors:
|
||||
if flavor.name == 'm1.tiny':
|
||||
return flavor
|
||||
for flavor in flavors:
|
||||
if flavor.name == 'm1.small':
|
||||
return flavor
|
||||
raise NoFlavorException()
|
||||
|
||||
|
||||
def pick_image(images):
|
||||
for image in images:
|
||||
if image.name.startswith('cirros') and image.name.endswith('-uec'):
|
||||
return image
|
||||
raise NoImageException()
|
||||
|
||||
|
||||
class NoImageException(Exception):
|
||||
"""We couldn't find an acceptable image."""
|
||||
pass
|
||||
|
||||
|
||||
class NoFlavorException(Exception):
|
||||
"""We couldn't find an acceptable flavor."""
|
||||
pass
|
||||
|
||||
|
||||
class ClientTestBase(testtools.TestCase):
|
||||
"""
|
||||
This is a first pass at a simple read only python-novaclient test. This
|
||||
only exercises client commands that are read only.
|
||||
|
@ -27,12 +61,65 @@ class ClientTestBase(base.ClientTestBase):
|
|||
* initially just check return codes, and later test command outputs
|
||||
|
||||
"""
|
||||
def _get_clients(self):
|
||||
log_format = ('%(asctime)s %(process)d %(levelname)-8s '
|
||||
'[%(name)s] %(message)s')
|
||||
|
||||
def setUp(self):
|
||||
super(ClientTestBase, self).setUp()
|
||||
|
||||
test_timeout = os.environ.get('OS_TEST_TIMEOUT', 0)
|
||||
try:
|
||||
test_timeout = int(test_timeout)
|
||||
except ValueError:
|
||||
test_timeout = 0
|
||||
if test_timeout > 0:
|
||||
self.useFixture(fixtures.Timeout(test_timeout, gentle=True))
|
||||
|
||||
if (os.environ.get('OS_STDOUT_CAPTURE') == 'True' or
|
||||
os.environ.get('OS_STDOUT_CAPTURE') == '1'):
|
||||
stdout = self.useFixture(fixtures.StringStream('stdout')).stream
|
||||
self.useFixture(fixtures.MonkeyPatch('sys.stdout', stdout))
|
||||
if (os.environ.get('OS_STDERR_CAPTURE') == 'True' or
|
||||
os.environ.get('OS_STDERR_CAPTURE') == '1'):
|
||||
stderr = self.useFixture(fixtures.StringStream('stderr')).stream
|
||||
self.useFixture(fixtures.MonkeyPatch('sys.stderr', stderr))
|
||||
|
||||
if (os.environ.get('OS_LOG_CAPTURE') != 'False' and
|
||||
os.environ.get('OS_LOG_CAPTURE') != '0'):
|
||||
self.useFixture(fixtures.LoggerFixture(nuke_handlers=False,
|
||||
format=self.log_format,
|
||||
level=None))
|
||||
|
||||
# TODO(sdague): while we collect this information in
|
||||
# tempest-lib, we do it in a way that's not available for top
|
||||
# level tests. Long term this probably needs to be in the base
|
||||
# class.
|
||||
user = os.environ['OS_USERNAME']
|
||||
passwd = os.environ['OS_PASSWORD']
|
||||
tenant = os.environ['OS_TENANT_NAME']
|
||||
auth_url = os.environ['OS_AUTH_URL']
|
||||
|
||||
# TODO(sdague): we made a lot of fun of the glanceclient team
|
||||
# for version as int in first parameter. I guess we know where
|
||||
# they copied it from.
|
||||
self.client = novaclient.client.Client(
|
||||
2, user, passwd, tenant,
|
||||
auth_url=auth_url)
|
||||
|
||||
# pick some reasonable flavor / image combo
|
||||
self.flavor = pick_flavor(self.client.flavors.list())
|
||||
self.image = pick_image(self.client.images.list())
|
||||
|
||||
# create a CLI client in case we'd like to do CLI
|
||||
# testing. tempest_lib does this realy weird thing where it
|
||||
# builds a giant factory of all the CLIs that it knows
|
||||
# about. Eventually that should really be unwound into
|
||||
# something more sensible.
|
||||
cli_dir = os.environ.get(
|
||||
'OS_NOVACLIENT_EXEC_DIR',
|
||||
os.path.join(os.path.abspath('.'), '.tox/functional/bin'))
|
||||
|
||||
return base.CLIClient(
|
||||
self.cli_clients = tempest_lib.cli.base.CLIClient(
|
||||
username=os.environ.get('OS_USERNAME'),
|
||||
password=os.environ.get('OS_PASSWORD'),
|
||||
tenant_name=os.environ.get('OS_TENANT_NAME'),
|
||||
|
@ -40,5 +127,5 @@ class ClientTestBase(base.ClientTestBase):
|
|||
cli_dir=cli_dir)
|
||||
|
||||
def nova(self, *args, **kwargs):
|
||||
return self.clients.nova(*args,
|
||||
**kwargs)
|
||||
return self.cli_clients.nova(*args,
|
||||
**kwargs)
|
||||
|
|
|
@ -10,33 +10,12 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import time
|
||||
import uuid
|
||||
|
||||
import novaclient.client
|
||||
from novaclient.tests.functional import base
|
||||
|
||||
|
||||
# TODO(sdague): content that probably should be in utils, also throw
|
||||
# Exceptions when they fail.
|
||||
def pick_flavor(flavors):
|
||||
"""Given a flavor list pick a reasonable one."""
|
||||
for flavor in flavors:
|
||||
if flavor.name == 'm1.tiny':
|
||||
return flavor
|
||||
|
||||
for flavor in flavors:
|
||||
if flavor.name == 'm1.small':
|
||||
return flavor
|
||||
|
||||
|
||||
def pick_image(images):
|
||||
for image in images:
|
||||
if image.name.startswith('cirros') and image.name.endswith('-uec'):
|
||||
return image
|
||||
|
||||
|
||||
def volume_id_from_cli_create(output):
|
||||
"""Scrape the volume id out of the 'volume create' command
|
||||
|
||||
|
@ -67,27 +46,6 @@ def volume_at_status(output, volume_id, status):
|
|||
|
||||
|
||||
class TestInstanceCLI(base.ClientTestBase):
|
||||
def setUp(self):
|
||||
super(TestInstanceCLI, self).setUp()
|
||||
# TODO(sdague): while we collect this information in
|
||||
# tempest-lib, we do it in a way that's not available for top
|
||||
# level tests. Long term this probably needs to be in the base
|
||||
# class.
|
||||
user = os.environ['OS_USERNAME']
|
||||
passwd = os.environ['OS_PASSWORD']
|
||||
tenant = os.environ['OS_TENANT_NAME']
|
||||
auth_url = os.environ['OS_AUTH_URL']
|
||||
|
||||
# TODO(sdague): we made a lot of fun of the glanceclient team
|
||||
# for version as int in first parameter. I guess we know where
|
||||
# they copied it from.
|
||||
self.client = novaclient.client.Client(
|
||||
2, user, passwd, tenant,
|
||||
auth_url=auth_url)
|
||||
|
||||
# pick some reasonable flavor / image combo
|
||||
self.flavor = pick_flavor(self.client.flavors.list())
|
||||
self.image = pick_image(self.client.images.list())
|
||||
|
||||
def test_attach_volume(self):
|
||||
"""Test we can attach a volume via the cli.
|
||||
|
|
|
@ -10,13 +10,11 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import time
|
||||
import uuid
|
||||
|
||||
import six.moves
|
||||
|
||||
from novaclient import client
|
||||
from novaclient import exceptions
|
||||
from novaclient.tests.functional import base
|
||||
|
||||
|
@ -35,15 +33,6 @@ def wait_for_delete(test, name, thing, get_func):
|
|||
|
||||
class TestVolumesAPI(base.ClientTestBase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestVolumesAPI, self).setUp()
|
||||
user = os.environ['OS_USERNAME']
|
||||
passwd = os.environ['OS_PASSWORD']
|
||||
tenant = os.environ['OS_TENANT_NAME']
|
||||
auth_url = os.environ['OS_AUTH_URL']
|
||||
|
||||
self.client = client.Client(2, user, passwd, tenant, auth_url=auth_url)
|
||||
|
||||
def test_volumes_snapshots_types_create_get_list_delete(self):
|
||||
# Create a volume
|
||||
volume = self.client.volumes.create(1)
|
||||
|
|
Loading…
Reference in New Issue