Skip to content

Commit

Permalink
Add tests + snapshots for suggestions.
Browse files Browse the repository at this point in the history
  • Loading branch information
plypaul committed Dec 19, 2023
1 parent 1fdfbd2 commit 28c8111
Show file tree
Hide file tree
Showing 6 changed files with 306 additions and 0 deletions.
155 changes: 155 additions & 0 deletions metricflow/test/query/test_suggestions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
from __future__ import annotations

import logging

import pytest
from _pytest.fixtures import FixtureRequest
from dbt_semantic_interfaces.implementations.filters.where_filter import (
PydanticWhereFilter,
PydanticWhereFilterIntersection,
)
from dbt_semantic_interfaces.implementations.semantic_manifest import PydanticSemanticManifest
from dbt_semantic_interfaces.naming.keywords import METRIC_TIME_ELEMENT_NAME
from dbt_semantic_interfaces.references import MetricReference

from metricflow.model.semantic_manifest_lookup import SemanticManifestLookup
from metricflow.plan_conversion.column_resolver import DunderColumnAssociationResolver
from metricflow.query.query_exceptions import InvalidQueryException
from metricflow.query.query_parser import MetricFlowQueryParser
from metricflow.test.fixtures.setup_fixtures import MetricFlowTestSessionState
from metricflow.test.model.modify.modify_manifest import modify_manifest
from metricflow.test.model.modify.modify_metric_filter import ModifyMetricFilterTransform
from metricflow.test.snapshot_utils import assert_object_snapshot_equal

logger = logging.getLogger(__name__)


def test_suggestions_for_group_by_item( # noqa: D
request: FixtureRequest, mf_test_session_state: MetricFlowTestSessionState, query_parser: MetricFlowQueryParser
) -> None:
with pytest.raises(InvalidQueryException) as e:
query_parser.parse_and_validate_query(metric_names=("bookings",), group_by_names=("booking__instant",))

assert_object_snapshot_equal(
request=request,
mf_test_session_state=mf_test_session_state,
obj_id="result_0",
obj=str(e.value),
)


def test_suggestions_for_metric( # noqa: D
request: FixtureRequest, mf_test_session_state: MetricFlowTestSessionState, query_parser: MetricFlowQueryParser
) -> None:
with pytest.raises(InvalidQueryException) as e:
query_parser.parse_and_validate_query(metric_names=("booking",), group_by_names=(METRIC_TIME_ELEMENT_NAME,))

assert_object_snapshot_equal(
request=request,
mf_test_session_state=mf_test_session_state,
obj_id="result_0",
obj=str(e.value),
)


def test_suggestions_for_multiple_metrics( # noqa: D
request: FixtureRequest, mf_test_session_state: MetricFlowTestSessionState, query_parser: MetricFlowQueryParser
) -> None:
with pytest.raises(InvalidQueryException) as e:
query_parser.parse_and_validate_query(metric_names=("bookings", "listings"), group_by_names=("booking__ds",))

assert_object_snapshot_equal(
request=request,
mf_test_session_state=mf_test_session_state,
obj_id="result_0",
obj=str(e.value),
)


def test_suggestions_for_defined_where_filter( # noqa: D
request: FixtureRequest,
mf_test_session_state: MetricFlowTestSessionState,
simple_semantic_manifest: PydanticSemanticManifest,
) -> None:
modified_manifest = modify_manifest(
semantic_manifest=simple_semantic_manifest,
transform_rule=ModifyMetricFilterTransform(
metric_reference=MetricReference(element_name="listings"),
where_filter_intersection=PydanticWhereFilterIntersection(
where_filters=[
PydanticWhereFilter(where_sql_template=("{{ TimeDimension('listing__paid_at') }} > '2020-01-01'")),
]
),
),
)

semantic_manifest_lookup = SemanticManifestLookup(modified_manifest)
column_association_resolver = DunderColumnAssociationResolver(modified_manifest)

query_parser = MetricFlowQueryParser(
column_association_resolver=column_association_resolver,
model=semantic_manifest_lookup,
)
with pytest.raises(InvalidQueryException) as e:
query_parser.parse_and_validate_query(metric_names=("listings",), group_by_names=(METRIC_TIME_ELEMENT_NAME,))

assert_object_snapshot_equal(
request=request,
mf_test_session_state=mf_test_session_state,
obj_id="result_0",
obj=str(e.value),
)


def test_suggestions_for_defined_filters_in_multi_metric_query(
request: FixtureRequest,
mf_test_session_state: MetricFlowTestSessionState,
simple_semantic_manifest: PydanticSemanticManifest,
) -> None:
"""Tests that the suggestions for invalid items in filters are specific to the metric."""
where_sql_template = "{{ TimeDimension('booking__paid_at') }} > '2020-01-01'"
modified_manifest = modify_manifest(
semantic_manifest=simple_semantic_manifest,
transform_rule=ModifyMetricFilterTransform(
metric_reference=MetricReference(element_name="listings"),
where_filter_intersection=PydanticWhereFilterIntersection(
where_filters=[
PydanticWhereFilter(where_sql_template=where_sql_template),
]
),
),
)
modified_manifest = modify_manifest(
semantic_manifest=modified_manifest,
transform_rule=ModifyMetricFilterTransform(
metric_reference=MetricReference(element_name="bookings"),
where_filter_intersection=PydanticWhereFilterIntersection(
where_filters=[
PydanticWhereFilter(where_sql_template=where_sql_template),
]
),
),
)

semantic_manifest_lookup = SemanticManifestLookup(modified_manifest)
column_association_resolver = DunderColumnAssociationResolver(modified_manifest)

query_parser = MetricFlowQueryParser(
column_association_resolver=column_association_resolver,
model=semantic_manifest_lookup,
)
with pytest.raises(InvalidQueryException) as e:
query_parser.parse_and_validate_query(
metric_names=(
"bookings",
"listings",
),
group_by_names=(METRIC_TIME_ELEMENT_NAME,),
)

assert_object_snapshot_equal(
request=request,
mf_test_session_state=mf_test_session_state,
obj_id="result_0",
obj=str(e.value),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Got errors while resolving the query.

Error #1:
Query Input:

WhereFilter(
["{{ TimeDimension('booking__paid_at') }} > '2020-01-01'",]
)
Filter Path:
[Resolve Query(['bookings', 'listings'])]
-> [Resolve Metric('listings')]
Object Builder Input:
TimeDimension('booking__paid_at')

Message:

The given input does not match any of the available group-by-items for Measure('listings'). Common issues are:

* Incorrect names.
* No valid join paths exist from the measure to the group-by-item (fan-out joins are not yet supported).
* There are multiple matching join paths (disambiguation support is pending).

Suggestions:
[
"Dimension('listing__capacity_latest')",
"TimeDimension('listing__created_at', 'day')",
"TimeDimension('listing__ds', 'day')",
"Dimension('listing__is_lux_latest')",
"TimeDimension('user__created_at', 'day')",
"TimeDimension('user__ds_latest', 'day')",
]

Issue Location:

[Resolve Query(['bookings', 'listings'])]
-> [Resolve Metric('listings')]
-> [Resolve Measure('listings')]
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Got errors while resolving the query.

Error #1:
Query Input:

WhereFilter(
["{{ TimeDimension('listing__paid_at') }} > '2020-01-01'",]
)
Filter Path:
[Resolve Query(['listings'])]
-> [Resolve Metric('listings')]
Object Builder Input:
TimeDimension('listing__paid_at')

Message:

The given input does not match any of the available group-by-items for Measure('listings'). Common issues are:

* Incorrect names.
* No valid join paths exist from the measure to the group-by-item (fan-out joins are not yet supported).
* There are multiple matching join paths (disambiguation support is pending).

Suggestions:
[
"Dimension('listing__capacity_latest')",
"TimeDimension('listing__created_at', 'day')",
"TimeDimension('listing__ds', 'day')",
"Dimension('listing__is_lux_latest')",
"Dimension('listing__country_latest')",
"TimeDimension('user__created_at', 'day')",
]

Issue Location:

[Resolve Query(['listings'])]
-> [Resolve Metric('listings')]
-> [Resolve Measure('listings')]
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Got errors while resolving the query.

Error #1:
Query Input:

booking__instant

Message:

The given input does not match any of the available group-by-items for Measure('bookings'). Common issues are:

* Incorrect names.
* No valid join paths exist from the measure to the group-by-item (fan-out joins are not yet supported).
* There are multiple matching join paths (disambiguation support is pending).

Suggestions:
[
'booking__is_instant',
'booking__listing',
'booking__host',
'booking__guest',
'booking__ds__day',
'booking__paid_at__day',
]

Issue Location:

[Resolve Query(['bookings'])]
-> [Resolve Metric('bookings')]
-> [Resolve Measure('bookings')]
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Got errors while resolving the query.

Error #1:
Query Input:

booking

Message:

The given input does not exactly match any known metrics.

Suggestions:
['bookings', 'booking_fees', 'booking_value', 'instant_bookings', 'booking_payments', 'max_booking_value']

Issue Location:

[Resolve Query(['booking'])]
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Got errors while resolving the query.

Error #1:
Query Input:

booking__ds

Message:

The given input does not match any of the available group-by-items for Measure('listings'). Common issues are:

* Incorrect names.
* No valid join paths exist from the measure to the group-by-item (fan-out joins are not yet supported).
* There are multiple matching join paths (disambiguation support is pending).

Suggestions:
[
'listing__ds__day',
'listing__user',
'listing__lux_listing',
'listing__is_lux_latest',
'listing__country_latest',
'listing__created_at__day',
]

Issue Location:

[Resolve Query(['bookings', 'listings'])]
-> [Resolve Metric('listings')]
-> [Resolve Measure('listings')]

0 comments on commit 28c8111

Please sign in to comment.