phlo-testing 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/PKG-INFO +2 -1
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/pyproject.toml +27 -21
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing/__init__.py +1 -1
- phlo_testing-0.3.0/src/phlo_testing/conftest_template.py +95 -0
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing/execution.py +103 -71
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing/fixtures.py +21 -0
- phlo_testing-0.3.0/src/phlo_testing/hooks.py +284 -0
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing/local_mode.py +111 -63
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing/mock_dlt.py +99 -48
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing/mock_iceberg.py +146 -72
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing/mock_trino.py +161 -118
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing/non_versioned_profile_harness.py +110 -8
- phlo_testing-0.3.0/src/phlo_testing/placeholders.py +523 -0
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing/profile_harness.py +656 -21
- phlo_testing-0.3.0/src/phlo_testing/utils.py +68 -0
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing.egg-info/PKG-INFO +2 -1
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing.egg-info/requires.txt +1 -0
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/tests/test_profile_harness.py +3 -1
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/tests/test_testing_infrastructure.py +38 -0
- phlo_testing-0.2.0/src/phlo_testing/conftest_template.py +0 -65
- phlo_testing-0.2.0/src/phlo_testing/hooks.py +0 -135
- phlo_testing-0.2.0/src/phlo_testing/placeholders.py +0 -846
- phlo_testing-0.2.0/src/phlo_testing/utils.py +0 -20
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/README.md +0 -0
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/setup.cfg +0 -0
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing.egg-info/SOURCES.txt +0 -0
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing.egg-info/dependency_links.txt +0 -0
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/src/phlo_testing.egg-info/top_level.txt +0 -0
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/tests/test_integration_testing.py +0 -0
- {phlo_testing-0.2.0 → phlo_testing-0.3.0}/tests/test_non_versioned_profile_harness.py +0 -0
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: phlo-testing
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Testing utilities for Phlo
|
|
5
5
|
Author-email: Phlo Team <team@phlo.dev>
|
|
6
6
|
License: MIT
|
|
7
7
|
Requires-Python: >=3.11
|
|
8
8
|
Description-Content-Type: text/plain
|
|
9
9
|
Requires-Dist: phlo>=0.1.0
|
|
10
|
+
Requires-Dist: phlo-postgres>=0.1.0
|
|
10
11
|
Requires-Dist: duckdb>=0.9.0
|
|
11
12
|
Requires-Dist: pyarrow>=21.0.0
|
|
12
13
|
Requires-Dist: pyiceberg>=0.10.0
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["setuptools>=45", "wheel"]
|
|
3
2
|
build-backend = "setuptools.build_meta"
|
|
3
|
+
requires = [
|
|
4
|
+
"setuptools>=45",
|
|
5
|
+
"wheel",
|
|
6
|
+
]
|
|
4
7
|
|
|
5
8
|
[project]
|
|
6
|
-
name = "phlo-testing"
|
|
7
|
-
version = "0.2.0"
|
|
8
|
-
description = "Testing utilities for Phlo"
|
|
9
|
-
readme = {text = "Testing utilities for Phlo.", content-type = "text/plain"}
|
|
10
|
-
requires-python = ">=3.11"
|
|
11
|
-
authors = [
|
|
12
|
-
{name = "Phlo Team", email = "team@phlo.dev"},
|
|
13
|
-
]
|
|
14
|
-
license = {text = "MIT"}
|
|
15
9
|
dependencies = [
|
|
16
10
|
"phlo>=0.1.0",
|
|
11
|
+
"phlo-postgres>=0.1.0",
|
|
17
12
|
"duckdb>=0.9.0",
|
|
18
13
|
"pyarrow>=21.0.0",
|
|
19
14
|
"pyiceberg>=0.10.0",
|
|
@@ -21,25 +16,36 @@ dependencies = [
|
|
|
21
16
|
"pandera>=0.26.1",
|
|
22
17
|
"dlt>=1.18.2",
|
|
23
18
|
]
|
|
19
|
+
description = "Testing utilities for Phlo"
|
|
20
|
+
name = "phlo-testing"
|
|
21
|
+
requires-python = ">=3.11"
|
|
22
|
+
version = "0.3.0"
|
|
23
|
+
|
|
24
|
+
[[project.authors]]
|
|
25
|
+
email = "team@phlo.dev"
|
|
26
|
+
name = "Phlo Team"
|
|
27
|
+
|
|
28
|
+
[project.license]
|
|
29
|
+
text = "MIT"
|
|
24
30
|
|
|
25
31
|
[project.optional-dependencies]
|
|
26
32
|
dev = [
|
|
27
33
|
"pytest>=7.0",
|
|
28
34
|
"ruff>=0.1.0",
|
|
29
35
|
]
|
|
30
|
-
dlt = [
|
|
31
|
-
|
|
32
|
-
]
|
|
33
|
-
trino = [
|
|
34
|
-
"phlo-trino>=0.1.0",
|
|
35
|
-
]
|
|
36
|
-
|
|
37
|
-
[tool.setuptools]
|
|
38
|
-
package-dir = {"" = "src"}
|
|
36
|
+
dlt = ["phlo-dlt>=0.1.0"]
|
|
37
|
+
trino = ["phlo-trino>=0.1.0"]
|
|
39
38
|
|
|
40
|
-
[
|
|
41
|
-
|
|
39
|
+
[project.readme]
|
|
40
|
+
content-type = "text/plain"
|
|
41
|
+
text = "Testing utilities for Phlo."
|
|
42
42
|
|
|
43
43
|
[tool.ruff]
|
|
44
44
|
line-length = 100
|
|
45
45
|
target-version = "py311"
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.package-dir]
|
|
48
|
+
"" = "src"
|
|
49
|
+
|
|
50
|
+
[tool.setuptools.packages.find]
|
|
51
|
+
where = ["src"]
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"""Conftest template for user projects.
|
|
2
|
+
|
|
3
|
+
This module provides a ready-to-use conftest.py template that users can copy
|
|
4
|
+
to their tests/ directory to get all phlo_testing fixtures automatically.
|
|
5
|
+
|
|
6
|
+
The template includes:
|
|
7
|
+
- All standard phlo_testing fixtures (mock resources, test data, etc.)
|
|
8
|
+
- Environment reset fixture for test isolation
|
|
9
|
+
- Project root fixture for path resolution
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
>>> from phlo_testing.conftest_template import CONFTEST_TEMPLATE, get_conftest_template
|
|
13
|
+
>>> from pathlib import Path
|
|
14
|
+
>>> # Write template to tests/conftest.py
|
|
15
|
+
>>> Path("tests/conftest.py").write_text(get_conftest_template())
|
|
16
|
+
>>> # Or use the constant directly
|
|
17
|
+
>>> print(CONFTEST_TEMPLATE)
|
|
18
|
+
|
|
19
|
+
The fixtures included in the template:
|
|
20
|
+
- mock_iceberg_catalog: Fresh MockIcebergCatalog for each test
|
|
21
|
+
- mock_trino: Fresh MockTrinoResource for each test
|
|
22
|
+
- mock_asset_context: MockAssetContext with logging capture
|
|
23
|
+
- sample_partition_date: Standard test partition date
|
|
24
|
+
- sample_dlt_data: Sample DLT source data
|
|
25
|
+
- temp_staging_dir: Temporary directory for test files
|
|
26
|
+
- And more...
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
CONFTEST_TEMPLATE = '''"""
|
|
30
|
+
Pytest configuration and shared fixtures.
|
|
31
|
+
|
|
32
|
+
Place this file in tests/ directory to make fixtures available to all tests.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
import pytest
|
|
36
|
+
from pathlib import Path
|
|
37
|
+
|
|
38
|
+
# Import fixtures from phlo_testing
|
|
39
|
+
from phlo_testing.fixtures import (
|
|
40
|
+
mock_iceberg_catalog,
|
|
41
|
+
mock_trino,
|
|
42
|
+
mock_asset_context,
|
|
43
|
+
mock_resources,
|
|
44
|
+
sample_partition_date,
|
|
45
|
+
sample_partition_range,
|
|
46
|
+
sample_dlt_data,
|
|
47
|
+
sample_dataframe,
|
|
48
|
+
mock_dlt_source_fixture,
|
|
49
|
+
temp_staging_dir,
|
|
50
|
+
test_data_dir,
|
|
51
|
+
setup_test_catalog,
|
|
52
|
+
setup_test_trino,
|
|
53
|
+
load_json_fixture,
|
|
54
|
+
load_csv_fixture,
|
|
55
|
+
test_config,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@pytest.fixture(autouse=True)
|
|
60
|
+
def reset_test_env(monkeypatch):
|
|
61
|
+
"""Reset environment variables before each test.
|
|
62
|
+
|
|
63
|
+
Ensures test isolation by setting PHLO_ENV and PHLO_LOG_LEVEL
|
|
64
|
+
before each test execution.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
monkeypatch: pytest monkeypatch fixture.
|
|
68
|
+
"""
|
|
69
|
+
monkeypatch.setenv("PHLO_ENV", "test")
|
|
70
|
+
monkeypatch.setenv("PHLO_LOG_LEVEL", "DEBUG")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@pytest.fixture
|
|
74
|
+
def project_root() -> Path:
|
|
75
|
+
"""Return path to project root.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Path to the project root directory (where pyproject.toml is located).
|
|
79
|
+
"""
|
|
80
|
+
return Path(__file__).parent.parent
|
|
81
|
+
'''
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def get_conftest_template() -> str:
|
|
85
|
+
"""Get the conftest.py template content.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
String content for conftest.py that can be written to a file.
|
|
89
|
+
|
|
90
|
+
Example:
|
|
91
|
+
>>> template = get_conftest_template()
|
|
92
|
+
>>> Path("tests/conftest.py").write_text(template)
|
|
93
|
+
|
|
94
|
+
"""
|
|
95
|
+
return CONFTEST_TEMPLATE
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Helper to execute assets with mocked dependencies and capture results.
|
|
1
|
+
"""Helper to execute assets with mocked dependencies and capture results.
|
|
3
2
|
|
|
4
3
|
Provides `test_asset_execution()` for running `@phlo_ingestion` assets in tests
|
|
5
4
|
with mocked Iceberg, Trino, and DLT dependencies.
|
|
@@ -12,6 +11,7 @@ Example:
|
|
|
12
11
|
... )
|
|
13
12
|
>>> assert result.success
|
|
14
13
|
>>> assert len(result.data) == 1
|
|
14
|
+
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
from __future__ import annotations
|
|
@@ -30,17 +30,20 @@ from phlo_testing.mock_trino import MockTrinoResource
|
|
|
30
30
|
|
|
31
31
|
@dataclass
|
|
32
32
|
class AssetTestResult:
|
|
33
|
-
"""
|
|
34
|
-
|
|
33
|
+
"""Result of executing an asset in test mode.
|
|
34
|
+
|
|
35
|
+
Encapsulates all information about an asset test execution including
|
|
36
|
+
success status, resulting data, metadata, logs, timing, and errors.
|
|
35
37
|
|
|
36
38
|
Attributes:
|
|
37
|
-
success: Whether asset execution succeeded
|
|
38
|
-
data: Resulting DataFrame (if available)
|
|
39
|
-
metadata: Metadata from MaterializeResult
|
|
40
|
-
logs: Captured log messages
|
|
41
|
-
duration: Execution time in seconds
|
|
42
|
-
error: Exception if execution failed
|
|
43
|
-
raw_result: Raw Dagster ExecuteInProcessResult (advanced use)
|
|
39
|
+
success: Whether asset execution succeeded.
|
|
40
|
+
data: Resulting DataFrame (if available).
|
|
41
|
+
metadata: Metadata from MaterializeResult.
|
|
42
|
+
logs: Captured log messages.
|
|
43
|
+
duration: Execution time in seconds.
|
|
44
|
+
error: Exception if execution failed.
|
|
45
|
+
raw_result: Raw Dagster ExecuteInProcessResult (advanced use).
|
|
46
|
+
|
|
44
47
|
"""
|
|
45
48
|
|
|
46
49
|
success: bool
|
|
@@ -53,10 +56,21 @@ class AssetTestResult:
|
|
|
53
56
|
|
|
54
57
|
|
|
55
58
|
class MockAssetContext:
|
|
56
|
-
"""
|
|
57
|
-
|
|
59
|
+
"""Mock Dagster context for asset execution.
|
|
60
|
+
|
|
61
|
+
Provides mocked resources (Iceberg, Trino, DLT) and logging capabilities
|
|
62
|
+
for testing assets without requiring a full Dagster environment.
|
|
63
|
+
|
|
64
|
+
Attributes:
|
|
65
|
+
partition_key: Partition identifier (e.g., "2024-01-01").
|
|
66
|
+
iceberg: MockIcebergCatalog instance for table operations.
|
|
67
|
+
trino: MockTrinoResource instance for SQL execution.
|
|
68
|
+
|
|
69
|
+
Example:
|
|
70
|
+
>>> context = MockAssetContext(partition_key="2024-01-01")
|
|
71
|
+
>>> context.log("Processing partition")
|
|
72
|
+
>>> table_store = context.get_resource("table_store")
|
|
58
73
|
|
|
59
|
-
Provides mocked resources (Iceberg, Trino, DLT) and logging.
|
|
60
74
|
"""
|
|
61
75
|
|
|
62
76
|
def __init__(
|
|
@@ -65,13 +79,13 @@ class MockAssetContext:
|
|
|
65
79
|
mock_iceberg: Optional[MockIcebergCatalog] = None,
|
|
66
80
|
mock_trino: Optional[MockTrinoResource] = None,
|
|
67
81
|
) -> None:
|
|
68
|
-
"""
|
|
69
|
-
Initialize mock context.
|
|
82
|
+
"""Initialize mock context.
|
|
70
83
|
|
|
71
84
|
Args:
|
|
72
|
-
partition_key: Partition identifier (e.g., "2024-01-01")
|
|
73
|
-
mock_iceberg: MockIcebergCatalog instance (creates new if None)
|
|
74
|
-
mock_trino: MockTrinoResource instance (creates new if None)
|
|
85
|
+
partition_key: Partition identifier (e.g., "2024-01-01").
|
|
86
|
+
mock_iceberg: MockIcebergCatalog instance (creates new if None).
|
|
87
|
+
mock_trino: MockTrinoResource instance (creates new if None).
|
|
88
|
+
|
|
75
89
|
"""
|
|
76
90
|
self.partition_key = partition_key or "2024-01-01"
|
|
77
91
|
self.iceberg = mock_iceberg or MockIcebergCatalog()
|
|
@@ -81,7 +95,12 @@ class MockAssetContext:
|
|
|
81
95
|
self._logger = self._create_logger()
|
|
82
96
|
|
|
83
97
|
def _create_logger(self) -> Any:
|
|
84
|
-
"""Create logger that captures to self._logs.
|
|
98
|
+
"""Create logger that captures to self._logs.
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Logger instance with capture handler attached.
|
|
102
|
+
|
|
103
|
+
"""
|
|
85
104
|
name = f"asset_test_{id(self)}"
|
|
86
105
|
logger = get_logger(name)
|
|
87
106
|
|
|
@@ -99,6 +118,7 @@ class MockAssetContext:
|
|
|
99
118
|
|
|
100
119
|
Args:
|
|
101
120
|
logs_list: Destination list for formatted log messages.
|
|
121
|
+
|
|
102
122
|
"""
|
|
103
123
|
super().__init__()
|
|
104
124
|
self.logs = logs_list
|
|
@@ -108,6 +128,7 @@ class MockAssetContext:
|
|
|
108
128
|
|
|
109
129
|
Args:
|
|
110
130
|
record: Log record emitted by the logger.
|
|
131
|
+
|
|
111
132
|
"""
|
|
112
133
|
self.logs.append(self.format(record))
|
|
113
134
|
|
|
@@ -121,12 +142,12 @@ class MockAssetContext:
|
|
|
121
142
|
return logger
|
|
122
143
|
|
|
123
144
|
def log(self, message: str, level: str = "INFO") -> None:
|
|
124
|
-
"""
|
|
125
|
-
Log a message.
|
|
145
|
+
"""Log a message.
|
|
126
146
|
|
|
127
147
|
Args:
|
|
128
|
-
message: Message to log
|
|
129
|
-
level: Log level (DEBUG, INFO, WARNING, ERROR)
|
|
148
|
+
message: Message to log.
|
|
149
|
+
level: Log level (DEBUG, INFO, WARNING, ERROR).
|
|
150
|
+
|
|
130
151
|
"""
|
|
131
152
|
resolved_level = level.lower()
|
|
132
153
|
if resolved_level == "warn":
|
|
@@ -135,21 +156,26 @@ class MockAssetContext:
|
|
|
135
156
|
|
|
136
157
|
@property
|
|
137
158
|
def logs(self) -> list[str]:
|
|
138
|
-
"""Get all captured logs.
|
|
159
|
+
"""Get all captured logs.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
List of formatted log messages.
|
|
163
|
+
|
|
164
|
+
"""
|
|
139
165
|
return self._logs.copy()
|
|
140
166
|
|
|
141
167
|
def get_resource(self, name: str) -> Any:
|
|
142
|
-
"""
|
|
143
|
-
Get a mock resource by name.
|
|
168
|
+
"""Get a mock resource by name.
|
|
144
169
|
|
|
145
170
|
Args:
|
|
146
|
-
name: Resource name (table_store, trino, etc.)
|
|
171
|
+
name: Resource name (table_store, trino, etc.).
|
|
147
172
|
|
|
148
173
|
Returns:
|
|
149
|
-
Mock resource instance
|
|
174
|
+
Mock resource instance.
|
|
150
175
|
|
|
151
176
|
Raises:
|
|
152
|
-
ValueError: If resource doesn't exist
|
|
177
|
+
ValueError: If resource doesn't exist.
|
|
178
|
+
|
|
153
179
|
"""
|
|
154
180
|
resources = {
|
|
155
181
|
"table_store": self.iceberg,
|
|
@@ -172,26 +198,26 @@ def test_asset_execution(
|
|
|
172
198
|
materialize_kwargs: Optional[dict[str, Any]] = None,
|
|
173
199
|
_pytest_skip: bool = True, # Flag to prevent pytest collection
|
|
174
200
|
) -> AssetTestResult:
|
|
175
|
-
"""
|
|
176
|
-
Execute an asset with mocked dependencies.
|
|
201
|
+
"""Execute an asset with mocked dependencies.
|
|
177
202
|
|
|
178
203
|
Runs a `@phlo_ingestion` asset in isolation with mocked Iceberg,
|
|
179
204
|
Trino, and DLT services. Captures results and logs for inspection.
|
|
180
205
|
|
|
181
206
|
Args:
|
|
182
|
-
asset_fn: Asset function to test
|
|
183
|
-
partition: Partition key (e.g., "2024-01-01")
|
|
184
|
-
mock_data: Mock data to return from DLT source
|
|
185
|
-
mock_iceberg: Pre-configured MockIcebergCatalog (uses new if None)
|
|
186
|
-
mock_trino: Pre-configured MockTrinoResource (uses new if None)
|
|
187
|
-
expected_schema: Pandera schema to validate results
|
|
188
|
-
materialize_kwargs: Extra kwargs to pass to materialize
|
|
207
|
+
asset_fn: Asset function to test.
|
|
208
|
+
partition: Partition key (e.g., "2024-01-01").
|
|
209
|
+
mock_data: Mock data to return from DLT source.
|
|
210
|
+
mock_iceberg: Pre-configured MockIcebergCatalog (uses new if None).
|
|
211
|
+
mock_trino: Pre-configured MockTrinoResource (uses new if None).
|
|
212
|
+
expected_schema: Pandera schema to validate results.
|
|
213
|
+
materialize_kwargs: Extra kwargs to pass to materialize.
|
|
214
|
+
_pytest_skip: Flag to prevent pytest from collecting as test.
|
|
189
215
|
|
|
190
216
|
Returns:
|
|
191
|
-
AssetTestResult with execution details
|
|
217
|
+
AssetTestResult with execution details.
|
|
192
218
|
|
|
193
219
|
Raises:
|
|
194
|
-
ValueError: If asset execution fails (and success=False in result)
|
|
220
|
+
ValueError: If asset execution fails (and success=False in result).
|
|
195
221
|
|
|
196
222
|
Example:
|
|
197
223
|
>>> @phlo_ingestion(
|
|
@@ -207,6 +233,7 @@ def test_asset_execution(
|
|
|
207
233
|
... )
|
|
208
234
|
>>> assert result.success
|
|
209
235
|
>>> assert len(result.data) == 1
|
|
236
|
+
|
|
210
237
|
"""
|
|
211
238
|
if mock_data is None:
|
|
212
239
|
mock_data = []
|
|
@@ -274,27 +301,27 @@ def test_asset_with_catalog(
|
|
|
274
301
|
partition: str = "2024-01-01",
|
|
275
302
|
catalog: Optional[MockIcebergCatalog] = None,
|
|
276
303
|
) -> AssetTestResult:
|
|
277
|
-
"""
|
|
278
|
-
Execute an asset with access to mock Iceberg catalog.
|
|
304
|
+
"""Execute an asset with access to mock Iceberg catalog.
|
|
279
305
|
|
|
280
306
|
Useful for testing assets that read from or write to Iceberg tables.
|
|
281
307
|
|
|
282
308
|
Args:
|
|
283
|
-
asset_fn: Asset function to test
|
|
284
|
-
partition: Partition key
|
|
285
|
-
catalog: Pre-configured MockIcebergCatalog
|
|
309
|
+
asset_fn: Asset function to test.
|
|
310
|
+
partition: Partition key.
|
|
311
|
+
catalog: Pre-configured MockIcebergCatalog.
|
|
286
312
|
|
|
287
313
|
Returns:
|
|
288
|
-
AssetTestResult with catalog access
|
|
314
|
+
AssetTestResult with catalog access.
|
|
289
315
|
|
|
290
316
|
Example:
|
|
291
317
|
>>> catalog = MockIcebergCatalog()
|
|
292
|
-
>>> #
|
|
318
|
+
>>> # Set up tables in catalog
|
|
293
319
|
>>> result = test_asset_with_catalog(
|
|
294
320
|
... my_transform_asset,
|
|
295
321
|
... partition="2024-01-01",
|
|
296
322
|
... catalog=catalog,
|
|
297
323
|
... )
|
|
324
|
+
|
|
298
325
|
"""
|
|
299
326
|
if catalog is None:
|
|
300
327
|
catalog = MockIcebergCatalog()
|
|
@@ -311,26 +338,26 @@ def test_asset_with_trino(
|
|
|
311
338
|
partition: str = "2024-01-01",
|
|
312
339
|
trino: Optional[MockTrinoResource] = None,
|
|
313
340
|
) -> AssetTestResult:
|
|
314
|
-
"""
|
|
315
|
-
Execute an asset with access to mock Trino resource.
|
|
341
|
+
"""Execute an asset with access to mock Trino resource.
|
|
316
342
|
|
|
317
343
|
Useful for testing quality checks and transform assets.
|
|
318
344
|
|
|
319
345
|
Args:
|
|
320
|
-
asset_fn: Asset function to test
|
|
321
|
-
partition: Partition key
|
|
322
|
-
trino: Pre-configured MockTrinoResource
|
|
346
|
+
asset_fn: Asset function to test.
|
|
347
|
+
partition: Partition key.
|
|
348
|
+
trino: Pre-configured MockTrinoResource.
|
|
323
349
|
|
|
324
350
|
Returns:
|
|
325
|
-
AssetTestResult with Trino access
|
|
351
|
+
AssetTestResult with Trino access.
|
|
326
352
|
|
|
327
353
|
Example:
|
|
328
354
|
>>> trino = MockTrinoResource()
|
|
329
|
-
>>> #
|
|
355
|
+
>>> # Set up tables in Trino
|
|
330
356
|
>>> result = test_asset_with_trino(
|
|
331
357
|
... my_quality_check,
|
|
332
358
|
... trino=trino,
|
|
333
359
|
... )
|
|
360
|
+
|
|
334
361
|
"""
|
|
335
362
|
if trino is None:
|
|
336
363
|
trino = MockTrinoResource()
|
|
@@ -343,16 +370,21 @@ def test_asset_with_trino(
|
|
|
343
370
|
|
|
344
371
|
|
|
345
372
|
class TestAssetExecutor:
|
|
346
|
-
"""
|
|
347
|
-
Reusable executor for testing multiple asset runs.
|
|
373
|
+
"""Reusable executor for testing multiple asset runs.
|
|
348
374
|
|
|
349
375
|
Maintains catalog state across multiple executions for integration testing.
|
|
350
376
|
|
|
377
|
+
Attributes:
|
|
378
|
+
catalog: Shared MockIcebergCatalog instance.
|
|
379
|
+
trino: Shared MockTrinoResource instance.
|
|
380
|
+
results: List of all AssetTestResult instances from executions.
|
|
381
|
+
|
|
351
382
|
Example:
|
|
352
383
|
>>> executor = TestAssetExecutor()
|
|
353
384
|
>>> result1 = executor.execute(asset1, partition="2024-01-01")
|
|
354
385
|
>>> result2 = executor.execute(asset2, partition="2024-01-01")
|
|
355
386
|
>>> # Both use same catalog instance
|
|
387
|
+
|
|
356
388
|
"""
|
|
357
389
|
|
|
358
390
|
def __init__(
|
|
@@ -360,12 +392,12 @@ class TestAssetExecutor:
|
|
|
360
392
|
catalog: Optional[MockIcebergCatalog] = None,
|
|
361
393
|
trino: Optional[MockTrinoResource] = None,
|
|
362
394
|
) -> None:
|
|
363
|
-
"""
|
|
364
|
-
Initialize executor.
|
|
395
|
+
"""Initialize executor.
|
|
365
396
|
|
|
366
397
|
Args:
|
|
367
|
-
catalog: Shared MockIcebergCatalog
|
|
368
|
-
trino: Shared MockTrinoResource
|
|
398
|
+
catalog: Shared MockIcebergCatalog.
|
|
399
|
+
trino: Shared MockTrinoResource.
|
|
400
|
+
|
|
369
401
|
"""
|
|
370
402
|
self.catalog = catalog or MockIcebergCatalog()
|
|
371
403
|
self.trino = trino or MockTrinoResource()
|
|
@@ -377,16 +409,16 @@ class TestAssetExecutor:
|
|
|
377
409
|
partition: str = "2024-01-01",
|
|
378
410
|
mock_data: Optional[list[dict[str, Any]]] = None,
|
|
379
411
|
) -> AssetTestResult:
|
|
380
|
-
"""
|
|
381
|
-
Execute an asset with shared resources.
|
|
412
|
+
"""Execute an asset with shared resources.
|
|
382
413
|
|
|
383
414
|
Args:
|
|
384
|
-
asset_fn: Asset function to test
|
|
385
|
-
partition: Partition key
|
|
386
|
-
mock_data: Mock data (not used in executor mode)
|
|
415
|
+
asset_fn: Asset function to test.
|
|
416
|
+
partition: Partition key.
|
|
417
|
+
mock_data: Mock data (not used in executor mode).
|
|
387
418
|
|
|
388
419
|
Returns:
|
|
389
|
-
AssetTestResult
|
|
420
|
+
AssetTestResult with execution details.
|
|
421
|
+
|
|
390
422
|
"""
|
|
391
423
|
result = test_asset_execution(
|
|
392
424
|
asset_fn,
|
|
@@ -399,14 +431,14 @@ class TestAssetExecutor:
|
|
|
399
431
|
return result
|
|
400
432
|
|
|
401
433
|
def get_results(self, asset_fn: Callable) -> list[AssetTestResult]:
|
|
402
|
-
"""
|
|
403
|
-
Get results for a specific asset.
|
|
434
|
+
"""Get results for a specific asset.
|
|
404
435
|
|
|
405
436
|
Args:
|
|
406
|
-
asset_fn: Asset function to filter by
|
|
437
|
+
asset_fn: Asset function to filter by.
|
|
407
438
|
|
|
408
439
|
Returns:
|
|
409
|
-
List of results for that asset
|
|
440
|
+
List of results for that asset.
|
|
441
|
+
|
|
410
442
|
"""
|
|
411
443
|
# This is a simplified implementation
|
|
412
444
|
# In practice, you'd track asset names
|