From 43468b26a1caf220d6f022a1a9c364ae64ab12b5 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Wed, 30 Oct 2024 16:11:37 -0700 Subject: [PATCH] Add test for synthetic manifest generator. --- .../performance/test_manifest_generator.py | 53 ++++++ .../test_manifest_generator__result.txt | 155 ++++++++++++++++++ 2 files changed, 208 insertions(+) create mode 100644 tests_metricflow/performance/test_manifest_generator.py create mode 100644 tests_metricflow/snapshots/test_manifest_generator.py/PydanticSemanticManifest/test_manifest_generator__result.txt diff --git a/tests_metricflow/performance/test_manifest_generator.py b/tests_metricflow/performance/test_manifest_generator.py new file mode 100644 index 000000000..098dd7f9c --- /dev/null +++ b/tests_metricflow/performance/test_manifest_generator.py @@ -0,0 +1,53 @@ +from __future__ import annotations + +import logging + +from _pytest.fixtures import FixtureRequest +from dbt_semantic_interfaces.implementations.semantic_manifest import PydanticSemanticManifest +from dbt_semantic_interfaces.transformations.semantic_manifest_transformer import PydanticSemanticManifestTransformer +from dbt_semantic_interfaces.validations.semantic_manifest_validator import SemanticManifestValidator +from metricflow_semantics.mf_logging.lazy_formattable import LazyFormat +from metricflow_semantics.test_helpers.config_helpers import MetricFlowTestConfiguration +from metricflow_semantics.test_helpers.snapshot_helpers import assert_object_snapshot_equal + +from tests_metricflow.performance.semantic_manifest_generator import SyntheticManifestGenerator +from tests_metricflow.performance.synthetic_manifest_parameter_set import SyntheticManifestParameterSet + +logger = logging.getLogger(__name__) + + +def test_manifest_generator( # noqa: D103 + request: FixtureRequest, + mf_test_configuration: MetricFlowTestConfiguration, +) -> None: + parameter_set = SyntheticManifestParameterSet( + measure_semantic_model_count=2, + measures_per_semantic_model=2, + dimension_semantic_model_count=2, + categorical_dimensions_per_semantic_model=2, + max_metric_depth=2, + max_metric_width=2, + saved_query_count=2, + metrics_per_saved_query=2, + categorical_dimensions_per_saved_query=2, + ) + generator = SyntheticManifestGenerator(parameter_set) + manifest = generator.generate_manifest() + assert_object_snapshot_equal( + request=request, + mf_test_configuration=mf_test_configuration, + obj=manifest, + ) + + manifest = PydanticSemanticManifestTransformer.transform(manifest) + validator = SemanticManifestValidator[PydanticSemanticManifest]() + validation_result = validator.validate_semantic_manifest(manifest) + logger.debug(LazyFormat("Generated manifest", manifest=manifest)) + + assert not validation_result.has_blocking_issues, str( + LazyFormat( + "Found validation issues with the generated manifest", + validation_result=validation_result, + manifest=manifest, + ) + ) diff --git a/tests_metricflow/snapshots/test_manifest_generator.py/PydanticSemanticManifest/test_manifest_generator__result.txt b/tests_metricflow/snapshots/test_manifest_generator.py/PydanticSemanticManifest/test_manifest_generator__result.txt new file mode 100644 index 000000000..2f38bd7f6 --- /dev/null +++ b/tests_metricflow/snapshots/test_manifest_generator.py/PydanticSemanticManifest/test_manifest_generator__result.txt @@ -0,0 +1,155 @@ +PydanticSemanticManifest( + semantic_models=[ + PydanticSemanticModel( + name='measure_model_000', + node_relation=PydanticNodeRelation( + alias='measure_model_000', + schema_name='demo', + relation_name='demo.measure_model_000', + ), + entities=[ + PydanticEntity(name='measure_model_000_primary_entity', type=PRIMARY), + PydanticEntity(name='common_entity', type=UNIQUE), + ], + measures=[ + PydanticMeasure(name='measure_000', agg=SUM, agg_time_dimension='ds'), + PydanticMeasure(name='measure_001', agg=SUM, agg_time_dimension='ds'), + ], + dimensions=[ + PydanticDimension( + name='ds', + type=TIME, + is_partition=False, + type_params=PydanticDimensionTypeParams(time_granularity=DAY), + ), + ], + ), + PydanticSemanticModel( + name='measure_model_001', + node_relation=PydanticNodeRelation( + alias='measure_model_001', + schema_name='demo', + relation_name='demo.measure_model_001', + ), + entities=[ + PydanticEntity(name='measure_model_001_primary_entity', type=PRIMARY), + PydanticEntity(name='common_entity', type=UNIQUE), + ], + measures=[ + PydanticMeasure(name='measure_002', agg=SUM, agg_time_dimension='ds'), + PydanticMeasure(name='measure_003', agg=SUM, agg_time_dimension='ds'), + ], + dimensions=[ + PydanticDimension( + name='ds', + type=TIME, + is_partition=False, + type_params=PydanticDimensionTypeParams(time_granularity=DAY), + ), + ], + ), + PydanticSemanticModel( + name='dimension_model_000', + node_relation=PydanticNodeRelation( + alias='dimension_model_000', + schema_name='demo', + relation_name='demo.dimension_model_000', + ), + entities=[ + PydanticEntity(name='dimension_model_000_primary_entity', type=PRIMARY), + PydanticEntity(name='common_entity', type=UNIQUE), + ], + dimensions=[ + PydanticDimension(name='dimension_000', type=CATEGORICAL, is_partition=False), + PydanticDimension(name='dimension_001', type=CATEGORICAL, is_partition=False), + ], + ), + PydanticSemanticModel( + name='dimension_model_001', + node_relation=PydanticNodeRelation( + alias='dimension_model_001', + schema_name='demo', + relation_name='demo.dimension_model_001', + ), + entities=[ + PydanticEntity(name='dimension_model_001_primary_entity', type=PRIMARY), + PydanticEntity(name='common_entity', type=UNIQUE), + ], + dimensions=[ + PydanticDimension(name='dimension_002', type=CATEGORICAL, is_partition=False), + PydanticDimension(name='dimension_003', type=CATEGORICAL, is_partition=False), + ], + ), + ], + metrics=[ + PydanticMetric( + name='metric_0_000', + type=SIMPLE, + type_params=PydanticMetricTypeParams( + measure=PydanticMetricInputMeasure(name='measure_000', join_to_timespine=False), + ), + ), + PydanticMetric( + name='metric_0_001', + type=SIMPLE, + type_params=PydanticMetricTypeParams( + measure=PydanticMetricInputMeasure(name='measure_001', join_to_timespine=False), + ), + ), + PydanticMetric( + name='metric_1_000', + type=DERIVED, + type_params=PydanticMetricTypeParams( + expr='metric_0_000 + metric_0_001', + metrics=[PydanticMetricInput(name='metric_0_000'), PydanticMetricInput(name='metric_0_001')], + ), + ), + PydanticMetric( + name='metric_1_001', + type=DERIVED, + type_params=PydanticMetricTypeParams( + expr='metric_0_000 + metric_0_001', + metrics=[PydanticMetricInput(name='metric_0_000'), PydanticMetricInput(name='metric_0_001')], + ), + ), + ], + project_configuration=PydanticProjectConfiguration( + dsi_package_version=PydanticSemanticVersion( + major_version='0', + minor_version='7', + patch_version='2', + ), + time_spines=[ + PydanticTimeSpine( + node_relation=PydanticNodeRelation( + alias='time_spine_source_table', + schema_name='demo', + relation_name='demo.time_spine_source_table', + ), + primary_column=PydanticTimeSpinePrimaryColumn(name='ds', time_granularity=DAY), + ), + ], + ), + saved_queries=[ + PydanticSavedQuery( + name='saved_query_000', + query_params=PydanticSavedQueryQueryParams( + metrics=['metric_1_000', 'metric_1_001'], + group_by=[ + "Dimension('common_entity__dimension_000')", + "Dimension('common_entity__dimension_001')", + ], + ), + ), + PydanticSavedQuery( + name='saved_query_001', + query_params=PydanticSavedQueryQueryParams( + metrics=['metric_1_000', 'metric_1_001'], + group_by=[ + "Dimension('common_entity__dimension_002')", + "Dimension('common_entity__dimension_003')", + ], + ), + ), + ], +)