Add basic external test plugin support to tempest

This commit starts the basic framework for using external plugins in
tempest. It adds a new singleton class to load the plugins once from
stevedore and also provides an interface for different steps in the
tempest execution to use plugins as well as in-tree code.

As part of this an ABC abstract class is created to simplify the
plugin side creation. Eventually the expectation is that this
abstract class will live in tempest-lib. But, for right now while
this feature is still experimental and under development this will
likely change frequently so it'll live in tempest for the time being.

Partially Implements bp external-plugin-interface

Change-Id: I8ebabdb4ce9f4d3b3aca375158835f907d5ca315
This commit is contained in:
Matthew Treinish 2015-07-01 12:46:41 -04:00
parent e97870c641
commit 7a51877e3c
No known key found for this signature in database
GPG Key ID: FD12A0F214C9E177
4 changed files with 75 additions and 1 deletions

View File

@ -24,3 +24,4 @@ fixtures>=1.3.1
testscenarios>=0.4
tempest-lib>=0.6.1
PyYAML>=3.1.0
stevedore>=1.5.0 # Apache-2.0

View File

@ -0,0 +1,56 @@
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import abc
import six
import stevedore
from tempest_lib.common.utils import misc
@six.add_metaclass(abc.ABCMeta)
class TempestPlugin(object):
"""A TempestPlugin class provides the basic hooks for an external
plugin to provide tempest the necessary information to run the plugin.
"""
@abc.abstractmethod
def load_tests(self):
"""Method to return the information necessary to load the tests in the
plugin.
:return: a tuple with the first value being the test_dir and the second
being the top_level
:rtype: tuple
"""
return
@misc.singleton
class TempestTestPluginManager(object):
"""Tempest test plugin manager class
This class is used to manage the lifecycle of external tempest test
plugins. It provides functions for getting set
"""
def __init__(self):
self.ext_plugins = stevedore.ExtensionManager(
'tempest.test.plugins', invoke_on_load=True,
propagate_map_exceptions=True)
def get_plugin_load_tests_tuple(self):
load_tests_dict = {}
for plug in self.ext_plugins:
load_tests_dict[plug.name] = plug.obj.load_tests()
return load_tests_dict

View File

@ -15,6 +15,8 @@
import os
import sys
from tempest.test_discover import plugins
if sys.version_info >= (2, 7):
import unittest
else:
@ -22,9 +24,12 @@ else:
def load_tests(loader, tests, pattern):
ext_plugins = plugins.TempestTestPluginManager()
suite = unittest.TestSuite()
base_path = os.path.split(os.path.dirname(os.path.abspath(__file__)))[0]
base_path = os.path.split(base_path)[0]
# Load local tempest tests
for test_dir in ['./tempest/api', './tempest/scenario',
'./tempest/thirdparty']:
if not pattern:
@ -32,4 +37,17 @@ def load_tests(loader, tests, pattern):
else:
suite.addTests(loader.discover(test_dir, pattern=pattern,
top_level_dir=base_path))
plugin_load_tests = ext_plugins.get_plugin_load_tests_tuple()
if not plugin_load_tests:
return suite
# Load any installed plugin tests
for plugin in plugin_load_tests:
test_dir, top_path = plugin_load_tests[plugin]
if not pattern:
suite.addTests(loader.discover(test_dir, top_level=top_path))
else:
suite.addTests(loader.discover(test_dir, pattern=pattern,
top_level=top_path))
return suite

View File

@ -10,4 +10,3 @@ mox>=0.5.3
mock>=1.0
coverage>=3.6
oslotest>=1.5.1 # Apache-2.0
stevedore>=1.5.0 # Apache-2.0