-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Summary
Extract test functions from Python test files using tree-sitter. Produces DiscoveredItem(kind=TEST_FUNCTION) for each found test.
New file
src/specleft/discovery/miners/python/tests.py
import uuid
from specleft.discovery.models import SupportedLanguage, MinerResult, DiscoveredItem, ItemKind, TestFunctionMeta
from specleft.discovery.context import MinerContext
class PythonTestMiner:
miner_id = uuid.UUID("a7b21db5-0d22-41be-9902-7c725e63892e")
name = "python_test_functions"
languages = frozenset({SupportedLanguage.PYTHON})
def mine(self, ctx: MinerContext) -> MinerResult: ...Detection rules
File targeting: use ctx.file_index.files_matching("test_*.py", "*_test.py") — do NOT walk the filesystem directly.
Tree-sitter queries (via ctx.registry.parse(file_path)):
- Top-level functions where name starts with
test_ - Methods inside a class where the class name starts with
Test
Framework detection: read from ctx.frameworks[SupportedLanguage.PYTHON] — do NOT re-detect. The FrameworkDetector has already resolved this.
Typed metadata
Each item's metadata dict must conform to TestFunctionMeta:
TestFunctionMeta(
framework = ctx.frameworks.get(SupportedLanguage.PYTHON, ["unknown"])[0],
class_name = "TestLogin" | None,
decorators = ["pytest.mark.parametrize"],
has_docstring = True,
docstring = "Test that valid credentials...",
is_parametrized = True,
)Pass meta.model_dump() as the metadata dict when constructing DiscoveredItem.
name: raw function name (e.g. test_valid_credentials)
language: SupportedLanguage.PYTHON
confidence: 0.9 for test_ prefix + known framework; 0.7 otherwise
Error handling
Return MinerResult(error_kind=MinerErrorKind.PARSE_ERROR, error="...") for files that fail to parse, not exceptions. Continue processing remaining files.
Acceptance criteria
- Given a fixture with 3 test functions (1 plain, 1 parametrized, 1 inside
TestCase), miner returns exactly 3 items - All items have
language=SupportedLanguage.PYTHON - Each item's
metadatavalidates againstTestFunctionMeta(noValidationError) -
is_parametrized=Trueset correctly for the parametrized function -
class_namepopulated for theTestCasemethod,Nonefor top-level functions - Uses
ctx.file_index.files_matching()— does not walk filesystem - Uses
ctx.frameworks— does not re-detect framework - Parse errors on individual files produce
error_kind=PARSE_ERRORon the result, not exceptions - Tests in
tests/discovery/miners/test_python_tests.pyusing fixtures fromtests/fixtures/discovery/ - Update scenarios and tests in
features/feature-spec-discovery.mdto cover the functionality introduced by this issue