Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions application/datamanager/features/equity_bars.feature
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,22 @@ Feature: Equity Bars Data Management
# Then the response status code should be 200
# And the equity bars data for "2023-05-01" should be deleted
# And the response should confirm successful deletion

Scenario Outline: Manage bucket data for <start_date> to <end_date>
Given I have date ranges:
| start_date | end_date |
| <start_date> | <end_date> |
And the bucket object for "<start_date>" does not exist
When I send a POST request to "/equity-bars" for date range
Then the response status code should be 200
And the bucket object for "<start_date>" should exist
When I read the bucket object for "<start_date>" with DuckDB
Then the result should have rows
When I send a DELETE request to "/equity-bars" for date "<start_date>"
Then the response status code should be 204
And the bucket object for "<start_date>" should not exist

Examples: dates
| start_date | end_date |
| 2025/05/01 | 2025/05/02 |
| 2025/05/03 | 2025/05/04 |
44 changes: 44 additions & 0 deletions application/datamanager/features/steps/bucket_steps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Step definitions for bucket management."""

import os
import duckdb
import gcsfs
from behave import given, when, then


def _bucket_path(start_date: str, end_date: str) -> str:
bucket = os.environ.get("DATA_BUCKET", "test-bucket")
return f"gs://{bucket}/equity/bars/{start_date}_{end_date}/data.parquet"


@given('the bucket object for "{date_str}" does not exist')
def step_impl(context, date_str):
context.bucket_path = _bucket_path(date_str, context.end_date)


@then('the bucket object for "{date_str}" should exist')
def step_impl(context, date_str):
fs = gcsfs.GCSFileSystem(token=os.environ.get("GOOGLE_APPLICATION_CREDENTIALS"))
assert fs.exists(context.bucket_path), f"{context.bucket_path} does not exist"


@then('the bucket object for "{date_str}" should not exist')
def step_impl(context, date_str):
fs = gcsfs.GCSFileSystem(token=os.environ.get("GOOGLE_APPLICATION_CREDENTIALS"))
assert not fs.exists(context.bucket_path), f"{context.bucket_path} still exists"


@when('I read the bucket object for "{date_str}" with DuckDB')
def step_impl(context, date_str):
con = duckdb.connect()
query = (
f"SELECT * FROM read_parquet('{context.bucket_path}') "
f"WHERE date >= '{context.start_date}' AND date <= '{context.end_date}'"
)
context.duckdb_df = con.sql(query).df()


@then('the result should have rows')
def step_impl(context):
assert getattr(context, "duckdb_df", None) is not None
assert len(context.duckdb_df) > 0
Loading