The oslo_db.sqlalchemy.test_fixtures Module

class oslo_db.sqlalchemy.test_fixtures.AdHocDbFixture(url=None)

Bases: oslo_db.sqlalchemy.test_fixtures.SimpleDbFixture

“Fixture which creates and disposes a database engine per test.

Also allows a specific URL to be passed, meaning the fixture can be hardcoded to a specific SQLite file.

For a SQLite, this fixture will create the named database upon setup and tear it down upon teardown. For other databases, the database is assumed to exist already and will remain after teardown.

class oslo_db.sqlalchemy.test_fixtures.BaseDbFixture(driver=None, ident=None)

Bases: fixtures.fixture.Fixture

Base database provisioning fixture.

This serves as the base class for the other fixtures, but by itself does not implement _setUp(). It provides the basis for the flags implemented by the various capability mixins (GenerateSchema, DeletesFromSchema, etc.) as well as providing an abstraction over the provisioning objects, which are specific to testresources. Overall, consumers of this fixture just need to use the right classes and the testresources mechanics are taken care of.

DRIVER = 'sqlite'
get_enginefacade()

Return an enginefacade._TransactionContextManager.

This is typically a global variable like “context_manager” declared in the db/api.py module and is the object returned by enginefacade.transaction_context().

If left not implemented, the global enginefacade manager is used.

For the case where a project uses per-object or per-test enginefacades like Gnocchi, the get_per_test_enginefacade() method should also be implemented.

get_per_test_enginefacade()

Return an enginefacade._TransactionContextManager per test.

This facade should be the one that the test expects the code to use. Usually this is the same one returned by get_engineafacade() which is the default. For special applications like Gnocchi, this can be overridden to provide an instance-level facade.

class oslo_db.sqlalchemy.test_fixtures.DeletesFromSchema

Bases: oslo_db.sqlalchemy.test_fixtures.ResetsData

Mixin defining a fixture that can delete from all tables in place.

When DeletesFromSchema is present in a fixture, _DROP_SCHEMA_PER_TEST is now False; this means that the “teardown” flag of provision.SchemaResource will be False, which prevents SchemaResource from dropping all objects within the schema after each test.

This is a “capability” mixin that works in conjunction with classes that include BaseDbFixture as a base.

delete_from_schema(engine)

A hook which should delete all data from an existing schema.

Should not drop any objects, just remove data from tables that needs to be reset between tests.

reset_schema_data(engine, facade)
class oslo_db.sqlalchemy.test_fixtures.GeneratesSchema

Bases: object

Mixin defining a fixture as generating a schema using create_all().

This is a “capability” mixin that works in conjunction with classes that include BaseDbFixture as a base.

generate_schema_create_all(engine)

A hook which should generate the model schema using create_all().

This hook is called within the scope of creating the database assuming BUILD_WITH_MIGRATIONS is False.

class oslo_db.sqlalchemy.test_fixtures.GeneratesSchemaFromMigrations

Bases: oslo_db.sqlalchemy.test_fixtures.GeneratesSchema

Mixin defining a fixture as generating a schema using migrations.

This is a “capability” mixin that works in conjunction with classes that include BaseDbFixture as a base.

generate_schema_migrations(engine)

A hook which should generate the model schema using migrations.

This hook is called within the scope of creating the database assuming BUILD_WITH_MIGRATIONS is True.

class oslo_db.sqlalchemy.test_fixtures.MySQLOpportunisticFixture(test, driver=None, ident=None)

Bases: oslo_db.sqlalchemy.test_fixtures.OpportunisticDbFixture

DRIVER = 'mysql'
class oslo_db.sqlalchemy.test_fixtures.OpportunisticDBTestMixin

Bases: object

Test mixin that integrates the test suite with testresources.

There are three goals to this system:

  1. Allow creation of “stub” test suites that will run all the tests in a parent suite against a specific kind of database (e.g. Mysql, Postgresql), where the entire suite will be skipped if that target kind of database is not available to the suite.
  2. provide a test with a process-local, anonymously named schema within a target database, so that the test can run concurrently with other tests without conflicting data
  3. provide compatibility with the testresources.OptimisingTestSuite, which organizes TestCase instances ahead of time into groups that all make use of the same type of database, setting up and tearing down a database schema once for the scope of any number of tests within. This technique is essential when testing against a non-SQLite database because building of a schema is expensive, and also is most ideally accomplished using the applications schema migration which are even more vastly slow than a straight create_all().

This mixin provides the .resources attribute required by testresources when using the OptimisingTestSuite.The .resources attribute then provides a collection of testresources.TestResourceManager objects, which are defined here in oslo_db.sqlalchemy.provision. These objects know how to find available database backends, build up temporary databases, and invoke schema generation and teardown instructions. The actual “build the schema objects” part of the equation, and optionally a “delete from all the tables” step, is provided by the implementing application itself.

FIXTURE

alias of OpportunisticDbFixture

SKIP_ON_UNAVAILABLE_DB = True
generate_fixtures()
resources

Provide a collection of TestResourceManager objects.

The collection here is memoized, both at the level of the test case itself, as well as in the fixture object(s) which provide those resources.

setUp()
class oslo_db.sqlalchemy.test_fixtures.OpportunisticDbFixture(test, driver=None, ident=None)

Bases: oslo_db.sqlalchemy.test_fixtures.BaseDbFixture

Fixture which uses testresources fully for optimised runs.

This fixture relies upon the use of the OpportunisticDBTestMixin to supply a test.resources attribute, and also works much more effectively when combined the testresources.OptimisingTestSuite. The optimize_db_test_loader() function should be used at the module and package levels to optimize database provisioning across many tests.

class oslo_db.sqlalchemy.test_fixtures.PostgresqlOpportunisticFixture(test, driver=None, ident=None)

Bases: oslo_db.sqlalchemy.test_fixtures.OpportunisticDbFixture

DRIVER = 'postgresql'
class oslo_db.sqlalchemy.test_fixtures.ReplaceEngineFacadeFixture(enginefacade, replace_with_enginefacade)

Bases: fixtures.fixture.Fixture

A fixture that will plug the engine of one enginefacade into another.

This fixture can be used by test suites that already have their own non- oslo_db database setup / teardown schemes, to plug any URL or test-oriented enginefacade as-is into an enginefacade-oriented API.

For applications that use oslo.db’s testing fixtures, the ReplaceEngineFacade fixture is used internally.

E.g.:

class MyDBTest(TestCase):

    def setUp(self):
        from myapplication.api import main_enginefacade

        my_test_enginefacade = enginefacade.transaction_context()
        my_test_enginefacade.configure(connection=my_test_url)

        self.useFixture(
            ReplaceEngineFacadeFixture(
                main_enginefacade, my_test_enginefacade))

Above, the main_enginefacade object is the normal application level one, and my_test_enginefacade is a local one that we’ve created to refer to some testing database. Throughout the fixture’s setup, the application level enginefacade will use the engine factory and engines of the testing enginefacade, and at fixture teardown will be replaced back.

class oslo_db.sqlalchemy.test_fixtures.ResetsData

Bases: object

Mixin defining a fixture that resets schema data without dropping.

reset_schema_data(engine, enginefacade)

Reset the data in the schema.

setup_for_reset(engine, enginefacade)

“Perform setup that may be needed before the test runs.

class oslo_db.sqlalchemy.test_fixtures.RollsBackTransaction

Bases: oslo_db.sqlalchemy.test_fixtures.ResetsData

Fixture class that maintains a database transaction per test.

reset_schema_data(engine, facade)
setup_for_reset(engine, facade)
class oslo_db.sqlalchemy.test_fixtures.SimpleDbFixture(driver=None, ident=None)

Bases: oslo_db.sqlalchemy.test_fixtures.BaseDbFixture

Fixture which provides an engine from a fixed URL.

The SimpleDbFixture is generally appropriate only for a SQLite memory database, as this database is naturally isolated from other processes and does not require management of schemas. For tests that need to run specifically against MySQL or Postgresql, the OpportunisticDbFixture is more appropriate.

The database connection information itself comes from the provisoning system, matching the desired driver (typically sqlite) to the default URL that provisioning provides for this driver (in the case of sqlite, it’s the SQLite memory URL, e.g. sqlite://. For MySQL and Postgresql, it’s the familiar “openstack_citest” URL on localhost).

There are a variety of create/drop schemes that can take place:

  • The default is to procure a database connection on setup, and at teardown, an instruction is issued to “drop” all objects in the schema (e.g. tables, indexes). The SQLAlchemy engine itself remains referenced at the class level for subsequent re-use.
  • When the GeneratesSchema or GeneratesSchemaFromMigrations mixins are implemented, the appropriate generate_schema method is also called when the fixture is set up, by default this is per test.
  • When the DeletesFromSchema mixin is implemented, the generate_schema method is now only called once, and the “drop all objects” system is replaced with the delete_from_schema method. This allows the same database to remain set up with all schema objects intact, so that expensive migrations need not be run on every test.
  • The fixture does not dispose the engine at the end of a test. It is assumed the same engine will be re-used many times across many tests. The AdHocDbFixture extends this one to provide engine.dispose() at the end of a test.

This fixture is intended to work without needing a reference to the test itself, and therefore cannot take advantage of the OptimisingTestSuite.

oslo_db.sqlalchemy.test_fixtures.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 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.

oslo_db.sqlalchemy.test_fixtures.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 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.