Research-Stack/4-Infrastructure/NoDupeLabs/tests/database/test_query_coverage.py

438 lines
14 KiB
Python

# SPDX-License-Identifier: Apache-2.0
# Copyright (c) 2025 NoDupeLabs
"""Tests to achieve 100% coverage on query.py module.
This test file targets the missing coverage in:
- query.py: Query optimization paths, batch operations, performance monitoring
"""
from unittest.mock import MagicMock
import pytest
from nodupe.tools.databases.query import (
DatabaseBackup,
DatabaseBatch,
DatabaseIntegrity,
DatabaseMigration,
DatabaseOptimization,
DatabasePerformance,
DatabaseQuery,
DatabaseRecovery,
)
class TestDatabaseQueryCoverage:
"""Tests for DatabaseQuery class to achieve 100% coverage."""
def test_execute_with_get_connection(self):
"""Test execute when db has get_connection method."""
mock_db = MagicMock()
mock_conn = MagicMock()
mock_cursor = MagicMock()
mock_db.get_connection.return_value = mock_conn
mock_conn.cursor.return_value = mock_cursor
mock_cursor.fetchall.return_value = [('row1_col1', 'row1_col2'), ('row2_col1', 'row2_col2')]
mock_cursor.description = [('col1',), ('col2',)]
query = DatabaseQuery(mock_db)
results = query.execute("SELECT * FROM test")
assert len(results) == 2
assert results[0] == {'col1': 'row1_col1', 'col2': 'row1_col2'}
assert results[1] == {'col1': 'row2_col1', 'col2': 'row2_col2'}
mock_db.get_connection.assert_called_once()
def test_execute_with_connect(self):
"""Test execute when db has connect method (no get_connection)."""
mock_db = MagicMock()
del mock_db.get_connection # Remove get_connection attribute
mock_conn = MagicMock()
mock_cursor = MagicMock()
mock_db.connect.return_value = mock_conn
mock_conn.cursor.return_value = mock_cursor
mock_cursor.fetchall.return_value = []
mock_cursor.description = [('col1',)]
query = DatabaseQuery(mock_db)
results = query.execute("SELECT * FROM test")
assert results == []
mock_db.connect.assert_called_once()
def test_execute_with_params(self):
"""Test execute with parameters."""
mock_db = MagicMock()
mock_conn = MagicMock()
mock_cursor = MagicMock()
mock_db.get_connection.return_value = mock_conn
mock_conn.cursor.return_value = mock_cursor
mock_cursor.fetchall.return_value = []
mock_cursor.description = [('col1',)]
query = DatabaseQuery(mock_db)
query.execute("SELECT * FROM test WHERE id = ?", (123,))
mock_cursor.execute.assert_called_once_with("SELECT * FROM test WHERE id = ?", (123,))
def test_execute_no_params(self):
"""Test execute without parameters (uses empty tuple)."""
mock_db = MagicMock()
mock_conn = MagicMock()
mock_cursor = MagicMock()
mock_db.get_connection.return_value = mock_conn
mock_conn.cursor.return_value = mock_cursor
mock_cursor.fetchall.return_value = []
mock_cursor.description = [('col1',)]
query = DatabaseQuery(mock_db)
query.execute("SELECT * FROM test")
mock_cursor.execute.assert_called_once_with("SELECT * FROM test", ())
class TestDatabaseBatchCoverage:
"""Tests for DatabaseBatch class to achieve 100% coverage."""
def test_execute_batch_with_get_connection(self):
"""Test execute_batch when db has get_connection method."""
mock_db = MagicMock()
mock_conn = MagicMock()
mock_cursor = MagicMock()
mock_db.get_connection.return_value = mock_conn
mock_conn.cursor.return_value = mock_cursor
batch = DatabaseBatch(mock_db)
operations = [
("INSERT INTO test VALUES (?, ?)", (1, 'a')),
("UPDATE test SET col = ?", ('b',)),
]
batch.execute_batch(operations)
assert mock_cursor.execute.call_count == 2
mock_conn.commit.assert_called_once()
def test_execute_batch_with_connect(self):
"""Test execute_batch when db has connect method."""
mock_db = MagicMock()
del mock_db.get_connection
mock_conn = MagicMock()
mock_cursor = MagicMock()
mock_db.connect.return_value = mock_conn
mock_conn.cursor.return_value = mock_cursor
batch = DatabaseBatch(mock_db)
batch.execute_batch([("INSERT INTO test VALUES (1)", ())])
mock_db.connect.assert_called_once()
def test_execute_transaction_batch_success(self):
"""Test execute_transaction_batch successful commit."""
mock_db = MagicMock()
mock_conn = MagicMock()
mock_cursor = MagicMock()
mock_db.get_connection.return_value = mock_conn
mock_conn.cursor.return_value = mock_cursor
batch = DatabaseBatch(mock_db)
operations = [("INSERT INTO test VALUES (?)", (1,))]
batch.execute_transaction_batch(operations)
mock_conn.commit.assert_called_once()
mock_conn.rollback.assert_not_called()
def test_execute_transaction_batch_rollback(self):
"""Test execute_transaction_batch rollback on exception."""
mock_db = MagicMock()
mock_conn = MagicMock()
mock_cursor = MagicMock()
mock_db.get_connection.return_value = mock_conn
mock_conn.cursor.return_value = mock_cursor
mock_cursor.execute.side_effect = Exception("Query failed")
batch = DatabaseBatch(mock_db)
operations = [("INSERT INTO test VALUES (?)", (1,))]
with pytest.raises(Exception, match="Query failed"):
batch.execute_transaction_batch(operations)
mock_conn.rollback.assert_called_once()
mock_conn.commit.assert_not_called()
class TestDatabasePerformanceCoverage:
"""Tests for DatabasePerformance class to achieve 100% coverage."""
def test_get_metrics(self):
"""Test get_metrics returns metrics dict."""
mock_db = MagicMock()
perf = DatabasePerformance(mock_db)
metrics = perf.get_metrics()
assert 'metrics' in metrics
assert metrics['metrics']['queries'] == 0
assert metrics['metrics']['total_time'] == 0.0
assert metrics['metrics']['avg_time'] == 0.0
def test_record_query_first(self):
"""Test record_query for first query."""
mock_db = MagicMock()
perf = DatabasePerformance(mock_db)
perf.record_query(0.5)
assert perf._metrics['queries'] == 1
assert perf._metrics['total_time'] == 0.5
assert perf._metrics['avg_time'] == 0.5
def test_record_query_multiple(self):
"""Test record_query for multiple queries."""
mock_db = MagicMock()
perf = DatabasePerformance(mock_db)
perf.record_query(0.3)
perf.record_query(0.5)
perf.record_query(0.4)
assert perf._metrics['queries'] == 3
assert perf._metrics['total_time'] == pytest.approx(1.2)
assert perf._metrics['avg_time'] == pytest.approx(0.4)
def test_monitor_performance(self):
"""Test monitor_performance returns db.monitoring."""
mock_db = MagicMock()
mock_monitoring = MagicMock()
mock_db.monitoring = mock_monitoring
perf = DatabasePerformance(mock_db)
result = perf.monitor_performance()
assert result is mock_monitoring
def test_get_results(self):
"""Test get_results returns db.monitoring.get_metrics()."""
mock_db = MagicMock()
mock_monitoring = MagicMock()
mock_monitoring.get_metrics.return_value = {'test': 'metrics'}
mock_db.monitoring = mock_monitoring
perf = DatabasePerformance(mock_db)
result = perf.get_results()
assert result == {'test': 'metrics'}
mock_monitoring.get_metrics.assert_called_once()
class TestDatabaseIntegrityCoverage:
"""Tests for DatabaseIntegrity class to achieve 100% coverage."""
def test_validate(self):
"""Test validate returns expected format."""
mock_db = MagicMock()
integrity = DatabaseIntegrity(mock_db)
result = integrity.validate()
assert 'valid' in result
assert 'errors' in result
assert 'tables' in result
assert result['valid'] is True
assert result['errors'] == []
assert result['tables'] == []
def test_check_integrity(self):
"""Test check_integrity returns expected format with indexes."""
mock_db = MagicMock()
integrity = DatabaseIntegrity(mock_db)
result = integrity.check_integrity()
assert 'valid' in result
assert 'errors' in result
assert 'tables' in result
assert 'indexes' in result
assert result['valid'] is True
assert result['errors'] == []
assert result['tables'] == []
assert result['indexes'] == []
class TestDatabaseBackupCoverage:
"""Tests for DatabaseBackup class to achieve 100% coverage."""
def test_create_backup(self, tmp_path):
"""Test create_backup copies database file."""
mock_db = MagicMock()
source_db = tmp_path / "source.db"
source_db.write_bytes(b"database content")
mock_db.path = str(source_db)
backup_path = tmp_path / "backup.db"
backup = DatabaseBackup(mock_db)
backup.create_backup(str(backup_path))
assert backup_path.exists()
assert backup_path.read_bytes() == b"database content"
def test_restore_backup(self, tmp_path):
"""Test restore_backup copies backup to restore path."""
mock_db = MagicMock()
backup_file = tmp_path / "backup.db"
backup_file.write_bytes(b"backup content")
restore_path = tmp_path / "restored.db"
backup = DatabaseBackup(mock_db)
backup.restore_backup(str(backup_file), str(restore_path))
assert restore_path.exists()
assert restore_path.read_bytes() == b"backup content"
class TestDatabaseMigrationCoverage:
"""Tests for DatabaseMigration class to achieve 100% coverage."""
def test_migrate_schema(self):
"""Test migrate_schema (pass-through implementation)."""
mock_db = MagicMock()
migration = DatabaseMigration(mock_db)
migrations = {
'table1': {'add': ['col1'], 'remove': []},
}
# Should not raise (pass-through implementation)
migration.migrate_schema(migrations)
def test_migrate_data(self):
"""Test migrate_data (pass-through implementation)."""
mock_db = MagicMock()
migration = DatabaseMigration(mock_db)
transformations = {'col1': 'UPPER(col1)'}
new_columns = ['col2']
# Should not raise (pass-through implementation)
migration.migrate_data('table1', transformations, new_columns)
def test_migrate_data_no_new_columns(self):
"""Test migrate_data without new_columns parameter."""
mock_db = MagicMock()
migration = DatabaseMigration(mock_db)
transformations = {'col1': 'UPPER(col1)'}
# Should not raise (pass-through implementation)
migration.migrate_data('table1', transformations)
class TestDatabaseRecoveryCoverage:
"""Tests for DatabaseRecovery class to achieve 100% coverage."""
def test_handle_errors_success(self):
"""Test handle_errors when integrity check passes."""
mock_db = MagicMock()
mock_integrity = MagicMock()
mock_integrity.check_integrity.return_value = {'valid': True, 'errors': []}
mock_db.integrity = mock_integrity
recovery = DatabaseRecovery(mock_db)
result = recovery.handle_errors(raise_on_error=False)
assert result is True
def test_handle_errors_invalid_not_raise(self):
"""Test handle_errors when integrity check fails (not raising)."""
mock_db = MagicMock()
mock_integrity = MagicMock()
mock_integrity.check_integrity.return_value = {'valid': False, 'errors': ['error1']}
mock_db.integrity = mock_integrity
recovery = DatabaseRecovery(mock_db)
result = recovery.handle_errors(raise_on_error=False)
assert result is False
def test_handle_errors_invalid_raise(self):
"""Test handle_errors when integrity check fails (raising)."""
mock_db = MagicMock()
mock_integrity = MagicMock()
mock_integrity.check_integrity.return_value = {'valid': False, 'errors': ['error1']}
mock_db.integrity = mock_integrity
recovery = DatabaseRecovery(mock_db)
with pytest.raises(Exception, match="Database integrity check failed"):
recovery.handle_errors(raise_on_error=True)
def test_handle_errors_exception_not_raise(self):
"""Test handle_errors when exception occurs (not raising)."""
mock_db = MagicMock()
mock_db.integrity.check_integrity.side_effect = Exception("DB error")
recovery = DatabaseRecovery(mock_db)
result = recovery.handle_errors(raise_on_error=False)
assert result is False
def test_handle_errors_exception_raise(self):
"""Test handle_errors when exception occurs (raising)."""
mock_db = MagicMock()
mock_db.integrity.check_integrity.side_effect = Exception("DB error")
recovery = DatabaseRecovery(mock_db)
with pytest.raises(Exception, match="DB error"):
recovery.handle_errors(raise_on_error=True)
class TestDatabaseOptimizationCoverage:
"""Tests for DatabaseOptimization class to achieve 100% coverage."""
def test_optimize_query_basic(self):
"""Test optimize_query strips and removes trailing semicolon."""
mock_db = MagicMock()
optimization = DatabaseOptimization(mock_db)
result = optimization.optimize_query("SELECT * FROM test; ")
assert result == "SELECT * FROM test"
def test_optimize_query_no_semicolon(self):
"""Test optimize_query when no trailing semicolon."""
mock_db = MagicMock()
optimization = DatabaseOptimization(mock_db)
result = optimization.optimize_query("SELECT * FROM test")
assert result == "SELECT * FROM test"
def test_optimize_query_whitespace_only(self):
"""Test optimize_query with whitespace-only query."""
mock_db = MagicMock()
optimization = DatabaseOptimization(mock_db)
result = optimization.optimize_query(" ; ")
assert result == ""
def test_optimize_query_empty(self):
"""Test optimize_query with empty query."""
mock_db = MagicMock()
optimization = DatabaseOptimization(mock_db)
result = optimization.optimize_query("")
assert result == ""