Merge "Break optimize_db_test_loader into package and module level"

This commit is contained in:
Jenkins 2016-11-20 21:29:46 +00:00 committed by Gerrit Code Review
commit accd272d15
3 changed files with 166 additions and 39 deletions

View File

@ -14,9 +14,9 @@
# under the License. # under the License.
import debtcollector import debtcollector
import debtcollector.moves
import fixtures import fixtures
import testresources import testresources
import testscenarios
try: try:
from oslotest import base as test_base from oslotest import base as test_base
@ -25,8 +25,6 @@ except ImportError:
' test-requirements') ' test-requirements')
import os
from oslo_utils import reflection from oslo_utils import reflection
import six import six
@ -34,6 +32,7 @@ from oslo_db import exception
from oslo_db.sqlalchemy import enginefacade from oslo_db.sqlalchemy import enginefacade
from oslo_db.sqlalchemy import provision from oslo_db.sqlalchemy import provision
from oslo_db.sqlalchemy import session from oslo_db.sqlalchemy import session
from oslo_db.sqlalchemy.test_fixtures import optimize_package_test_loader
@debtcollector.removals.removed_class("DbFixture") @debtcollector.removals.removed_class("DbFixture")
@ -245,39 +244,5 @@ class PostgreSQLOpportunisticTestCase(OpportunisticTestCase):
FIXTURE = PostgreSQLOpportunisticFixture FIXTURE = PostgreSQLOpportunisticFixture
def optimize_db_test_loader(file_): optimize_db_test_loader = debtcollector.moves.moved_function(
"""Package level load_tests() function. optimize_package_test_loader, "optimize_db_test_loader", __name__)
Will apply an optimizing test suite to all sub-tests, which groups DB
tests and other resources appropriately.
Place this in an __init__.py package file within the root of the test
suite, at the level where testresources loads it as a package::
from oslo_db.sqlalchemy import test_base
load_tests = test_base.optimize_db_test_loader(__file__)
Alternatively, the directive can be placed into a test module directly.
"""
this_dir = os.path.dirname(file_)
def load_tests(loader, found_tests, pattern):
# pattern is None if the directive is placed within
# a test module directly, as well as within certain test
# discovery patterns
if pattern is not None:
pkg_tests = loader.discover(start_dir=this_dir, pattern=pattern)
result = testresources.OptimisingTestSuite()
found_tests = testscenarios.load_tests_apply_scenarios(
loader, found_tests, pattern)
result.addTest(found_tests)
if pattern is not None:
result.addTest(pkg_tests)
return result
return load_tests

View File

@ -15,7 +15,9 @@
import fixtures import fixtures
import logging import logging
import os
import testresources import testresources
import testscenarios
from oslo_db import exception from oslo_db import exception
from oslo_db.sqlalchemy import enginefacade from oslo_db.sqlalchemy import enginefacade
@ -544,3 +546,79 @@ class MySQLOpportunisticFixture(OpportunisticDbFixture):
class PostgresqlOpportunisticFixture(OpportunisticDbFixture): class PostgresqlOpportunisticFixture(OpportunisticDbFixture):
DRIVER = 'postgresql' DRIVER = 'postgresql'
def optimize_package_test_loader(file_):
"""Organize package-level tests into a testresources.OptimizingTestSuite.
This function provides a unittest-compatible load_tests hook
for a given package; for per-module, use the
:func:`.optimize_module_test_loader` function.
When a unitest or subunit style
test runner is used, the function will be called in order to
return a TestSuite containing the tests to run; this function
ensures that this suite is an OptimisingTestSuite, which will organize
the production of test resources across groups of tests at once.
The function is invoked as::
from oslo_db.sqlalchemy import test_base
load_tests = test_base.optimize_package_test_loader(__file__)
The loader *must* be present in the package level __init__.py.
The function also applies testscenarios expansion to all test collections.
This so that an existing test suite that already needs to build
TestScenarios from a load_tests call can still have this take place when
replaced with this function.
"""
this_dir = os.path.dirname(file_)
def load_tests(loader, found_tests, pattern):
result = testresources.OptimisingTestSuite()
result.addTests(found_tests)
pkg_tests = loader.discover(start_dir=this_dir, pattern=pattern)
result.addTests(testscenarios.generate_scenarios(pkg_tests))
return result
return load_tests
def optimize_module_test_loader():
"""Organize module-level tests into a testresources.OptimizingTestSuite.
This function provides a unittest-compatible load_tests hook
for a given module; for per-package, use the
:func:`.optimize_package_test_loader` function.
When a unitest or subunit style
test runner is used, the function will be called in order to
return a TestSuite containing the tests to run; this function
ensures that this suite is an OptimisingTestSuite, which will organize
the production of test resources across groups of tests at once.
The function is invoked as::
from oslo_db.sqlalchemy import test_base
load_tests = test_base.optimize_module_test_loader()
The loader *must* be present in an individual module, and *not* the
package level __init__.py.
The function also applies testscenarios expansion to all test collections.
This so that an existing test suite that already needs to build
TestScenarios from a load_tests call can still have this take place when
replaced with this function.
"""
def load_tests(loader, found_tests, pattern):
result = testresources.OptimisingTestSuite()
result.addTests(testscenarios.generate_scenarios(found_tests))
return result
return load_tests

View File

@ -11,7 +11,10 @@
# under the License. # under the License.
import mock import mock
import os
import testresources import testresources
import testscenarios
import unittest
from oslo_db.sqlalchemy import enginefacade from oslo_db.sqlalchemy import enginefacade
from oslo_db.sqlalchemy import provision from oslo_db.sqlalchemy import provision
@ -19,6 +22,8 @@ from oslo_db.sqlalchemy import test_base as legacy_test_base
from oslo_db.sqlalchemy import test_fixtures from oslo_db.sqlalchemy import test_fixtures
from oslotest import base as oslo_test_base from oslotest import base as oslo_test_base
start_dir = os.path.dirname(__file__)
class BackendSkipTest(oslo_test_base.BaseTestCase): class BackendSkipTest(oslo_test_base.BaseTestCase):
@ -212,3 +217,82 @@ class LegacyBaseClassTest(oslo_test_base.BaseTestCase):
db_resource = dict(st.resources)['db'] db_resource = dict(st.resources)['db']
self.assertTrue(db_resource.provision_new_database) self.assertTrue(db_resource.provision_new_database)
class TestLoadHook(unittest.TestCase):
"""Test the 'load_tests' hook supplied by test_base.
The purpose of this loader is to organize tests into an
OptimisingTestSuite using the standard unittest load_tests hook.
The hook needs to detect if it is being invoked at the module
level or at the package level. It has to behave completely differently
in these two cases.
"""
def test_module_level(self):
load_tests = test_fixtures.optimize_module_test_loader()
loader = unittest.TestLoader()
found_tests = loader.discover(start_dir, pattern="test_fixtures.py")
new_loader = load_tests(loader, found_tests, "test_fixtures.py")
self.assertTrue(
isinstance(new_loader, testresources.OptimisingTestSuite)
)
actual_tests = unittest.TestSuite(
testscenarios.generate_scenarios(found_tests)
)
self.assertEqual(
new_loader.countTestCases(), actual_tests.countTestCases()
)
def test_package_level(self):
self._test_package_level(test_fixtures.optimize_package_test_loader)
def test_package_level_legacy(self):
self._test_package_level(legacy_test_base.optimize_db_test_loader)
def _test_package_level(self, fn):
load_tests = fn(
os.path.join(start_dir, "__init__.py"))
loader = unittest.TestLoader()
new_loader = load_tests(
loader, unittest.suite.TestSuite(), "test_fixtures.py")
self.assertTrue(
isinstance(new_loader, testresources.OptimisingTestSuite)
)
actual_tests = unittest.TestSuite(
testscenarios.generate_scenarios(
loader.discover(start_dir, pattern="test_fixtures.py"))
)
self.assertEqual(
new_loader.countTestCases(), actual_tests.countTestCases()
)
class TestWScenarios(unittest.TestCase):
"""a 'do nothing' test suite.
Should generate exactly four tests when testscenarios is used.
"""
def test_one(self):
pass
def test_two(self):
pass
scenarios = [
('scenario1', dict(scenario='scenario 1')),
('scenario2', dict(scenario='scenario 2'))
]