Testing Common Database
testing.common.database is a Python utility library that provides a base class and helpers for testing packages that interact with databases. It offers functionalities like managing temporary database instances, caching initialized databases to speed up tests, and decorators to skip tests if database commands are not found. The current version is 2.0.3, released in 2017, suggesting a maintenance or stable release cadence rather than active development.
Warnings
- deprecated The library has not seen a release since October 2017 (version 2.0.3) and officially supports Python 3.4, 3.5, and 3.6. Using it with newer Python versions (3.7+) may lead to compatibility issues or unaddressed bugs.
- gotcha The `Database` class is designed as an abstract base class. Directly instantiating `testing.common.database.Database` without inheriting and overriding essential methods (e.g., `initialize`, `get_data_directory`, `get_server_commandline`) will result in `NotImplementedError` or incorrect behavior, as it lacks concrete implementation for database interaction.
- gotcha When using `DatabaseFactory(cache_initialized_db=True)`, the initialized database is cached and reused across tests. Failing to call `factory.clear_cache()` in a `tearDownModule` or similar cleanup hook can lead to stale test data or unexpected interactions between unrelated test cases, especially if `on_initialized` is not idempotently handled or test data is not reset.
Install
-
pip install testing-common-database
Imports
- Database
from testing.common.database import Database
- DatabaseFactory
from testing.common.database import DatabaseFactory
- SkipIfNotInstalledDecorator
from testing.common.database import SkipIfNotInstalledDecorator
- get_unused_port
from testing.common.database import get_unused_port
- get_path_of
from testing.common.database import get_path_of
Quickstart
import os
import unittest
from testing.common.database import Database, DatabaseFactory
class MyTestDatabase(Database):
# This is a minimal mock for demonstration; real implementation would
# manage a database server (e.g., PostgreSQL, MySQL).
def initialize(self):
# Simulate database initialization
print(f"[{self.name}] Initializing database...")
def get_data_directory(self):
# Return a temporary directory for data
return os.path.join(self.base_dir, 'data')
def get_server_commandline(self):
# No actual server command for this mock
return ['echo', 'Mock database server started']
def is_server_available(self):
# Always available for this mock
return True
def stop(self):
# Simulate stopping the database
print(f"[{self.name}] Stopping database...")
# Create a factory for the mock database, with caching enabled
# In a real scenario, this would be a specific database factory like PostgresqlFactory
MyCachedDatabase = DatabaseFactory(target_class=MyTestDatabase, cache_initialized_db=True)
# Ensure the cache is cleared after all tests in this module
def tearDownModule():
MyCachedDatabase.clear_cache()
class MyDatabaseTestCase(unittest.TestCase):
def setUp(self):
# Each test gets a fresh copy of the cached database
self.db = MyCachedDatabase()
print(f"Setting up test with database instance at: {self.db.data_dir}")
def tearDown(self):
self.db.stop()
print(f"Tearing down test: {self.db.data_dir}")
def test_database_interaction(self):
# Simulate interacting with the database
self.assertTrue(self.db.is_alive())
print("Performing test operations...")
self.assertIn('data', self.db.data_dir)
if __name__ == '__main__':
unittest.main()