diff --git a/neutron/tests/api/__init__.py b/neutron/tests/api/__init__.py index cbfe3d2c4ab..740001b5399 100644 --- a/neutron/tests/api/__init__.py +++ b/neutron/tests/api/__init__.py @@ -16,8 +16,6 @@ import unittest # Allow the retargetable and tempest api tests to be executed as part # of the same job by ensuring that tests from both tests are # discovered. -# -# TODO(marun) Remove once the tempest tests have been moved to api/ def _discover(loader, path, pattern): @@ -30,8 +28,12 @@ def load_tests(_, tests, pattern): loader = unittest.loader.TestLoader() suite.addTests(_discover(loader, "./neutron/tests/api", pattern)) + # TODO(marun) Remove once the tempest tests have been moved to api/ suite.addTests(_discover(loader, "./neutron/tests/tempest/api/network", pattern)) + suite.addTests(_discover(loader, + "./neutron/tests/retargetable", + pattern)) return suite diff --git a/neutron/tests/api/base_v2.py b/neutron/tests/api/base_v2.py deleted file mode 100644 index 823e1a3af1b..00000000000 --- a/neutron/tests/api/base_v2.py +++ /dev/null @@ -1,129 +0,0 @@ -# Copyright 2014, Red Hat Inc. -# All Rights Reserved. -# -# 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. - -""" -This module defines functional tests for the Neutron V2 API in the -BaseTestApi class. The intention is that the class will be overridden -and configured for use with testscenarios as follows: - - - A subclass should override the 'scenarios' class member with a - list of tuple pairs, e.g. - - scenarios = [('scenario_id', dict(client=Client())] - - The first element of each scenario tuple is a user-defined textual - id, and the second element is a dictionary whose client parameter - should be a subclass of BaseNeutronClient. - - - The module containing the test class should defines a 'load_tests' - variable as follows: - - load_tests = testscenarios.load_tests_apply_scenarios - -Examples of use include: - - neutron.tests.functional.api.test_v2_plugin - targets the plugin api - for each configured plugin - - neutron.tests.api.test_v2_rest_client - targets neutron server - via the tempest rest client - - The tests in neutron.tests.api depend on Neutron and Tempest being - deployed (e.g. with Devstack) and are intended to be run in advisory - check jobs. - -Reference: https://pypi.python.org/pypi/testscenarios/ -""" - -import abc - -import six -import testtools - -from neutron.tests import base - - -@six.add_metaclass(abc.ABCMeta) -class BaseNeutronClient(object): - """ - Base class for a client that can interact the neutron api in some - manner. - - Reference: :file:`neutron/neutron_plugin_base_v2.py` - """ - - def setUp(self, test_case): - """Configure the api for use with a test case - - :param test_case: The test case that will exercise the api - """ - self.test_case = test_case - - @abc.abstractproperty - def NotFound(self): - """The exception that indicates a resource could not be found. - - Tests can use this property to assert for a missing resource - in a client-agnostic way. - """ - - @abc.abstractmethod - def create_network(self, **kwargs): - pass - - @abc.abstractmethod - def update_network(self, id_, **kwargs): - pass - - @abc.abstractmethod - def get_network(self, id_, fields=None): - pass - - @abc.abstractmethod - def get_networks(self, filters=None, fields=None, - sorts=None, limit=None, marker=None, page_reverse=False): - pass - - @abc.abstractmethod - def delete_network(self, id_): - pass - - -class BaseTestApi(base.BaseTestCase): - - scenarios = () - - def setUp(self, setup_parent=True): - # Calling the parent setUp is optional - the subclass may be - # calling it already via a different ancestor. - if setup_parent: - super(BaseTestApi, self).setUp() - self.client.setUp(self) - - def test_network_lifecycle(self): - net = self.client.create_network(name=base.get_rand_name()) - listed_networks = dict((x.id, x.name) - for x in self.client.get_networks()) - self.assertIn(net.id, listed_networks) - self.assertEqual(listed_networks[net.id], net.name, - 'Listed network name is not as expected.') - updated_name = 'new %s' % net.name - updated_net = self.client.update_network(net.id, name=updated_name) - self.assertEqual(updated_name, updated_net.name, - 'Updated network name is not as expected.') - self.client.delete_network(net.id) - with testtools.ExpectedException(self.client.NotFound, - msg='Network was not deleted'): - self.client.get_network(net.id) diff --git a/neutron/tests/api/test_v2_rest.py b/neutron/tests/api/test_v2_rest.py deleted file mode 100644 index 641f5418847..00000000000 --- a/neutron/tests/api/test_v2_rest.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright 2014, Red Hat Inc. -# All Rights Reserved. -# -# 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. - -""" -This module implements BaseNeutronClient for the Tempest rest client -and configures the api tests with scenarios targeting the Neutron API. -""" - -from tempest_lib import exceptions -import testscenarios - -from neutron.tests.api import base_v2 -from neutron.tests import base -from neutron.tests.tempest.api.network import base as t_base - -# Required to generate tests from scenarios. Not compatible with nose. -load_tests = testscenarios.load_tests_apply_scenarios - - -class TempestRestClient(base_v2.BaseNeutronClient): - - @property - def client(self): - if not hasattr(self, '_client'): - manager = t_base.BaseNetworkTest.get_client_manager() - self._client = manager.network_client - return self._client - - @property - def NotFound(self): - return exceptions.NotFound - - def _cleanup_network(self, id_): - try: - self.delete_network(id_) - except self.NotFound: - pass - - def create_network(self, **kwargs): - network = self._create_network(**kwargs) - self.test_case.addCleanup(self._cleanup_network, network.id) - return network - - def _create_network(self, **kwargs): - # Internal method - use create_network() instead - body = self.client.create_network(**kwargs) - return base.AttributeDict(body['network']) - - def update_network(self, id_, **kwargs): - body = self.client.update_network(id_, **kwargs) - return base.AttributeDict(body['network']) - - def get_network(self, id_, **kwargs): - body = self.client.show_network(id_, **kwargs) - return base.AttributeDict(body['network']) - - def get_networks(self, **kwargs): - body = self.client.list_networks(**kwargs) - return [base.AttributeDict(x) for x in body['networks']] - - def delete_network(self, id_): - self.client.delete_network(id_) - - -class TestApiWithRestClient(base_v2.BaseTestApi): - scenarios = [('tempest', {'client': TempestRestClient()})] - - def setUp(self): - raise self.skipException( - 'Tempest fixture requirements prevent this test from running') diff --git a/neutron/tests/functional/__init__.py b/neutron/tests/functional/__init__.py index d9e92950489..50035b2633f 100644 --- a/neutron/tests/functional/__init__.py +++ b/neutron/tests/functional/__init__.py @@ -13,17 +13,11 @@ # under the License. """ -Previously, running 'tox -e dsvm-functional' simply ran a normal test discovery -of the ./neutron/tests/functional tree. In order to save gate resources, we -decided to forgo adding a new gate job specifically for the full-stack -framework, and instead discover tests that are present in -./neutron/tests/fullstack. - -In short, running 'tox -e dsvm-functional' now runs both functional tests and -full-stack tests, and this code allows for the test discovery needed. +In order to save gate resources, test paths that have similar +environmental requirements to the functional path are marked for +discovery. """ -import os import unittest @@ -37,8 +31,8 @@ def load_tests(_, tests, pattern): loader = unittest.loader.TestLoader() suite.addTests(_discover(loader, "./neutron/tests/functional", pattern)) - - if os.getenv('OS_RUN_FULLSTACK') == '1': - suite.addTests(_discover(loader, "./neutron/tests/fullstack", pattern)) + suite.addTests(_discover(loader, "./neutron/tests/fullstack", pattern)) + suite.addTests(_discover(loader, "./neutron/tests/retargetable", + pattern)) return suite diff --git a/neutron/tests/functional/api/test_v2_plugin.py b/neutron/tests/functional/api/test_v2_plugin.py deleted file mode 100644 index 203e584ab7a..00000000000 --- a/neutron/tests/functional/api/test_v2_plugin.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright 2014, Red Hat Inc. -# All Rights Reserved. -# -# 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. - -""" -This module implements BaseNeutronClient for the programmatic plugin -api and configures the api tests with scenarios targeting individual -plugins. -""" - -import testscenarios - -from neutron.common import exceptions as q_exc -from neutron import context -from neutron import manager -from neutron.tests.api import base_v2 -from neutron.tests import base -from neutron.tests.unit.ml2 import test_ml2_plugin -from neutron.tests.unit import testlib_api - - -# Each plugin must add a class to plugin_configurations that can configure the -# plugin for use with PluginClient. For a given plugin, the setup -# used for NeutronDbPluginV2TestCase can usually be reused. See the -# configuration classes listed below for examples of this reuse. - -#TODO(marun) Discover plugin conf via a metaclass -plugin_configurations = [ - test_ml2_plugin.Ml2PluginConf, -] - - -# Required to generate tests from scenarios. Not compatible with nose. -load_tests = testscenarios.load_tests_apply_scenarios - - -class PluginClient(base_v2.BaseNeutronClient): - - @property - def ctx(self): - if not hasattr(self, '_ctx'): - self._ctx = context.Context('', 'test-tenant') - return self._ctx - - @property - def plugin(self): - return manager.NeutronManager.get_plugin() - - @property - def NotFound(self): - return q_exc.NetworkNotFound - - def create_network(self, **kwargs): - # Supply defaults that are expected to be set by the api - # framwork - kwargs.setdefault('admin_state_up', True) - kwargs.setdefault('vlan_transparent', False) - kwargs.setdefault('shared', False) - data = dict(network=kwargs) - result = self.plugin.create_network(self.ctx, data) - return base.AttributeDict(result) - - def update_network(self, id_, **kwargs): - data = dict(network=kwargs) - result = self.plugin.update_network(self.ctx, id_, data) - return base.AttributeDict(result) - - def get_network(self, *args, **kwargs): - result = self.plugin.get_network(self.ctx, *args, **kwargs) - return base.AttributeDict(result) - - def get_networks(self, *args, **kwargs): - result = self.plugin.get_networks(self.ctx, *args, **kwargs) - return [base.AttributeDict(x) for x in result] - - def delete_network(self, id_): - self.plugin.delete_network(self.ctx, id_) - - -def get_scenarios(): - scenarios = [] - client = PluginClient() - for conf in plugin_configurations: - name = conf.plugin_name - class_name = name[name.rfind('.') + 1:] - scenarios.append((class_name, {'client': client, 'plugin_conf': conf})) - return scenarios - - -class TestPluginApi(base_v2.BaseTestApi, - testlib_api.SqlTestCase): - - scenarios = get_scenarios() - - def setUp(self): - # BaseTestApi is not based on BaseTestCase to avoid import - # errors when importing Tempest. When targeting the plugin - # api, it is necessary to avoid calling BaseTestApi's parent - # setUp, since that setup will be called by SqlTestCase.setUp. - super(TestPluginApi, self).setUp(setup_parent=False) - testlib_api.SqlTestCase.setUp(self) - self.useFixture(base.PluginFixture(self.plugin_conf.plugin_name)) - self.plugin_conf.setUp(self) diff --git a/neutron/tests/retargetable/__init__.py b/neutron/tests/retargetable/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/neutron/tests/retargetable/base.py b/neutron/tests/retargetable/base.py new file mode 100644 index 00000000000..fe0e7c79ef1 --- /dev/null +++ b/neutron/tests/retargetable/base.py @@ -0,0 +1,80 @@ +# 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. + +""" +This module defines a base test case that uses testscenarios to +parametize the test methods of subclasses by varying the client +fixture used to target the Neutron API. + +PluginClientFixture targets the Neutron API directly via the plugin +api, and will be executed by default. testscenarios will ensure that +each test is run against all plugins defined in plugin_configurations. + +RestClientFixture targets a deployed Neutron daemon, and will be used +instead of PluginClientFixture only if OS_TEST_API_WITH_REST is set to 1. + +Reference: https://pypi.python.org/pypi/testscenarios/ +""" + +import testscenarios + +from neutron.tests import base as tests_base +from neutron.tests.retargetable import client_fixtures +from neutron.tests.unit.ml2 import test_ml2_plugin + + +# Each plugin must add a class to plugin_configurations that can configure the +# plugin for use with PluginClient. For a given plugin, the setup +# used for NeutronDbPluginV2TestCase can usually be reused. See the +# configuration classes listed below for examples of this reuse. + +# TODO(marun) Discover plugin conf via a metaclass +plugin_configurations = [ + test_ml2_plugin.Ml2ConfFixture(), +] + + +def rest_enabled(): + return tests_base.bool_from_env('OS_TEST_API_WITH_REST') + + +def get_plugin_scenarios(): + scenarios = [] + for conf in plugin_configurations: + name = conf.plugin_name + class_name = name.rsplit('.', 1)[-1] + client = client_fixtures.PluginClientFixture(conf) + scenarios.append((class_name, {'client': client})) + return scenarios + + +def get_scenarios(): + if rest_enabled(): + # FIXME(marun) Remove local import once tempest config is safe + # to import alonside neutron config + from neutron.tests.retargetable import rest_fixture + return [('tempest', {'client': rest_fixture.RestClientFixture()})] + else: + return get_plugin_scenarios() + + +class RetargetableApiTest(testscenarios.WithScenarios, + tests_base.BaseTestCase): + + scenarios = get_scenarios() + + def setUp(self): + super(RetargetableApiTest, self).setUp() + if rest_enabled(): + raise self.skipException( + 'Tempest fixture requirements prevent this test from running') + self.useFixture(self.client) diff --git a/neutron/tests/retargetable/client_fixtures.py b/neutron/tests/retargetable/client_fixtures.py new file mode 100644 index 00000000000..75d9091a0bb --- /dev/null +++ b/neutron/tests/retargetable/client_fixtures.py @@ -0,0 +1,117 @@ +# 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. + +""" +This module defines client fixtures that can be used to target the +Neutron API via different methods. +""" + +import abc + +import fixtures +import six + +from neutron.common import exceptions as q_exc +from neutron import context +from neutron import manager +from neutron.tests import base +from neutron.tests.unit import testlib_api + + +@six.add_metaclass(abc.ABCMeta) +class AbstractClientFixture(fixtures.Fixture): + """ + Base class for a client that can interact the neutron api in some + manner. + """ + + @abc.abstractproperty + def NotFound(self): + """The exception that indicates a resource could not be found. + + Tests can use this property to assert for a missing resource + in a client-agnostic way. + """ + + @abc.abstractmethod + def create_network(self, **kwargs): + pass + + @abc.abstractmethod + def update_network(self, id_, **kwargs): + pass + + @abc.abstractmethod + def get_network(self, id_, fields=None): + pass + + @abc.abstractmethod + def get_networks(self, filters=None, fields=None, + sorts=None, limit=None, marker=None, page_reverse=False): + pass + + @abc.abstractmethod + def delete_network(self, id_): + pass + + +class PluginClientFixture(AbstractClientFixture): + """Targets the Neutron API via the plugin API""" + + def __init__(self, plugin_conf): + self.plugin_conf = plugin_conf + + def setUp(self): + super(PluginClientFixture, self).setUp() + self.useFixture(testlib_api.SqlFixture()) + self.useFixture(self.plugin_conf) + self.useFixture(base.PluginFixture(self.plugin_conf.plugin_name)) + + @property + def ctx(self): + if not hasattr(self, '_ctx'): + self._ctx = context.Context('', 'test-tenant') + return self._ctx + + @property + def plugin(self): + return manager.NeutronManager.get_plugin() + + @property + def NotFound(self): + return q_exc.NetworkNotFound + + def create_network(self, **kwargs): + # Supply defaults that are expected to be set by the api + # framwork + kwargs.setdefault('admin_state_up', True) + kwargs.setdefault('vlan_transparent', False) + kwargs.setdefault('shared', False) + data = dict(network=kwargs) + result = self.plugin.create_network(self.ctx, data) + return base.AttributeDict(result) + + def update_network(self, id_, **kwargs): + data = dict(network=kwargs) + result = self.plugin.update_network(self.ctx, id_, data) + return base.AttributeDict(result) + + def get_network(self, *args, **kwargs): + result = self.plugin.get_network(self.ctx, *args, **kwargs) + return base.AttributeDict(result) + + def get_networks(self, *args, **kwargs): + result = self.plugin.get_networks(self.ctx, *args, **kwargs) + return [base.AttributeDict(x) for x in result] + + def delete_network(self, id_): + self.plugin.delete_network(self.ctx, id_) diff --git a/neutron/tests/retargetable/rest_fixture.py b/neutron/tests/retargetable/rest_fixture.py new file mode 100644 index 00000000000..9255459730e --- /dev/null +++ b/neutron/tests/retargetable/rest_fixture.py @@ -0,0 +1,70 @@ +# 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. + +""" +This module defines a client fixture that can be used to target a +deployed neutron daemon. The potential for conflict between Tempest +configuration and Neutron configuration requires that +neutron.tests.tempest imports be isolated in this module for now. +""" + +from tempest_lib import exceptions as tlib_exceptions + +from neutron.tests import base +from neutron.tests.retargetable import client_fixtures +from neutron.tests.tempest import test as t_test + + +class RestClientFixture(client_fixtures.AbstractClientFixture): + """Targets the Neutron API via REST.""" + + @property + def client(self): + if not hasattr(self, '_client'): + manager = t_test.BaseTestCase.get_client_manager() + self._client = manager.network_client + return self._client + + @property + def NotFound(self): + return tlib_exceptions.NotFound + + def _cleanup_network(self, id_): + try: + self.delete_network(id_) + except self.NotFound: + pass + + def create_network(self, **kwargs): + network = self._create_network(**kwargs) + self.addCleanup(self._cleanup_network, network.id) + return network + + def _create_network(self, **kwargs): + # Internal method - use create_network() instead + body = self.client.create_network(**kwargs) + return base.AttributeDict(body['network']) + + def update_network(self, id_, **kwargs): + body = self.client.update_network(id_, **kwargs) + return base.AttributeDict(body['network']) + + def get_network(self, id_, **kwargs): + body = self.client.show_network(id_, **kwargs) + return base.AttributeDict(body['network']) + + def get_networks(self, **kwargs): + body = self.client.list_networks(**kwargs) + return [base.AttributeDict(x) for x in body['networks']] + + def delete_network(self, id_): + self.client.delete_network(id_) diff --git a/neutron/tests/retargetable/test_example.py b/neutron/tests/retargetable/test_example.py new file mode 100644 index 00000000000..02e7cb6f01e --- /dev/null +++ b/neutron/tests/retargetable/test_example.py @@ -0,0 +1,39 @@ +# 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 testtools + +from neutron.tests import base as tests_base +from neutron.tests.retargetable import base + + +class TestExample(base.RetargetableApiTest): + """This class is an example of how to write a retargetable api test. + + See the parent class for details about how the 'client' attribute + is configured via testscenarios. + """ + + def test_network_lifecycle(self): + net = self.client.create_network(name=tests_base.get_rand_name()) + listed_networks = {x.id: x.name for x in self.client.get_networks()} + self.assertIn(net.id, listed_networks) + self.assertEqual(listed_networks[net.id], net.name, + 'Listed network name is not as expected.') + updated_name = 'new %s' % net.name + updated_net = self.client.update_network(net.id, name=updated_name) + self.assertEqual(updated_name, updated_net.name, + 'Updated network name is not as expected.') + self.client.delete_network(net.id) + with testtools.ExpectedException(self.client.NotFound, + msg='Network was not deleted'): + self.client.get_network(net.id) diff --git a/neutron/tests/tempest/README.rst b/neutron/tests/tempest/README.rst index bc57df40a97..6f50970c218 100644 --- a/neutron/tests/tempest/README.rst +++ b/neutron/tests/tempest/README.rst @@ -4,3 +4,7 @@ WARNING The files under this path are maintained automatically by the script tools/copy_api_tests_from_tempest.sh. It's contents should not be manually modified until further notice. + +Note that neutron.tests.tempest.config uses the global cfg.CONF +instance for now and importing it outside of the api tests has the +potential to break Neutron's use of cfg.CONF. diff --git a/neutron/tests/unit/ml2/test_ml2_plugin.py b/neutron/tests/unit/ml2/test_ml2_plugin.py index 1eef9e13601..1723b81252c 100644 --- a/neutron/tests/unit/ml2/test_ml2_plugin.py +++ b/neutron/tests/unit/ml2/test_ml2_plugin.py @@ -21,6 +21,7 @@ import testtools import uuid import webob +import fixtures from oslo_db import exception as db_exc from neutron.callbacks import registry @@ -66,20 +67,24 @@ DEVICE_OWNER_COMPUTE = 'compute:None' HOST = 'fake_host' -class Ml2PluginConf(object): - """Plugin configuration shared across the unit and functional tests. +# TODO(marun) - Move to somewhere common for reuse +class PluginConfFixture(fixtures.Fixture): + """Plugin configuration shared across the unit and functional tests.""" - TODO(marun) Evolve a configuration interface usable across all plugins. - """ + def __init__(self, plugin_name, parent_setup=None): + self.plugin_name = plugin_name + self.parent_setup = parent_setup - plugin_name = PLUGIN_NAME + def setUp(self): + super(PluginConfFixture, self).setUp() + if self.parent_setup: + self.parent_setup() - @staticmethod - def setUp(test_case, parent_setup=None): - """Perform additional configuration around the parent's setUp.""" - if parent_setup: - parent_setup() - test_case.port_create_status = 'DOWN' + +class Ml2ConfFixture(PluginConfFixture): + + def __init__(self, parent_setup=None): + super(Ml2ConfFixture, self).__init__(PLUGIN_NAME, parent_setup) class Ml2PluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase): @@ -95,10 +100,11 @@ class Ml2PluginV2TestCase(test_plugin.NeutronDbPluginV2TestCase): # by the common configuration setUp. parent_setup = functools.partial( super(Ml2PluginV2TestCase, self).setUp, - plugin=Ml2PluginConf.plugin_name, + plugin=PLUGIN_NAME, service_plugins=service_plugins, ) - Ml2PluginConf.setUp(self, parent_setup) + self.useFixture(Ml2ConfFixture(parent_setup)) + self.port_create_status = 'DOWN' def setUp(self): # Enable the test mechanism driver to ensure that diff --git a/neutron/tests/unit/testlib_api.py b/neutron/tests/unit/testlib_api.py index bb482ababe5..bbfa1bbbed3 100644 --- a/neutron/tests/unit/testlib_api.py +++ b/neutron/tests/unit/testlib_api.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +import fixtures import testtools from neutron.db import api as db_api @@ -52,18 +53,18 @@ def create_request(path, body, content_type, method='GET', return req -class SqlTestCase(base.BaseTestCase): +class SqlFixture(fixtures.Fixture): # flag to indicate that the models have been loaded _TABLES_ESTABLISHED = False def setUp(self): - super(SqlTestCase, self).setUp() + super(SqlFixture, self).setUp() # Register all data models engine = db_api.get_engine() - if not SqlTestCase._TABLES_ESTABLISHED: + if not SqlFixture._TABLES_ESTABLISHED: model_base.BASEV2.metadata.create_all(engine) - SqlTestCase._TABLES_ESTABLISHED = True + SqlFixture._TABLES_ESTABLISHED = True def clear_tables(): with engine.begin() as conn: @@ -74,6 +75,13 @@ class SqlTestCase(base.BaseTestCase): self.addCleanup(clear_tables) +class SqlTestCase(base.BaseTestCase): + + def setUp(self): + super(SqlTestCase, self).setUp() + self.useFixture(SqlFixture()) + + class WebTestCase(SqlTestCase): fmt = 'json' diff --git a/tox.ini b/tox.ini index 40c44d75723..a32fa8c3429 100644 --- a/tox.ini +++ b/tox.ini @@ -28,6 +28,7 @@ setenv = VIRTUAL_ENV={envdir} [testenv:api] setenv = OS_TEST_PATH=./neutron/tests/api TEMPEST_CONFIG_DIR={env:TEMPEST_CONFIG_DIR:/opt/stack/tempest/etc} + OS_TEST_API_WITH_REST=1 [testenv:functional] setenv = OS_TEST_PATH=./neutron/tests/functional @@ -43,7 +44,6 @@ setenv = OS_TEST_PATH=./neutron/tests/functional OS_ROOTWRAP_DAEMON_CMD=sudo {envbindir}/neutron-rootwrap-daemon {envdir}/etc/neutron/rootwrap.conf OS_FAIL_ON_MISSING_DEPS=1 OS_TEST_TIMEOUT=90 - OS_RUN_FULLSTACK=1 sitepackages=True deps = {[testenv:functional]deps}