Skip to content

Commit 1468a48

Browse files
committed
clean up naming, remove unused
1 parent d0aba9f commit 1468a48

File tree

6 files changed

+87
-80
lines changed

6 files changed

+87
-80
lines changed

airbyte_cdk/test/declarative/models/scenario.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717

1818

1919
class ConnectorTestScenario(BaseModel):
20-
"""Acceptance test instance, as a Pydantic model.
20+
"""Acceptance test scenario, as a Pydantic model.
2121
22-
This class represents an acceptance test instance, which is a single test case
22+
This class represents an acceptance test scenario, which is a single test case
2323
that can be run against a connector. It is used to deserialize and validate the
2424
acceptance test configuration file.
2525
"""

airbyte_cdk/test/declarative/test_suites/connector_base.py

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,12 @@
2929
MANIFEST_YAML = "manifest.yaml"
3030

3131

32-
class JavaClass(str):
33-
"""A string that represents a Java class."""
34-
35-
36-
class DockerImage(str):
37-
"""A string that represents a Docker image."""
38-
39-
40-
class RunnableConnector(abc.ABC):
41-
"""A connector that can be run in a test scenario."""
42-
43-
@abc.abstractmethod
44-
def launch(cls, args: list[str] | None) -> None: ...
45-
46-
4732
def generate_tests(metafunc: pytest.Metafunc) -> None:
4833
"""
4934
A helper for pytest_generate_tests hook.
5035
5136
If a test method (in a class subclassed from our base class)
52-
declares an argument 'instance', this function retrieves the
37+
declares an argument 'scenario', this function retrieves the
5338
'scenarios' attribute from the test class and parametrizes that
5439
test with the values from 'scenarios'.
5540
@@ -69,8 +54,8 @@ class TestMyConnector(ConnectorTestSuiteBase):
6954
7055
```
7156
"""
72-
# Check if the test function requires an 'instance' argument
73-
if "instance" in metafunc.fixturenames:
57+
# Check if the test function requires an 'scenario' argument
58+
if "scenario" in metafunc.fixturenames:
7459
# Retrieve the test class
7560
test_class = metafunc.cls
7661
if test_class is None:
@@ -85,14 +70,14 @@ class TestMyConnector(ConnectorTestSuiteBase):
8570

8671
scenarios = test_class.get_scenarios()
8772
ids = [str(scenario) for scenario in scenarios]
88-
metafunc.parametrize("instance", scenarios, ids=ids)
73+
metafunc.parametrize("scenario", scenarios, ids=ids)
8974

9075

9176
class ConnectorTestSuiteBase(abc.ABC):
9277
"""Base class for connector test suites."""
9378

9479
connector: type[IConnector] | Callable[[], IConnector] | None = None
95-
"""The connector class or a factory function that returns an instance of IConnector."""
80+
"""The connector class or a factory function that returns an scenario of IConnector."""
9681

9782
@classmethod
9883
def get_test_class_dir(cls) -> Path:
@@ -120,31 +105,17 @@ def create_connector(
120105
"override `cls.create_connector()` to define a custom initialization process."
121106
)
122107

123-
def run_test_scenario(
124-
self,
125-
verb: Literal["read", "check", "discover"],
126-
test_scenario: ConnectorTestScenario,
127-
*,
128-
catalog: dict[str, Any] | None = None,
129-
) -> entrypoint_wrapper.EntrypointOutput:
130-
"""Run a test job from provided CLI args and return the result."""
131-
return run_test_job(
132-
self.create_connector(test_scenario),
133-
verb,
134-
test_instance=test_scenario,
135-
catalog=catalog,
136-
)
137-
138108
# Test Definitions
139109

140110
def test_check(
141111
self,
142-
instance: ConnectorTestScenario,
112+
scenario: ConnectorTestScenario,
143113
) -> None:
144114
"""Run `connection` acceptance tests."""
145-
result = self.run_test_scenario(
115+
result: entrypoint_wrapper.EntrypointOutput = run_test_job(
116+
self.create_connector(scenario),
146117
"check",
147-
test_scenario=instance,
118+
test_scenario=scenario,
148119
)
149120
conn_status_messages: list[AirbyteMessage] = [
150121
msg for msg in result._messages if msg.type == Type.CONNECTION_STATUS

airbyte_cdk/test/declarative/test_suites/declarative_sources.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,25 @@
1818

1919

2020
def md5_checksum(file_path: Path) -> str:
21+
"""Helper function to calculate the MD5 checksum of a file.
22+
23+
This is used to calculate the checksum of the `components.py` file, if it exists.
24+
"""
2125
with open(file_path, "rb") as file:
2226
return md5(file.read()).hexdigest()
2327

2428

2529
class DeclarativeSourceTestSuite(SourceTestSuiteBase):
30+
"""Declarative source test suite.
31+
32+
This inherits from the Python-based source test suite and implements the
33+
`create_connector` method to create a declarative source object instead of
34+
requiring a custom Python source object.
35+
36+
The class also automatically locates the `manifest.yaml` file and the
37+
`components.py` file (if it exists) in the connector's directory.
38+
"""
39+
2640
@classproperty
2741
def manifest_yaml_path(cls) -> Path:
2842
"""Get the path to the manifest.yaml file."""
@@ -37,7 +51,10 @@ def manifest_yaml_path(cls) -> Path:
3751

3852
@classproperty
3953
def components_py_path(cls) -> Path | None:
40-
"""Get the path to the components.py file."""
54+
"""Get the path to the `components.py` file, if one exists.
55+
56+
If not `components.py` file exists, return None.
57+
"""
4158
result = cls.get_connector_root_dir() / "components.py"
4259
if result.exists():
4360
return result
@@ -49,11 +66,14 @@ def create_connector(
4966
cls,
5067
scenario: ConnectorTestScenario,
5168
) -> IConnector:
52-
"""Create a connector instance for the test suite."""
69+
"""Create a connector scenario for the test suite.
70+
71+
This overrides `create_connector` from the create a declarative source object
72+
instead of requiring a custom python source object.
73+
74+
Subclasses should not need to override this method.
75+
"""
5376
config: dict[str, Any] = scenario.get_config_dict()
54-
# catalog = scenario.get_catalog()
55-
# state = scenario.get_state()
56-
# source_config = scenario.get_source_config()
5777

5878
manifest_dict = yaml.safe_load(cls.manifest_yaml_path.read_text())
5979
if cls.components_py_path and cls.components_py_path.exists():

airbyte_cdk/test/declarative/test_suites/destination_base.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@ class DestinationTestSuiteBase(ConnectorTestSuiteBase):
99
1010
This class provides a base set of functionality for testing destination connectors, and it
1111
inherits all generic connector tests from the `ConnectorTestSuiteBase` class.
12+
13+
TODO: As of now, this class does not add any additional functionality or tests specific to
14+
destination connectors. However, it serves as a placeholder for future enhancements and
15+
customizations that may be needed for destination connectors.
1216
"""

airbyte_cdk/test/declarative/test_suites/source_base.py

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,18 @@ class SourceTestSuiteBase(ConnectorTestSuiteBase):
3131

3232
def test_check(
3333
self,
34-
instance: ConnectorTestScenario,
34+
scenario: ConnectorTestScenario,
3535
) -> None:
36-
"""Run `connection` acceptance tests."""
36+
"""Run standard `check` tests on the connector.
37+
38+
Assert that the connector returns a single CONNECTION_STATUS message.
39+
This test is designed to validate the connector's ability to establish a connection
40+
and return its status with the expected message type.
41+
"""
3742
result: entrypoint_wrapper.EntrypointOutput = run_test_job(
38-
self.create_connector(instance),
43+
self.create_connector(scenario),
3944
"check",
40-
test_instance=instance,
45+
test_scenario=scenario,
4146
)
4247
conn_status_messages: list[AirbyteMessage] = [
4348
msg for msg in result._messages if msg.type == Type.CONNECTION_STATUS
@@ -50,15 +55,21 @@ def test_check(
5055

5156
def test_basic_read(
5257
self,
53-
instance: ConnectorTestScenario,
58+
scenario: ConnectorTestScenario,
5459
) -> None:
55-
"""Run acceptance tests."""
60+
"""Run standard `read` test on the connector.
61+
62+
This test is designed to validate the connector's ability to read data
63+
from the source and return records. It first runs a `discover` job to
64+
obtain the catalog of streams, and then it runs a `read` job to fetch
65+
records from those streams.
66+
"""
5667
discover_result = run_test_job(
57-
self.create_connector(instance),
68+
self.create_connector(scenario),
5869
"discover",
59-
test_instance=instance,
70+
test_scenario=scenario,
6071
)
61-
if instance.expect_exception:
72+
if scenario.expect_exception:
6273
assert discover_result.errors, "Expected exception but got none."
6374
return
6475

@@ -73,20 +84,20 @@ def test_basic_read(
7384
]
7485
)
7586
result = run_test_job(
76-
self.create_connector(instance),
87+
self.create_connector(scenario),
7788
"read",
78-
test_instance=instance,
89+
test_scenario=scenario,
7990
catalog=configured_catalog,
8091
)
8192

8293
if not result.records:
8394
raise AssertionError("Expected records but got none.") # noqa: TRY003
8495

85-
def test_fail_with_bad_catalog(
96+
def test_fail_read_with_bad_catalog(
8697
self,
87-
instance: ConnectorTestScenario,
98+
scenario: ConnectorTestScenario,
8899
) -> None:
89-
"""Test that a bad catalog fails."""
100+
"""Standard test for `read` when passed a bad catalog file."""
90101
invalid_configured_catalog = ConfiguredAirbyteCatalog(
91102
streams=[
92103
# Create ConfiguredAirbyteStream which is deliberately invalid
@@ -107,22 +118,23 @@ def test_fail_with_bad_catalog(
107118
]
108119
)
109120
# Set expected status to "failed" to ensure the test fails if the connector.
110-
instance.status = "failed"
111-
result = self.run_test_scenario(
121+
scenario.status = "failed"
122+
result: entrypoint_wrapper.EntrypointOutput = run_test_job(
123+
self.create_connector(scenario),
112124
"read",
113-
test_scenario=instance,
125+
test_scenario=scenario,
114126
catalog=asdict(invalid_configured_catalog),
115127
)
116128
assert result.errors, "Expected errors but got none."
117129
assert result.trace_messages, "Expected trace messages but got none."
118130

119131
def test_discover(
120132
self,
121-
instance: ConnectorTestScenario,
133+
scenario: ConnectorTestScenario,
122134
) -> None:
123-
"""Run acceptance tests."""
135+
"""Standard test for `discover`."""
124136
run_test_job(
125-
self.create_connector(instance),
126-
"check",
127-
test_instance=instance,
137+
self.create_connector(scenario),
138+
"discover",
139+
test_scenario=scenario,
128140
)

airbyte_cdk/test/declarative/utils/job_runner.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ def launch(self, args: list[str] | None) -> None:
2929
def run_test_job(
3030
connector: IConnector | type[IConnector] | Callable[[], IConnector],
3131
verb: Literal["read", "check", "discover"],
32-
test_instance: ConnectorTestScenario,
32+
test_scenario: ConnectorTestScenario,
3333
*,
3434
catalog: ConfiguredAirbyteCatalog | dict[str, Any] | None = None,
3535
) -> entrypoint_wrapper.EntrypointOutput:
36-
"""Run a test job from provided CLI args and return the result."""
36+
"""Run a test scenario from provided CLI args and return the result."""
3737
if not connector:
3838
raise ValueError("Connector is required")
3939

@@ -59,14 +59,14 @@ def run_test_job(
5959
)
6060

6161
args: list[str] = [verb]
62-
if test_instance.config_path:
63-
args += ["--config", str(test_instance.config_path)]
64-
elif test_instance.config_dict:
62+
if test_scenario.config_path:
63+
args += ["--config", str(test_scenario.config_path)]
64+
elif test_scenario.config_dict:
6565
config_path = (
6666
Path(tempfile.gettempdir()) / "airbyte-test" / f"temp_config_{uuid.uuid4().hex}.json"
6767
)
6868
config_path.parent.mkdir(parents=True, exist_ok=True)
69-
config_path.write_text(orjson.dumps(test_instance.config_dict).decode())
69+
config_path.write_text(orjson.dumps(test_scenario.config_dict).decode())
7070
args += ["--config", str(config_path)]
7171

7272
catalog_path: Path | None = None
@@ -81,21 +81,21 @@ def run_test_job(
8181
)
8282
catalog_path.parent.mkdir(parents=True, exist_ok=True)
8383
catalog_path.write_text(orjson.dumps(catalog).decode())
84-
elif test_instance.configured_catalog_path:
85-
catalog_path = Path(test_instance.configured_catalog_path)
84+
elif test_scenario.configured_catalog_path:
85+
catalog_path = Path(test_scenario.configured_catalog_path)
8686

8787
if catalog_path:
8888
args += ["--catalog", str(catalog_path)]
8989

9090
# This is a bit of a hack because the source needs the catalog early.
91-
# Because it *also* can fail, we have ot redundantly wrap it in a try/except block.
91+
# Because it *also* can fail, we have to redundantly wrap it in a try/except block.
9292

9393
result: entrypoint_wrapper.EntrypointOutput = entrypoint_wrapper._run_command( # noqa: SLF001 # Non-public API
9494
source=connector_obj, # type: ignore [arg-type]
9595
args=args,
96-
expecting_exception=test_instance.expect_exception,
96+
expecting_exception=test_scenario.expect_exception,
9797
)
98-
if result.errors and not test_instance.expect_exception:
98+
if result.errors and not test_scenario.expect_exception:
9999
raise AssertionError(
100100
"\n\n".join(
101101
[str(err.trace.error).replace("\\n", "\n") for err in result.errors if err.trace],
@@ -114,7 +114,7 @@ def run_test_job(
114114
f"{len(result.connection_status_messages)}:\n"
115115
+ "\n".join([str(msg) for msg in result.connection_status_messages])
116116
)
117-
if test_instance.expect_exception:
117+
if test_scenario.expect_exception:
118118
conn_status = result.connection_status_messages[0].connectionStatus
119119
assert conn_status, (
120120
"Expected CONNECTION_STATUS message to be present. Got: \n"
@@ -128,7 +128,7 @@ def run_test_job(
128128
return result
129129

130130
# For all other verbs, we assert check that an exception is raised (or not).
131-
if test_instance.expect_exception:
131+
if test_scenario.expect_exception:
132132
if not result.errors:
133133
raise AssertionError("Expected exception but got none.")
134134

0 commit comments

Comments
 (0)