Files
cleveragents-core/features/uow_coverage_boost.feature
HAL9000 7536830f85
CI / push-validation (pull_request) Successful in 22s
CI / helm (pull_request) Successful in 31s
CI / build (pull_request) Successful in 45s
CI / quality (pull_request) Successful in 47s
CI / lint (pull_request) Successful in 55s
CI / typecheck (pull_request) Successful in 55s
CI / security (pull_request) Successful in 1m5s
CI / integration_tests (pull_request) Successful in 3m30s
CI / unit_tests (pull_request) Failing after 3m42s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 3s
test(postgresql): add BDD coverage for UoW validation, dispose, context manager and is_postgresql ValueError
Cover previously-uncovered code paths added in the PostgreSQL backend PR:
- UnitOfWork argument validation (empty URL, pool_size=0, max_overflow=-1, pool_recycle=-2)
- dispose() with active engine (True branch) and without engine (False branch)
- __enter__/__exit__ context manager protocol
- psycopg2 ImportError path when psycopg2 is unavailable
- settings.is_postgresql() except ValueError branch (server_mode + SQLite URL)

ISSUES CLOSED: #1118
2026-05-29 03:59:05 -04:00

137 lines
6.6 KiB
Gherkin

@phase1 @domain @unit_of_work @uow_coverage_boost
Feature: UnitOfWork coverage boost for uncovered code paths
As a developer maintaining the UnitOfWork infrastructure
I want thorough coverage of engine creation, checkpoint repository, and refresh
So that all code paths in unit_of_work.py are exercised
# ---------------------------------------------------------------------------
# Engine creation: non-SQLite URL (lines 90-93)
# ---------------------------------------------------------------------------
@uow_non_sqlite_engine
Scenario: UnitOfWork creates engine for non-SQLite database URL
Given a UnitOfWork configured with a non-SQLite database URL
When I access the engine property with mocked create_engine
Then the engine should be created via the non-SQLite code path
And the engine should not use SQLite-specific connect_args
# ---------------------------------------------------------------------------
# Engine creation: fresh in-memory SQLite not yet cached (lines 71-76)
# ---------------------------------------------------------------------------
@uow_fresh_memory_engine
Scenario: UnitOfWork creates new in-memory engine when cache is empty
Given the in-memory engine cache is cleared
And a UnitOfWork configured with an in-memory SQLite URL
When I access the in-memory engine property with mocked migrations
Then a new in-memory engine should be created and cached
And the cached engine should use SERIALIZABLE isolation
# ---------------------------------------------------------------------------
# Checkpoint repository access (lines 244-248)
# ---------------------------------------------------------------------------
@uow_checkpoints_repo
Scenario: UnitOfWorkContext exposes checkpoints repository
Given a UnitOfWorkContext backed by a mock session
When I access the checkpoints repository from the context
Then the checkpoints repository should be a CheckpointRepository instance
@uow_checkpoints_repo_cached
Scenario: UnitOfWorkContext caches checkpoints repository on repeated access
Given a UnitOfWorkContext backed by a mock session
When I access the checkpoints repository from the context twice
Then both accesses should return the same CheckpointRepository instance
# ---------------------------------------------------------------------------
# refresh() method (line 312)
# ---------------------------------------------------------------------------
@uow_refresh_entity
Scenario: UnitOfWorkContext.refresh delegates to session refresh
Given a UnitOfWorkContext backed by a mock session
When I call refresh with a dummy entity
Then session.refresh should have been called with that entity
# ---------------------------------------------------------------------------
# Non-SQLite engine options verification (lines 90-93)
# ---------------------------------------------------------------------------
@uow_non_sqlite_engine_options
Scenario: Non-SQLite engine uses default options without isolation_level override
Given a UnitOfWork configured with a postgresql-style database URL
When I trigger engine creation with mocked dependencies
Then create_engine should have been called without isolation_level
And create_engine should have been called with future=True
# ---------------------------------------------------------------------------
# In-memory engine cache hit vs miss (lines 70-78)
# ---------------------------------------------------------------------------
@uow_memory_engine_cache_hit
Scenario: UnitOfWork reuses cached in-memory engine on second instantiation
Given the in-memory engine cache is cleared
And a first UnitOfWork has already created an in-memory engine
When a second UnitOfWork accesses its engine property
Then the second engine should be the same object as the first
# ---------------------------------------------------------------------------
# Argument validation in __init__ (ValueError raises)
# ---------------------------------------------------------------------------
@uow_validate_empty_url
Scenario: UnitOfWork rejects an empty database_url
When I try to create a UnitOfWork with an empty database_url
Then a ValueError should be raised containing "database_url must be a non-empty string"
@uow_validate_pool_size
Scenario: UnitOfWork rejects pool_size less than 1
When I try to create a UnitOfWork with pool_size set to 0
Then a ValueError should be raised containing "pool_size must be >= 1"
@uow_validate_max_overflow
Scenario: UnitOfWork rejects negative max_overflow
When I try to create a UnitOfWork with max_overflow set to -1
Then a ValueError should be raised containing "max_overflow must be >= 0"
@uow_validate_pool_recycle
Scenario: UnitOfWork rejects pool_recycle below -1
When I try to create a UnitOfWork with pool_recycle set to -2
Then a ValueError should be raised containing "pool_recycle must be >= -1"
# ---------------------------------------------------------------------------
# dispose() method branches (lines 196-205)
# ---------------------------------------------------------------------------
@uow_dispose_active_engine
Scenario: UnitOfWork dispose clears a non-memory engine
Given a UnitOfWork with a mocked non-memory engine
When I call dispose on the UnitOfWork
Then the internal engine should have been disposed and cleared
@uow_dispose_no_engine
Scenario: UnitOfWork dispose is a no-op when engine has not been created
Given a UnitOfWork configured with a non-SQLite database URL
When I call dispose on the UnitOfWork
Then the dispose call should complete without error
# ---------------------------------------------------------------------------
# Context manager protocol (__enter__ / __exit__) (lines 207-213)
# ---------------------------------------------------------------------------
@uow_context_manager_protocol
Scenario: UnitOfWork context manager disposes engine on exit
Given a UnitOfWork with a mocked non-memory engine
When I use the UnitOfWork as a context manager
Then the engine should be disposed on context manager exit
# ---------------------------------------------------------------------------
# psycopg2 ImportError hint (lines 142-148)
# ---------------------------------------------------------------------------
@uow_psycopg2_missing
Scenario: UnitOfWork raises ImportError with install hint when psycopg2 is unavailable
Given a UnitOfWork configured with a non-SQLite database URL
When I access the engine with psycopg2 forcibly unavailable
Then an ImportError should be raised mentioning the server extra