Skip to content

Commit

Permalink
added test
Browse files Browse the repository at this point in the history
  • Loading branch information
WilliamDee committed Dec 11, 2023
1 parent 531719f commit 408689b
Show file tree
Hide file tree
Showing 7 changed files with 1,950 additions and 1 deletion.
271 changes: 271 additions & 0 deletions metricflow/test/integration/test_cases/itest_conversion_metric.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
---
integration_test:
name: conversion_rate_metric
description: Query a conversion metric that calculates the conversion rate
model: SIMPLE_MODEL
metrics: ["visit_buy_conversion_rate"]
group_bys: ["metric_time"]
check_query: |
SELECT
opportunities.metric_time AS metric_time__day
, CAST(conversions.buys AS {{ double_data_type_name }}) / CAST(NULLIF(opportunities.visits, 0) AS {{ double_data_type_name }}) AS visit_buy_conversion_rate
FROM (
SELECT
metric_time, SUM(a.visits) AS visits
FROM (
SELECT
ds AS metric_time, 1 AS visits
FROM {{ source_schema }}.fct_visits visits
) a
GROUP BY
a.metric_time
) opportunities
FULL OUTER JOIN (
SELECT
b.ds AS metric_time, SUM(b.buys) AS buys
FROM (
SELECT DISTINCT
first_value(v.ds) OVER (PARTITION BY buy_source.ds, buy_source.user_id ORDER BY v.ds DESC NULLS FIRST) AS ds
, first_value(v.user_id) OVER (PARTITION BY buy_source.ds, buy_source.user_id ORDER BY v.ds DESC NULLS FIRST) AS user_id
, first_value(v.referrer_id) OVER (PARTITION BY buy_source.ds, buy_source.user_id ORDER BY v.ds DESC NULLS FIRST) AS referrer_id
, buy_source.uuid
, 1 AS buys
FROM {{ source_schema }}.fct_visits v
INNER JOIN
(
SELECT *, {{ generate_random_uuid() }} AS uuid FROM {{ source_schema }}.fct_buys
) buy_source
ON
v.user_id = buy_source.user_id AND v.ds <= buy_source.ds AND v.ds > {{ render_date_sub("buy_source", "ds", 7, TimeGranularity.DAY) }}
) b
GROUP BY
b.ds
) conversions
ON opportunities.metric_time = conversions.metric_time
---
integration_test:
name: conversion_rate_metric_with_dimension
description: Query a conversion metric that calculates the conversion rate without time dimension
model: SIMPLE_MODEL
metrics: ["visit_buy_conversion_rate"]
group_bys: ["visit__referrer_id"]
check_query: |
SELECT
opportunities.referrer_id AS visit__referrer_id
, CAST(conversions.buys AS {{ double_data_type_name }}) / CAST(NULLIF(opportunities.visits, 0) AS {{ double_data_type_name }}) AS visit_buy_conversion_rate
FROM (
SELECT
referrer_id, SUM(a.visits) AS visits
FROM (
SELECT
referrer_id, 1 AS visits
FROM {{ source_schema }}.fct_visits visits
) a
GROUP BY
a.referrer_id
) opportunities
FULL OUTER JOIN (
SELECT
referrer_id AS referrer_id, SUM(b.buys) AS buys
FROM (
SELECT DISTINCT
first_value(v.ds) OVER (PARTITION BY buy_source.ds, buy_source.user_id ORDER BY v.ds DESC NULLS FIRST) AS ds
, first_value(v.user_id) OVER (PARTITION BY buy_source.ds, buy_source.user_id ORDER BY v.ds DESC NULLS FIRST) AS user_id
, first_value(v.referrer_id) OVER (PARTITION BY buy_source.ds, buy_source.user_id ORDER BY v.ds DESC NULLS FIRST) AS referrer_id
, buy_source.uuid
, 1 AS buys
FROM {{ source_schema }}.fct_visits v
INNER JOIN
(
SELECT *, {{ generate_random_uuid() }} AS uuid FROM {{ source_schema }}.fct_buys
) buy_source
ON
v.user_id = buy_source.user_id AND v.ds <= buy_source.ds AND v.ds > {{ render_date_sub("buy_source", "ds", 7, TimeGranularity.DAY) }}
) b
GROUP BY
b.referrer_id
) conversions
ON opportunities.referrer_id = conversions.referrer_id
---
integration_test:
name: conversion_rate_metric_with_multiple_dimension
description: Query a conversion metric that calculates the conversion rate with multiple dimension
model: SIMPLE_MODEL
metrics: ["visit_buy_conversion_rate"]
group_bys: ["metric_time", "visit__referrer_id"]
check_query: |
SELECT
opportunities.referrer_id AS visit__referrer_id
, opportunities.metric_time AS metric_time__day
, CAST(conversions.buys AS {{ double_data_type_name }}) / CAST(NULLIF(opportunities.visits, 0) AS {{ double_data_type_name }}) AS visit_buy_conversion_rate
FROM (
SELECT
metric_time, referrer_id, SUM(a.visits) AS visits
FROM (
SELECT
ds AS metric_time, referrer_id, 1 AS visits
FROM {{ source_schema }}.fct_visits visits
) a
GROUP BY
a.referrer_id, a.metric_time
) opportunities
FULL OUTER JOIN (
SELECT
b.ds AS metric_time, referrer_id AS referrer_id, SUM(b.buys) AS buys
FROM (
SELECT DISTINCT
first_value(v.ds) OVER (PARTITION BY buy_source.ds, buy_source.user_id ORDER BY v.ds DESC NULLS FIRST) AS ds
, first_value(v.user_id) OVER (PARTITION BY buy_source.ds, buy_source.user_id ORDER BY v.ds DESC NULLS FIRST) AS user_id
, first_value(v.referrer_id) OVER (PARTITION BY buy_source.ds, buy_source.user_id ORDER BY v.ds DESC NULLS FIRST) AS referrer_id
, buy_source.uuid
, 1 AS buys
FROM {{ source_schema }}.fct_visits v
INNER JOIN
(
SELECT *, {{ generate_random_uuid() }} AS uuid FROM {{ source_schema }}.fct_buys
) buy_source
ON
v.user_id = buy_source.user_id AND v.ds <= buy_source.ds AND v.ds > {{ render_date_sub("buy_source", "ds", 7, TimeGranularity.DAY) }}
) b
GROUP BY
b.referrer_id, b.ds
) conversions
ON opportunities.referrer_id = conversions.referrer_id AND opportunities.metric_time = conversions.metric_time
---
integration_test:
name: conversion_count_metric_with_multiple_dimension
description: Query a conversion metric that calculates the conversion count with multiple dimension
model: SIMPLE_MODEL
metrics: ["visit_buy_conversions"]
group_bys: ["metric_time", "visit__referrer_id"]
check_query: |
SELECT
opportunities.referrer_id AS visit__referrer_id
, opportunities.metric_time AS metric_time__day
, conversions.buys AS visit_buy_conversions
FROM (
SELECT
metric_time, referrer_id, SUM(a.visits) AS visits
FROM (
SELECT
ds AS metric_time, referrer_id, 1 AS visits
FROM {{ source_schema }}.fct_visits visits
) a
GROUP BY
a.referrer_id, a.metric_time
) opportunities
FULL OUTER JOIN (
SELECT
b.ds AS metric_time, referrer_id AS referrer_id, SUM(b.buys) AS buys
FROM (
SELECT DISTINCT
first_value(v.ds) OVER (PARTITION BY buy_source.ds, buy_source.user_id ORDER BY v.ds DESC NULLS FIRST) AS ds
, first_value(v.user_id) OVER (PARTITION BY buy_source.ds, buy_source.user_id ORDER BY v.ds DESC NULLS FIRST) AS user_id
, first_value(v.referrer_id) OVER (PARTITION BY buy_source.ds, buy_source.user_id ORDER BY v.ds DESC NULLS FIRST) AS referrer_id
, buy_source.uuid
, 1 AS buys
FROM {{ source_schema }}.fct_visits v
INNER JOIN
(
SELECT *, {{ generate_random_uuid() }} AS uuid FROM {{ source_schema }}.fct_buys
) buy_source
ON
v.user_id = buy_source.user_id AND v.ds <= buy_source.ds AND v.ds > {{ render_date_sub("buy_source", "ds", 7, TimeGranularity.DAY) }}
) b
GROUP BY
b.referrer_id, b.ds
) conversions
ON opportunities.referrer_id = conversions.referrer_id AND opportunities.metric_time = conversions.metric_time
---
integration_test:
name: conversion_rate_metric_with_constant_property
description: Query a conversion metric that calculates the conversion rate held by a constant property
model: SIMPLE_MODEL
metrics: ["visit_buy_conversion_rate_by_session"]
group_bys: ["metric_time"]
check_query: |
SELECT
opportunities.metric_time AS metric_time__day
, CAST(conversions.buys AS {{ double_data_type_name }}) / CAST(NULLIF(opportunities.visits, 0) AS {{ double_data_type_name }}) AS visit_buy_conversion_rate_by_session
FROM (
SELECT
metric_time, SUM(a.visits) AS visits
FROM (
SELECT
ds AS metric_time, 1 AS visits
FROM {{ source_schema }}.fct_visits visits
) a
GROUP BY
a.metric_time
) opportunities
FULL OUTER JOIN (
SELECT
b.ds AS metric_time, SUM(b.buys) AS buys
FROM (
SELECT DISTINCT
first_value(v.ds) OVER (PARTITION BY buy_source.ds, buy_source.user_id, buy_source.session_id ORDER BY v.ds DESC NULLS FIRST) AS ds
, first_value(v.user_id) OVER (PARTITION BY buy_source.ds, buy_source.user_id, buy_source.session_id ORDER BY v.ds DESC NULLS FIRST) AS user_id
, first_value(v.referrer_id) OVER (PARTITION BY buy_source.ds, buy_source.user_id, buy_source.session_id ORDER BY v.ds DESC NULLS FIRST) AS referrer_id
, buy_source.uuid
, 1 AS buys
FROM {{ source_schema }}.fct_visits v
INNER JOIN
(
SELECT *, {{ generate_random_uuid() }} AS uuid FROM {{ source_schema }}.fct_buys
) buy_source
ON
v.user_id = buy_source.user_id
AND v.ds <= buy_source.ds AND v.ds > {{ render_date_sub("buy_source", "ds", 7, TimeGranularity.DAY) }}
AND buy_source.session_id = v.session_id
) b
GROUP BY
b.ds
) conversions
ON opportunities.metric_time = conversions.metric_time
---
integration_test:
name: conversion_rate_metric_with_constant_property_multiple_dimensions
description: Query a conversion metric that calculates the conversion rate held by a constant property
model: SIMPLE_MODEL
metrics: ["visit_buy_conversion_rate_by_session"]
group_bys: ["metric_time", "visit__referrer_id"]
check_query: |
SELECT
opportunities.referrer_id AS visit__referrer_id
, opportunities.metric_time AS metric_time__day
, CAST(conversions.buys AS {{ double_data_type_name }}) / CAST(NULLIF(opportunities.visits, 0) AS {{ double_data_type_name }}) AS visit_buy_conversion_rate_by_session
FROM (
SELECT
metric_time, referrer_id, SUM(a.visits) AS visits
FROM (
SELECT
ds AS metric_time, referrer_id, 1 AS visits
FROM {{ source_schema }}.fct_visits visits
) a
GROUP BY
a.referrer_id, a.metric_time
) opportunities
FULL OUTER JOIN (
SELECT
b.ds AS metric_time, referrer_id AS referrer_id, SUM(b.buys) AS buys
FROM (
SELECT DISTINCT
first_value(v.ds) OVER (PARTITION BY buy_source.ds, buy_source.user_id, buy_source.session_id ORDER BY v.ds DESC NULLS FIRST) AS ds
, first_value(v.user_id) OVER (PARTITION BY buy_source.ds, buy_source.user_id, buy_source.session_id ORDER BY v.ds DESC NULLS FIRST) AS user_id
, first_value(v.referrer_id) OVER (PARTITION BY buy_source.ds, buy_source.user_id, buy_source.session_id ORDER BY v.ds DESC NULLS FIRST) AS referrer_id
, buy_source.uuid
, 1 AS buys
FROM {{ source_schema }}.fct_visits v
INNER JOIN
(
SELECT *, {{ generate_random_uuid() }} AS uuid FROM {{ source_schema }}.fct_buys
) buy_source
ON
v.user_id = buy_source.user_id
AND v.ds <= buy_source.ds AND v.ds > {{ render_date_sub("buy_source", "ds", 7, TimeGranularity.DAY) }}
AND buy_source.session_id = v.session_id
) b
GROUP BY
b.referrer_id, b.ds
) conversions
ON opportunities.referrer_id = conversions.referrer_id AND opportunities.metric_time = conversions.metric_time
8 changes: 8 additions & 0 deletions metricflow/test/integration/test_configured_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
SqlColumnReferenceExpression,
SqlDateTruncExpression,
SqlExtractExpression,
SqlGenerateUuidExpression,
SqlPercentileExpression,
SqlPercentileExpressionArgument,
SqlPercentileFunctionType,
Expand Down Expand Up @@ -172,6 +173,11 @@ def render_time_dimension_template(
f"{{{{ TimeDimension('{time_dimension_name}', '{time_granularity}', entity_path={repr(entity_path)}) }}}}"
)

def generate_random_uuid(self) -> str:
"""Returns the generate random UUID SQL function."""
expr = SqlGenerateUuidExpression()
return self._sql_client.sql_query_plan_renderer.expr_renderer.render_sql_expr(expr).sql


def filter_not_supported_features(
sql_client: SqlClient, required_features: Tuple[RequiredDwEngineFeatures, ...]
Expand Down Expand Up @@ -295,6 +301,7 @@ def test_case(
render_dimension_template=check_query_helpers.render_dimension_template,
render_entity_template=check_query_helpers.render_entity_template,
render_time_dimension_template=check_query_helpers.render_time_dimension_template,
generate_random_uuid=check_query_helpers.generate_random_uuid,
)
if case.where_filter
else None,
Expand All @@ -319,6 +326,7 @@ def test_case(
render_percentile_expr=check_query_helpers.render_percentile_expr,
mf_time_spine_source=semantic_manifest_lookup.time_spine_source.spine_table.sql,
double_data_type_name=check_query_helpers.double_data_type_name,
generate_random_uuid=check_query_helpers.generate_random_uuid,
)
)
# If we sort, it's effectively not checking the order whatever order that the output was would be overwritten.
Expand Down
2 changes: 1 addition & 1 deletion metricflow/test/model/test_semantic_model_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def test_local_linked_elements_for_metric( # noqa: D
def test_get_semantic_models_for_entity(semantic_model_lookup: SemanticModelLookup) -> None: # noqa: D
entity_reference = EntityReference(element_name="user")
linked_semantic_models = semantic_model_lookup.get_semantic_models_for_entity(entity_reference=entity_reference)
assert len(linked_semantic_models) == 8
assert len(linked_semantic_models) == 10


def test_linkable_set( # noqa: D
Expand Down
31 changes: 31 additions & 0 deletions metricflow/test/plan_conversion/test_dataflow_to_sql_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,37 @@ def test_compute_metrics_node_ratio_from_multiple_semantic_models(
)


@pytest.mark.sql_engine_snapshot
def test_conversion_metric(
request: FixtureRequest,
mf_test_session_state: MetricFlowTestSessionState,
dataflow_plan_builder: DataflowPlanBuilder,
dataflow_to_sql_converter: DataflowToSqlQueryPlanConverter,
sql_client: SqlClient,
) -> None:
"""Test conversion metric data flow plan rendering."""
dimension_spec = DimensionSpec(
element_name="referrer_id",
entity_links=(EntityReference(element_name="visit"),),
)
metric_spec = MetricSpec(element_name="visit_buy_conversion_rate")

dataflow_plan = dataflow_plan_builder.build_plan(
query_spec=MetricFlowQuerySpec(
metric_specs=(metric_spec,),
dimension_specs=(dimension_spec,),
),
)

convert_and_check(
request=request,
mf_test_session_state=mf_test_session_state,
dataflow_to_sql_converter=dataflow_to_sql_converter,
sql_client=sql_client,
node=dataflow_plan.sink_output_nodes[0].parent_node,
)


@pytest.mark.sql_engine_snapshot
def test_combine_output_node( # noqa: D
request: FixtureRequest,
Expand Down
Loading

0 comments on commit 408689b

Please sign in to comment.