Skip to content

Commit

Permalink
refactor: Break up TapTestClassFactory._annotate_test_class into si…
Browse files Browse the repository at this point in the history
…mpler methods
  • Loading branch information
edgarrmondragon committed Nov 18, 2023
1 parent 5b84912 commit f74dcea
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 77 deletions.
168 changes: 98 additions & 70 deletions singer_sdk/testing/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,22 @@
from .config import SuiteConfig
from .runners import TapTestRunner, TargetTestRunner
from .suites import (
TestSuite,
tap_stream_attribute_tests,
tap_stream_tests,
tap_tests,
target_tests,
)

if t.TYPE_CHECKING:
from singer_sdk import Tap, Target
from singer_sdk import Stream, Tap, Target

from .templates import (
AttributeTestTemplate,
StreamTestTemplate,
TapTestTemplate,
TargetTestTemplate,
)


class BaseTestClass:
Expand Down Expand Up @@ -144,11 +152,93 @@ def runner(self) -> TapTestRunner | TargetTestRunner:

return TapTestClass

# TODO: Refactor this. It's too long and nested.
def _annotate_test_class( # noqa: C901
def _annotate_tap_tests(
self,
empty_test_class: type[BaseTestClass],
suite: TestSuite[TapTestTemplate],
) -> None:
for test_class in suite.tests:
test = test_class()
test_name = f"test_{suite.kind}_{test.name}"
setattr(empty_test_class, test_name, test.run)

def _annotate_stream_tests(
self,
empty_test_class: type[BaseTestClass],
test_suites: list,
suite: TestSuite[StreamTestTemplate],
streams: list[Stream],
) -> None:
params = [
{
"stream": stream,
}
for stream in streams
]
param_ids = [stream.name for stream in streams]

for test_class in suite.tests:
test = test_class()
test_name = f"test_{suite.kind}_{test.name}"
setattr(
test_class,
test_name,
test.run,
)
empty_test_class.params[test_name] = params
empty_test_class.param_ids[test_name] = param_ids

def _annotate_attribute_tests(
self,
empty_test_class: type[BaseTestClass],
suite: TestSuite[AttributeTestTemplate],
streams: list[Stream],
) -> None:
for test_class in suite.tests:
test = test_class()
test_name = f"test_{suite.kind}_{test.name}"
test_params = []
test_ids: list[str] = []
for stream in streams:
final_schema = stream.stream_maps[-1].transformed_schema["properties"]
test_params.extend(
[
{
"stream": stream,
"attribute_name": prop_name,
}
for prop_name, prop_schema in final_schema.items()
if test_class.evaluate(
stream=stream,
property_name=prop_name,
property_schema=prop_schema,
)
],
)
test_ids.extend(
[
f"{stream.name}.{prop_name}"
for prop_name, prop_schema in final_schema.items()
if test_class.evaluate(
stream=stream,
property_name=prop_name,
property_schema=prop_schema,
)
],
)

if test_params:
setattr(
empty_test_class,
test_name,
test.run,
)
empty_test_class.params[test_name] = test_params
empty_test_class.param_ids[test_name] = test_ids

def _annotate_test_class(
self,
empty_test_class: type[BaseTestClass],
test_suites: list[TestSuite],
test_runner: TapTestRunner,
) -> type[BaseTestClass]:
"""Annotate test class with test methods.
Expand All @@ -163,78 +253,16 @@ def _annotate_test_class( # noqa: C901
"""
for suite in test_suites:
if suite.kind == "tap":
for test_class in suite.tests:
test = test_class()
test_name = f"test_{suite.kind}_{test.name}"
setattr(empty_test_class, test_name, test.run)
self._annotate_tap_tests(empty_test_class, suite)

if suite.kind in {"tap_stream", "tap_stream_attribute"}:
streams = list(test_runner.new_tap().streams.values())

if suite.kind == "tap_stream":
params = [
{
"stream": stream,
}
for stream in streams
]
param_ids = [stream.name for stream in streams]

for test_class in suite.tests:
test = test_class()
test_name = f"test_{suite.kind}_{test.name}"
setattr(
empty_test_class,
test_name,
test.run,
)
empty_test_class.params[test_name] = params
empty_test_class.param_ids[test_name] = param_ids
self._annotate_stream_tests(empty_test_class, suite, streams)

if suite.kind == "tap_stream_attribute":
for test_class in suite.tests:
test = test_class()
test_name = f"test_{suite.kind}_{test.name}"
test_params = []
test_ids: list[str] = []
for stream in streams:
final_schema = stream.stream_maps[-1].transformed_schema[
"properties"
]
test_params.extend(
[
{
"stream": stream,
"attribute_name": prop_name,
}
for prop_name, prop_schema in final_schema.items()
if test_class.evaluate(
stream=stream,
property_name=prop_name,
property_schema=prop_schema,
)
],
)
test_ids.extend(
[
f"{stream.name}.{prop_name}"
for prop_name, prop_schema in final_schema.items()
if test_class.evaluate(
stream=stream,
property_name=prop_name,
property_schema=prop_schema,
)
],
)

if test_params:
setattr(
empty_test_class,
test_name,
test.run,
)
empty_test_class.params[test_name] = test_params
empty_test_class.param_ids[test_name] = test_ids
self._annotate_attribute_tests(empty_test_class, suite, streams)

return empty_test_class

Expand Down Expand Up @@ -336,7 +364,7 @@ def runner(self) -> TargetTestRunner:
def _annotate_test_class(
self,
empty_test_class: type[BaseTestClass],
test_suites: list,
test_suites: list[TestSuite[TargetTestTemplate]],
) -> type[BaseTestClass]:
"""Annotate test class with test methods.
Expand Down
24 changes: 17 additions & 7 deletions singer_sdk/testing/suites.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,31 @@
TargetSchemaUpdates,
TargetSpecialCharsInAttributes,
)
from .templates import (
TestTemplate,
)

if t.TYPE_CHECKING:
from .templates import TapTestTemplate, TargetTestTemplate, TestTemplate
from .templates import (
AttributeTestTemplate,
StreamTestTemplate,
TapTestTemplate,
TargetTestTemplate,
)

T = t.TypeVar("T", bound=TestTemplate)


@dataclass
class TestSuite:
class TestSuite(t.Generic[T]):
"""Test Suite container class."""

kind: str
tests: list[type[TestTemplate] | type[TapTestTemplate] | type[TargetTestTemplate]]
tests: list[type[T]]


# Tap Test Suites
tap_tests = TestSuite(
tap_tests: TestSuite[TapTestTemplate] = TestSuite(
kind="tap",
tests=[
TapCLIPrintsTest,
Expand All @@ -65,7 +75,7 @@ class TestSuite:
TapValidFinalStateTest,
],
)
tap_stream_tests = TestSuite(
tap_stream_tests: TestSuite[StreamTestTemplate] = TestSuite(
kind="tap_stream",
tests=[
StreamCatalogSchemaMatchesRecordTest,
Expand All @@ -75,7 +85,7 @@ class TestSuite:
StreamPrimaryKeysTest,
],
)
tap_stream_attribute_tests = TestSuite(
tap_stream_attribute_tests: TestSuite[AttributeTestTemplate] = TestSuite(
kind="tap_stream_attribute",
tests=[
AttributeIsBooleanTest,
Expand All @@ -89,7 +99,7 @@ class TestSuite:


# Target Test Suites
target_tests = TestSuite(
target_tests: TestSuite[TargetTestTemplate] = TestSuite(
kind="target",
tests=[
TargetArrayData,
Expand Down

0 comments on commit f74dcea

Please sign in to comment.