orchestrata_tools.test_generator.combined_generator
Reference › orchestrata_tools › test_generator › combined_generator
CombinedTestGenerator unifies the signature-based generators of this package behind one entry point. It is built from an ASTIndex and an optional TestMatcher (matcher), and creates a stub generator, an interface generator, a branch generator and a behavioral generator. It is re-exported by the package, and tests/test_orchestrata_tools_test_generator.py covers it.
generate_for_method returns a dictionary keyed by kind: always a stub, plus branch and behavioral when those generators produce output. generate_for_class takes a class: a protocol or ABC gets an interface test, a plain class gets class stubs, and each public method then contributes its branch and behavioral tests, with the per-method stub skipped when class stubs already cover it. generate_for_gaps asks the matcher for untested public methods and returns one stub file per module, named from the module path. It raises ValueError if no matcher was given.
At a glance
| Source | src/orchestrata_tools/test_generator/combined_generator.py |
| Lines of code | 90 |
| Classes | 1 |
| Functions | 0 |
| Imports (internal) | orchestrata_tools.models.ast_models, orchestrata_tools.parser.indexer, orchestrata_tools.test_analyzer.matcher, orchestrata_tools.test_generator.behavioral_tests, orchestrata_tools.test_generator.branch_tests, orchestrata_tools.test_generator.interface_tests, orchestrata_tools.test_generator.stub_generator |
| Imported by | orchestrata_tools.test_generator |
| Tests that import it | tests/test_orchestrata_tools.py, tests/test_orchestrata_tools_test_generator.py |
Class diagram
Dependency diagram
API
Classes
CombinedTestGenerator
Line 18
Generate comprehensive test suites using all available strategies.
| Method | Signature | Summary |
|---|---|---|
__init__ |
__init__(index: ASTIndex, matcher: TestMatcher | None = None) |
|
generate_for_method |
generate_for_method(method: MethodInfo) -> dict[str, str] |
Generate all applicable tests for a single method. |
generate_for_class |
generate_for_class() -> dict[str, str] |
Generate all applicable tests for a class. |
generate_for_gaps |
generate_for_gaps() -> dict[str, str] |
Generate tests for all uncovered public methods. |
Source
"""Unified test generation combining all strategies."""
from __future__ import annotations
from typing import TYPE_CHECKING
from orchestrata_tools.test_generator.behavioral_tests import BehavioralTestGenerator
from orchestrata_tools.test_generator.branch_tests import BranchTestGenerator
from orchestrata_tools.test_generator.interface_tests import InterfaceTestGenerator
from orchestrata_tools.test_generator.stub_generator import TestStubGenerator
if TYPE_CHECKING:
from orchestrata_tools.models.ast_models import ClassInfo, MethodInfo
from orchestrata_tools.parser.indexer import ASTIndex
from orchestrata_tools.test_analyzer.matcher import TestMatcher
class CombinedTestGenerator:
"""Generate comprehensive test suites using all available strategies."""
def __init__(self, index: ASTIndex, matcher: TestMatcher | None = None):
self.index = index
self.matcher = matcher
self.stub_gen = TestStubGenerator()
self.iface_gen = InterfaceTestGenerator()
self.branch_gen = BranchTestGenerator()
self.behavior_gen = BehavioralTestGenerator()
def generate_for_method(self, method: MethodInfo) -> dict[str, str]:
"""Generate all applicable tests for a single method."""
result = {}
result["stub"] = self.stub_gen.generate_stub(method)
branch = self.branch_gen.generate_for_method(method)
if branch:
result["branch"] = branch
behavioral = self.behavior_gen.generate_from_docstring(method)
if behavioral:
result["behavioral"] = behavioral
return result
def generate_for_class(self, cls: ClassInfo) -> dict[str, str]:
"""Generate all applicable tests for a class."""
result = {}
if cls.is_protocol:
result["interface"] = self.iface_gen.generate_for_protocol(cls)
elif cls.is_abstract:
result["interface"] = self.iface_gen.generate_for_abc(cls)
else:
result["stub"] = self.stub_gen.generate_class_stubs(cls)
already_stubbed = "stub" in result
for method in cls.methods:
if method.name.startswith("_"):
continue
method_tests = self.generate_for_method(method)
for key, val in method_tests.items():
if key == "stub" and already_stubbed:
# generate_class_stubs() above already emitted a stub
# for every public method of a plain class; re-merging
# the per-method stub here duplicated every generated
# test. Protocol/ABC classes never pre-seed "stub", so
# they still get one from generate_for_method here.
continue
if key not in result:
result[key] = ""
result[key] += val + "\n"
return result
def generate_for_gaps(self) -> dict[str, str]:
"""Generate tests for all uncovered public methods."""
if self.matcher is None:
raise ValueError("matcher required for gap generation")
untested = self.matcher.find_untested_methods(self.index)
files: dict[str, list[str]] = {}
for method in untested:
stub = self.stub_gen.generate_stub(method)
module_path = method.module_path.replace(".", "/")
filename = f"test_{module_path}.py"
if filename not in files:
files[filename] = [
'"""Generated test stubs for uncovered methods."""',
"",
"import pytest",
"",
]
files[filename].append(stub)
return {k: "\n".join(v) for k, v in files.items()}