Skip to content

Commit d71be53

Browse files
committed
Add test for SFV online retrieval
Signed-off-by: Felix Wang <wangfelix98@gmail.com>
1 parent 47d1c45 commit d71be53

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

sdk/python/tests/integration/online_store/test_universal_online.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,82 @@ def test_online_retrieval_with_event_timestamps(
441441
)
442442

443443

444+
@pytest.mark.integration
445+
@pytest.mark.universal_online_stores
446+
@pytest.mark.goserver
447+
@pytest.mark.parametrize("full_feature_names", [True, False], ids=lambda v: str(v))
448+
def test_stream_feature_view_online_retrieval(
449+
environment, universal_data_sources, feature_server_endpoint, full_feature_names
450+
):
451+
"""
452+
Tests materialization and online retrieval for stream feature views.
453+
454+
This test is separate from test_online_retrieval since combining feature views and
455+
stream feature views into a single test resulted in test flakiness. This is tech
456+
debt that should be resolved soon.
457+
"""
458+
# Set up feature store.
459+
fs = environment.feature_store
460+
entities, datasets, data_sources = universal_data_sources
461+
feature_views = construct_universal_feature_views(data_sources)
462+
pushable_feature_view = feature_views.pushed_locations
463+
fs.apply([location(), pushable_feature_view])
464+
465+
# Materialize.
466+
fs.materialize(
467+
environment.start_date - timedelta(days=1),
468+
environment.end_date + timedelta(days=1),
469+
)
470+
471+
# Get online features by randomly sampling 10 entities that exist in the batch source.
472+
sample_locations = datasets.location_df.sample(10)["location_id"]
473+
entity_rows = [
474+
{"location_id": sample_location} for sample_location in sample_locations
475+
]
476+
477+
feature_refs = [
478+
"pushable_location_stats:temperature",
479+
]
480+
unprefixed_feature_refs = [f.rsplit(":", 1)[-1] for f in feature_refs if ":" in f]
481+
482+
online_features_dict = get_online_features_dict(
483+
environment=environment,
484+
endpoint=feature_server_endpoint,
485+
features=feature_refs,
486+
entity_rows=entity_rows,
487+
full_feature_names=full_feature_names,
488+
)
489+
490+
# Check that the response has the expected set of keys.
491+
keys = set(online_features_dict.keys())
492+
expected_keys = set(
493+
f.replace(":", "__") if full_feature_names else f.split(":")[-1]
494+
for f in feature_refs
495+
) | {"location_id"}
496+
assert (
497+
keys == expected_keys
498+
), f"Response keys are different from expected: {keys - expected_keys} (extra) and {expected_keys - keys} (missing)"
499+
500+
# Check that the feature values match.
501+
tc = unittest.TestCase()
502+
for i, entity_row in enumerate(entity_rows):
503+
df_features = get_latest_feature_values_from_location_df(
504+
entity_row, datasets.location_df
505+
)
506+
507+
assert df_features["location_id"] == online_features_dict["location_id"][i]
508+
for unprefixed_feature_ref in unprefixed_feature_refs:
509+
tc.assertAlmostEqual(
510+
df_features[unprefixed_feature_ref],
511+
online_features_dict[
512+
response_feature_name(
513+
unprefixed_feature_ref, feature_refs, full_feature_names
514+
)
515+
][i],
516+
delta=0.0001,
517+
)
518+
519+
444520
@pytest.mark.integration
445521
@pytest.mark.universal_online_stores
446522
@pytest.mark.goserver
@@ -859,6 +935,10 @@ def get_latest_feature_values_for_location_df(entity_row, origin_df, destination
859935
}
860936

861937

938+
def get_latest_feature_values_from_location_df(entity_row, location_df):
939+
return get_latest_row(entity_row, location_df, "location_id", "location_id")
940+
941+
862942
def assert_feature_service_correctness(
863943
environment,
864944
endpoint,

0 commit comments

Comments
 (0)