phlo-testing 0.1.0__py3-none-any.whl
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/__init__.py +297 -0
- phlo_testing/conftest_template.py +65 -0
- phlo_testing/execution.py +405 -0
- phlo_testing/fixtures.py +447 -0
- phlo_testing/hooks.py +135 -0
- phlo_testing/local_mode.py +366 -0
- phlo_testing/mock_dlt.py +287 -0
- phlo_testing/mock_iceberg.py +435 -0
- phlo_testing/mock_trino.py +486 -0
- phlo_testing/placeholders.py +830 -0
- phlo_testing/utils.py +20 -0
- phlo_testing-0.1.0.dist-info/METADATA +22 -0
- phlo_testing-0.1.0.dist-info/RECORD +15 -0
- phlo_testing-0.1.0.dist-info/WHEEL +5 -0
- phlo_testing-0.1.0.dist-info/top_level.txt +1 -0
phlo_testing/__init__.py
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Phlo Testing Infrastructure
|
|
3
|
+
|
|
4
|
+
Comprehensive testing module for validating Phlo workflows without Docker.
|
|
5
|
+
Provides mock implementations of Iceberg, Trino, and DLT for fast, isolated tests.
|
|
6
|
+
|
|
7
|
+
## Phase 1: Core Mocks (✅ Implemented)
|
|
8
|
+
|
|
9
|
+
### MockIcebergCatalog (Task 1.1)
|
|
10
|
+
In-memory Iceberg catalog backed by DuckDB for fast table operations.
|
|
11
|
+
|
|
12
|
+
```python
|
|
13
|
+
from phlo_testing import MockIcebergCatalog
|
|
14
|
+
|
|
15
|
+
catalog = MockIcebergCatalog()
|
|
16
|
+
schema = pa.schema([("id", pa.int32()), ("name", pa.string())])
|
|
17
|
+
table = catalog.create_table("raw.users", schema=schema)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### mock_dlt_source (Task 1.2)
|
|
21
|
+
Mock DLT sources that return predefined data without API calls.
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from phlo_testing import mock_dlt_source
|
|
25
|
+
|
|
26
|
+
data = [{"id": 1, "name": "Alice"}]
|
|
27
|
+
source = mock_dlt_source(data, resource_name="users")
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Phase 2: Execution & Resources (✅ Implemented)
|
|
31
|
+
|
|
32
|
+
### test_asset_execution (Task 1.3)
|
|
33
|
+
Execute assets with mocked dependencies and capture results.
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from phlo_testing import test_asset_execution
|
|
37
|
+
|
|
38
|
+
result = test_asset_execution(
|
|
39
|
+
my_asset,
|
|
40
|
+
partition="2024-01-01",
|
|
41
|
+
mock_data=[{"id": 1, "name": "Alice"}],
|
|
42
|
+
)
|
|
43
|
+
assert result.success
|
|
44
|
+
assert len(result.data) == 1
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### MockTrinoResource (Task 1.4)
|
|
48
|
+
Mock Trino resource backed by DuckDB for SQL testing.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from phlo_testing import MockTrinoResource
|
|
52
|
+
|
|
53
|
+
trino = MockTrinoResource()
|
|
54
|
+
cursor = trino.cursor()
|
|
55
|
+
cursor.execute("SELECT * FROM users")
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### pytest Fixtures (Task 1.5)
|
|
59
|
+
Reusable fixtures for common test scenarios.
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
def test_my_asset(mock_iceberg_catalog, mock_trino, sample_partition_date):
|
|
63
|
+
# Fixtures automatically provided
|
|
64
|
+
pass
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Local Test Mode (Task 1.6)
|
|
68
|
+
Enable `phlo test --local` without Docker.
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from phlo_testing import local_test_mode
|
|
72
|
+
|
|
73
|
+
with local_test_mode():
|
|
74
|
+
# All resources are mocked automatically
|
|
75
|
+
pass
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Quick Start
|
|
79
|
+
|
|
80
|
+
### 1. Basic Asset Test
|
|
81
|
+
```python
|
|
82
|
+
from phlo_testing import test_asset_execution, mock_dlt_source
|
|
83
|
+
|
|
84
|
+
def test_ingestion_asset():
|
|
85
|
+
data = [{"id": 1, "value": 42}]
|
|
86
|
+
result = test_asset_execution(
|
|
87
|
+
my_ingestion_asset,
|
|
88
|
+
partition="2024-01-01",
|
|
89
|
+
mock_data=data,
|
|
90
|
+
)
|
|
91
|
+
assert result.success
|
|
92
|
+
assert len(result.data) == 1
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 2. Using Fixtures
|
|
96
|
+
```python
|
|
97
|
+
def test_with_fixtures(mock_iceberg_catalog, sample_partition_date):
|
|
98
|
+
schema = create_schema()
|
|
99
|
+
table = mock_iceberg_catalog.create_table(
|
|
100
|
+
"raw.test",
|
|
101
|
+
schema=schema,
|
|
102
|
+
)
|
|
103
|
+
# Use in your test
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 3. Fixture Recording
|
|
107
|
+
```python
|
|
108
|
+
from phlo_testing import FixtureRecorder
|
|
109
|
+
|
|
110
|
+
recorder = FixtureRecorder()
|
|
111
|
+
data = recorder.record_dlt_source(
|
|
112
|
+
"users",
|
|
113
|
+
my_api_fetch_function,
|
|
114
|
+
)
|
|
115
|
+
# Data is saved for replay in tests
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Performance
|
|
119
|
+
|
|
120
|
+
- MockIcebergCatalog: < 100ms per operation
|
|
121
|
+
- MockTrinoResource: < 10ms per query
|
|
122
|
+
- test_asset_execution: < 1 second typical
|
|
123
|
+
- Full test suite: < 5 seconds
|
|
124
|
+
|
|
125
|
+
## Features
|
|
126
|
+
|
|
127
|
+
✅ Drop-in replacements for production resources
|
|
128
|
+
✅ DuckDB-backed for compatibility with Trino SQL
|
|
129
|
+
✅ Automatic resource cleanup
|
|
130
|
+
✅ Fixture recording and playback
|
|
131
|
+
✅ Context manager and fixture support
|
|
132
|
+
✅ Error injection for testing failure paths
|
|
133
|
+
✅ Session and function-scoped fixtures
|
|
134
|
+
|
|
135
|
+
## Modules
|
|
136
|
+
|
|
137
|
+
- `mock_iceberg.py` - MockIcebergCatalog and table operations
|
|
138
|
+
- `mock_dlt.py` - Mock DLT sources and pipelines
|
|
139
|
+
- `mock_trino.py` - MockTrinoResource and SQL execution
|
|
140
|
+
- `execution.py` - Asset execution with mocked dependencies
|
|
141
|
+
- `fixtures.py` - pytest fixtures for common scenarios
|
|
142
|
+
- `local_mode.py` - Local test mode with fixture recording
|
|
143
|
+
|
|
144
|
+
## Testing Guide
|
|
145
|
+
|
|
146
|
+
For comprehensive testing patterns and best practices, see:
|
|
147
|
+
`docs/TESTING_GUIDE.md`
|
|
148
|
+
"""
|
|
149
|
+
|
|
150
|
+
# Phase 1: Core Mocks
|
|
151
|
+
from phlo_testing.conftest_template import (
|
|
152
|
+
CONFTEST_TEMPLATE,
|
|
153
|
+
get_conftest_template,
|
|
154
|
+
)
|
|
155
|
+
from phlo_testing.execution import (
|
|
156
|
+
AssetTestResult,
|
|
157
|
+
MockAssetContext,
|
|
158
|
+
TestAssetExecutor,
|
|
159
|
+
test_asset_execution,
|
|
160
|
+
test_asset_with_catalog,
|
|
161
|
+
test_asset_with_trino,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Fixtures are auto-discovered by pytest from fixtures.py
|
|
165
|
+
# Import here for documentation purposes
|
|
166
|
+
from phlo_testing.fixtures import (
|
|
167
|
+
conftest_template,
|
|
168
|
+
create_partition_dates,
|
|
169
|
+
load_csv_fixture,
|
|
170
|
+
load_json_fixture,
|
|
171
|
+
mock_asset_context,
|
|
172
|
+
mock_dlt_source_fixture,
|
|
173
|
+
mock_iceberg_catalog,
|
|
174
|
+
mock_resources,
|
|
175
|
+
mock_trino,
|
|
176
|
+
sample_dataframe,
|
|
177
|
+
sample_dlt_data,
|
|
178
|
+
sample_partition_date,
|
|
179
|
+
sample_partition_range,
|
|
180
|
+
setup_test_catalog,
|
|
181
|
+
setup_test_trino,
|
|
182
|
+
temp_staging_dir,
|
|
183
|
+
test_config,
|
|
184
|
+
test_data_dir,
|
|
185
|
+
)
|
|
186
|
+
from phlo_testing.local_mode import (
|
|
187
|
+
FixtureRecorder,
|
|
188
|
+
LocalTestMode,
|
|
189
|
+
disable_local_test_mode,
|
|
190
|
+
enable_local_test_mode,
|
|
191
|
+
get_fixture_dir,
|
|
192
|
+
is_local_test_mode,
|
|
193
|
+
local_test,
|
|
194
|
+
local_test_mode,
|
|
195
|
+
set_fixture_dir,
|
|
196
|
+
)
|
|
197
|
+
from phlo_testing.mock_dlt import (
|
|
198
|
+
MockDLTError,
|
|
199
|
+
MockDLTResource,
|
|
200
|
+
MockDLTSource,
|
|
201
|
+
create_mock_dlt_dataframe,
|
|
202
|
+
mock_dlt_pipeline,
|
|
203
|
+
mock_dlt_source,
|
|
204
|
+
mock_dlt_source_multi,
|
|
205
|
+
mock_dlt_source_with_error,
|
|
206
|
+
)
|
|
207
|
+
from phlo_testing.mock_iceberg import (
|
|
208
|
+
MockIcebergCatalog,
|
|
209
|
+
MockTable,
|
|
210
|
+
MockTableScan,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
# Phase 2: Execution & Resources
|
|
214
|
+
from phlo_testing.mock_trino import (
|
|
215
|
+
MockConnection,
|
|
216
|
+
MockCursor,
|
|
217
|
+
MockTrinoResource,
|
|
218
|
+
)
|
|
219
|
+
from phlo_testing.hooks import (
|
|
220
|
+
MockHookBus,
|
|
221
|
+
capture_events,
|
|
222
|
+
sample_ingestion_event,
|
|
223
|
+
sample_lineage_event,
|
|
224
|
+
sample_publish_event,
|
|
225
|
+
sample_quality_event,
|
|
226
|
+
sample_service_event,
|
|
227
|
+
sample_telemetry_event,
|
|
228
|
+
sample_transform_event,
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
__all__ = [
|
|
232
|
+
# Phase 1: Core Mocks
|
|
233
|
+
"MockIcebergCatalog",
|
|
234
|
+
"MockTable",
|
|
235
|
+
"MockTableScan",
|
|
236
|
+
"MockDLTResource",
|
|
237
|
+
"MockDLTSource",
|
|
238
|
+
"mock_dlt_source",
|
|
239
|
+
"mock_dlt_source_multi",
|
|
240
|
+
"mock_dlt_source_with_error",
|
|
241
|
+
"mock_dlt_pipeline",
|
|
242
|
+
"create_mock_dlt_dataframe",
|
|
243
|
+
"MockDLTError",
|
|
244
|
+
# Phase 2: Execution & Resources
|
|
245
|
+
"MockTrinoResource",
|
|
246
|
+
"MockConnection",
|
|
247
|
+
"MockCursor",
|
|
248
|
+
"test_asset_execution",
|
|
249
|
+
"test_asset_with_catalog",
|
|
250
|
+
"test_asset_with_trino",
|
|
251
|
+
"AssetTestResult",
|
|
252
|
+
"MockAssetContext",
|
|
253
|
+
"TestAssetExecutor",
|
|
254
|
+
"LocalTestMode",
|
|
255
|
+
"local_test_mode",
|
|
256
|
+
"local_test",
|
|
257
|
+
"FixtureRecorder",
|
|
258
|
+
"is_local_test_mode",
|
|
259
|
+
"enable_local_test_mode",
|
|
260
|
+
"disable_local_test_mode",
|
|
261
|
+
"set_fixture_dir",
|
|
262
|
+
"get_fixture_dir",
|
|
263
|
+
# Fixtures
|
|
264
|
+
"mock_iceberg_catalog",
|
|
265
|
+
"mock_trino",
|
|
266
|
+
"mock_asset_context",
|
|
267
|
+
"mock_resources",
|
|
268
|
+
"mock_hook_bus",
|
|
269
|
+
"sample_partition_date",
|
|
270
|
+
"sample_partition_range",
|
|
271
|
+
"sample_dlt_data",
|
|
272
|
+
"sample_dataframe",
|
|
273
|
+
"mock_dlt_source_fixture",
|
|
274
|
+
"temp_staging_dir",
|
|
275
|
+
"test_data_dir",
|
|
276
|
+
"setup_test_catalog",
|
|
277
|
+
"setup_test_trino",
|
|
278
|
+
"load_json_fixture",
|
|
279
|
+
"load_csv_fixture",
|
|
280
|
+
"test_config",
|
|
281
|
+
"create_partition_dates",
|
|
282
|
+
"conftest_template",
|
|
283
|
+
"CONFTEST_TEMPLATE",
|
|
284
|
+
"get_conftest_template",
|
|
285
|
+
# Hooks
|
|
286
|
+
"MockHookBus",
|
|
287
|
+
"capture_events",
|
|
288
|
+
"sample_ingestion_event",
|
|
289
|
+
"sample_quality_event",
|
|
290
|
+
"sample_transform_event",
|
|
291
|
+
"sample_publish_event",
|
|
292
|
+
"sample_lineage_event",
|
|
293
|
+
"sample_telemetry_event",
|
|
294
|
+
"sample_service_event",
|
|
295
|
+
]
|
|
296
|
+
|
|
297
|
+
__version__ = "1.0.0"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Conftest template for user projects.
|
|
3
|
+
|
|
4
|
+
This module provides a ready-to-use conftest.py template that users can copy
|
|
5
|
+
to their tests/ directory to get all phlo_testing fixtures automatically.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from phlo_testing.conftest_template import CONFTEST_TEMPLATE
|
|
9
|
+
|
|
10
|
+
# Write to tests/conftest.py
|
|
11
|
+
Path("tests/conftest.py").write_text(CONFTEST_TEMPLATE)
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
CONFTEST_TEMPLATE = '''"""
|
|
15
|
+
Pytest configuration and shared fixtures.
|
|
16
|
+
|
|
17
|
+
Place this file in tests/ directory to make fixtures available to all tests.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import pytest
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
# Import fixtures from phlo_testing
|
|
24
|
+
from phlo_testing.fixtures import (
|
|
25
|
+
mock_iceberg_catalog,
|
|
26
|
+
mock_trino,
|
|
27
|
+
mock_asset_context,
|
|
28
|
+
mock_resources,
|
|
29
|
+
sample_partition_date,
|
|
30
|
+
sample_partition_range,
|
|
31
|
+
sample_dlt_data,
|
|
32
|
+
sample_dataframe,
|
|
33
|
+
mock_dlt_source_fixture,
|
|
34
|
+
temp_staging_dir,
|
|
35
|
+
test_data_dir,
|
|
36
|
+
setup_test_catalog,
|
|
37
|
+
setup_test_trino,
|
|
38
|
+
load_json_fixture,
|
|
39
|
+
load_csv_fixture,
|
|
40
|
+
test_config,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@pytest.fixture(autouse=True)
|
|
45
|
+
def reset_test_env(monkeypatch):
|
|
46
|
+
"""Reset environment variables before each test."""
|
|
47
|
+
monkeypatch.setenv("PHLO_ENV", "test")
|
|
48
|
+
monkeypatch.setenv("PHLO_LOG_LEVEL", "DEBUG")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@pytest.fixture
|
|
52
|
+
def project_root() -> Path:
|
|
53
|
+
"""Return path to project root."""
|
|
54
|
+
return Path(__file__).parent.parent
|
|
55
|
+
'''
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def get_conftest_template() -> str:
|
|
59
|
+
"""
|
|
60
|
+
Get the conftest.py template content.
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
String content for conftest.py
|
|
64
|
+
"""
|
|
65
|
+
return CONFTEST_TEMPLATE
|