forked from cleveragents/cleveragents-core
test: add TDD bug-capture test for #986 — CorrectionService checkpoint_service wiring
Add a Behave feature with two scenarios that verify the DI container wires checkpoint_service into CorrectionService. Both assertions currently fail — proving bug #986 exists — and the @tdd_expected_fail tag inverts the result so the test passes CI while the bug is unfixed. Scenario 1 asserts _checkpoint_service is not None after resolving CorrectionService from the container. Scenario 2 additionally verifies the injected object is a CheckpointService instance. When bug #986 is fixed (checkpoint_service=checkpoint_service added to the container registration), both assertions will pass and the developer must remove @tdd_expected_fail per the TDD bug workflow. Tags: @tdd_expected_fail @tdd_bug @tdd_bug_986 @mock_only Quality gates verified: - lint: pass - typecheck: pass (0 errors) - unit_tests: 462 features, 12232 scenarios, 0 failures - coverage: 98% (threshold 97%) - tag_validation: 19/19 scenarios pass - e2e_tests: 37/37 pass ISSUES CLOSED: #1030
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
"""Step definitions for TDD Bug #986 — CorrectionService checkpoint_service wiring.
|
||||
|
||||
This test captures bug #986: the DI container registers CorrectionService
|
||||
without wiring checkpoint_service, so revert-mode corrections silently skip
|
||||
checkpoint rollback. The test is tagged @tdd_expected_fail and will pass CI
|
||||
via result inversion until the bug is fixed.
|
||||
|
||||
See: https://git.cleverthis.com/cleveragents/cleveragents-core/issues/986
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from behave import given, then, when
|
||||
from behave.runner import Context
|
||||
|
||||
|
||||
@given("tccw a fresh DI container with an in-memory database")
|
||||
def step_fresh_container(context: Context) -> None:
|
||||
"""Set up a clean DI container with an in-memory SQLite database."""
|
||||
import os
|
||||
|
||||
from cleveragents.application.container import get_container, reset_container
|
||||
|
||||
# Reset to ensure a fresh container for this scenario.
|
||||
reset_container()
|
||||
|
||||
# Ensure database URL points to an in-memory database so the
|
||||
# CheckpointService factory can resolve without filesystem side-effects.
|
||||
os.environ["CLEVERAGENTS_DATABASE_URL"] = "sqlite:///:memory:"
|
||||
os.environ["CLEVERAGENTS_TEST_DATABASE_URL"] = "sqlite:///:memory:"
|
||||
|
||||
container = get_container()
|
||||
context.tccw_container = container # type: ignore[attr-defined]
|
||||
|
||||
|
||||
@when("tccw I resolve the correction_service from the container")
|
||||
def step_resolve_correction_service(context: Context) -> None:
|
||||
"""Resolve the CorrectionService singleton from the container."""
|
||||
container: Any = context.tccw_container # type: ignore[attr-defined]
|
||||
context.tccw_correction_svc = container.correction_service() # type: ignore[attr-defined]
|
||||
|
||||
|
||||
@then("tccw the correction_service should have a non-None checkpoint_service")
|
||||
def step_assert_checkpoint_service_not_none(context: Context) -> None:
|
||||
"""Assert that the resolved CorrectionService has checkpoint_service wired."""
|
||||
svc: Any = context.tccw_correction_svc # type: ignore[attr-defined]
|
||||
# Bug #986: CorrectionService._checkpoint_service is None because the
|
||||
# container does not pass checkpoint_service to the constructor.
|
||||
assert svc._checkpoint_service is not None, (
|
||||
"CorrectionService._checkpoint_service is None — the DI container "
|
||||
"does not wire checkpoint_service into CorrectionService. See bug #986."
|
||||
)
|
||||
|
||||
|
||||
@then("tccw the checkpoint_service should be a CheckpointService instance")
|
||||
def step_assert_checkpoint_service_type(context: Context) -> None:
|
||||
"""Assert that the injected checkpoint_service is a CheckpointService."""
|
||||
from cleveragents.application.services.checkpoint_service import (
|
||||
CheckpointService,
|
||||
)
|
||||
|
||||
svc: Any = context.tccw_correction_svc # type: ignore[attr-defined]
|
||||
cp_svc = svc._checkpoint_service
|
||||
assert cp_svc is not None, (
|
||||
"CorrectionService._checkpoint_service is None — cannot verify type. "
|
||||
"See bug #986."
|
||||
)
|
||||
assert isinstance(cp_svc, CheckpointService), (
|
||||
f"Expected CheckpointService instance, got {type(cp_svc).__name__}. "
|
||||
"See bug #986."
|
||||
)
|
||||
@@ -0,0 +1,30 @@
|
||||
@tdd_expected_fail @tdd_bug @tdd_bug_986 @mock_only
|
||||
Feature: TDD Bug #986 — CorrectionService missing checkpoint_service wiring in DI container
|
||||
As a developer
|
||||
I want to verify that CorrectionService receives checkpoint_service
|
||||
from the DI container
|
||||
So that revert-mode corrections can perform checkpoint rollback
|
||||
|
||||
Bug #986: The DI container registers CorrectionService with only
|
||||
event_bus but omits checkpoint_service, despite CheckpointService
|
||||
being registered in the same container. As a result, revert-mode
|
||||
corrections silently skip checkpoint rollback because the dependency
|
||||
is never injected.
|
||||
|
||||
Additionally, the CLI creates an ad-hoc CorrectionService instance
|
||||
that bypasses the container entirely, which means even if the
|
||||
container wiring is fixed, the CLI path remains broken.
|
||||
|
||||
These tests assert the expected wiring and will FAIL until the bug
|
||||
is fixed. The @tdd_expected_fail tag inverts the result so CI
|
||||
passes.
|
||||
|
||||
Scenario: DI container wires checkpoint_service into CorrectionService
|
||||
Given tccw a fresh DI container with an in-memory database
|
||||
When tccw I resolve the correction_service from the container
|
||||
Then tccw the correction_service should have a non-None checkpoint_service
|
||||
|
||||
Scenario: Container-provided CorrectionService checkpoint_service is a CheckpointService instance
|
||||
Given tccw a fresh DI container with an in-memory database
|
||||
When tccw I resolve the correction_service from the container
|
||||
Then tccw the checkpoint_service should be a CheckpointService instance
|
||||
Reference in New Issue
Block a user