From 385a6c82dbb1acda8fa6910e3dc39974f6dcb679 Mon Sep 17 00:00:00 2001 From: Paul Yang Date: Sun, 5 May 2024 10:46:13 -0700 Subject: [PATCH] Update test fixtures to load manifests using paths from anchors. --- .../test_helpers/manifest_helpers.py | 26 +++---- .../fixtures/manifest_fixtures.py | 31 ++++++-- .../fixtures/manifest_fixtures.py | 78 +++++++++++++++---- 3 files changed, 94 insertions(+), 41 deletions(-) diff --git a/metricflow-semantics/metricflow_semantics/test_helpers/manifest_helpers.py b/metricflow-semantics/metricflow_semantics/test_helpers/manifest_helpers.py index f7e3a8ae13..a46b77dd31 100644 --- a/metricflow-semantics/metricflow_semantics/test_helpers/manifest_helpers.py +++ b/metricflow-semantics/metricflow_semantics/test_helpers/manifest_helpers.py @@ -1,34 +1,26 @@ from __future__ import annotations +import pathlib from typing import Dict, Optional from dbt_semantic_interfaces.implementations.semantic_manifest import PydanticSemanticManifest from dbt_semantic_interfaces.parsing.dir_to_model import ( - SemanticManifestBuildResult, parse_directory_of_yaml_files_to_semantic_manifest, ) from dbt_semantic_interfaces.validations.semantic_manifest_validator import SemanticManifestValidator -from metricflow_semantics.test_helpers.semantic_manifest_yamls import SEMANTIC_MANIFEST_YAMLS_PATH_ANCHOR - def load_semantic_manifest( - relative_manifest_path: str, + yaml_file_directory: pathlib.Path, template_mapping: Optional[Dict[str, str]] = None, -) -> SemanticManifestBuildResult: +) -> PydanticSemanticManifest: """Reads the manifest YAMLs from the standard location, applies transformations, runs validations.""" - yaml_file_directory = SEMANTIC_MANIFEST_YAMLS_PATH_ANCHOR.directory.joinpath(relative_manifest_path) - build_result = parse_directory_of_yaml_files_to_semantic_manifest( - str(yaml_file_directory), template_mapping=template_mapping - ) - validator = SemanticManifestValidator[PydanticSemanticManifest]() - validator.checked_validations(build_result.semantic_manifest) - return build_result - - -def load_named_manifest(template_mapping: Dict[str, str], manifest_name: str) -> PydanticSemanticManifest: # noqa: D103 try: - build_result = load_semantic_manifest(manifest_name, template_mapping) + build_result = parse_directory_of_yaml_files_to_semantic_manifest( + str(yaml_file_directory), template_mapping=template_mapping + ) + validator = SemanticManifestValidator[PydanticSemanticManifest]() + validator.checked_validations(build_result.semantic_manifest) return build_result.semantic_manifest except Exception as e: - raise RuntimeError(f"Error while loading semantic manifest: {manifest_name}") from e + raise RuntimeError(f"Error while loading semantic manifest: {yaml_file_directory}") from e diff --git a/metricflow-semantics/tests_metricflow_semantics/fixtures/manifest_fixtures.py b/metricflow-semantics/tests_metricflow_semantics/fixtures/manifest_fixtures.py index de5d31cd3d..16db98d843 100644 --- a/metricflow-semantics/tests_metricflow_semantics/fixtures/manifest_fixtures.py +++ b/metricflow-semantics/tests_metricflow_semantics/fixtures/manifest_fixtures.py @@ -9,7 +9,22 @@ from metricflow_semantics.specs.column_assoc import ColumnAssociationResolver from metricflow_semantics.specs.dunder_column_association_resolver import DunderColumnAssociationResolver from metricflow_semantics.test_helpers.config_helpers import MetricFlowTestConfiguration -from metricflow_semantics.test_helpers.manifest_helpers import load_named_manifest +from metricflow_semantics.test_helpers.manifest_helpers import load_semantic_manifest +from metricflow_semantics.test_helpers.semantic_manifest_yamls.ambiguous_resolution_manifest import ( + AMBIGUOUS_RESOLUTION_MANIFEST_ANCHOR, +) +from metricflow_semantics.test_helpers.semantic_manifest_yamls.cyclic_join_manifest import CYCLIC_JOIN_MANIFEST_ANCHOR +from metricflow_semantics.test_helpers.semantic_manifest_yamls.multi_hop_join_manifest import ( + MULTI_HOP_JOIN_MANIFEST_ANCHOR, +) +from metricflow_semantics.test_helpers.semantic_manifest_yamls.partitioned_multi_hop_join_manifest import ( + PARTITIONED_MULTI_HOP_JOIN_MANIFEST_ANCHOR, +) +from metricflow_semantics.test_helpers.semantic_manifest_yamls.scd_manifest import SCD_MANIFEST_ANCHOR +from metricflow_semantics.test_helpers.semantic_manifest_yamls.simple_manifest import SIMPLE_MANIFEST_ANCHOR +from metricflow_semantics.test_helpers.semantic_manifest_yamls.simple_multi_hop_join_manifest import ( + SIMPLE_MULTI_HOP_JOIN_MANIFEST_ANCHOR, +) logger = logging.getLogger(__name__) @@ -23,7 +38,7 @@ def template_mapping(mf_test_configuration: MetricFlowTestConfiguration) -> Dict @pytest.fixture(scope="session") def simple_semantic_manifest(template_mapping: Dict[str, str]) -> PydanticSemanticManifest: """Manifest used for many tests.""" - return load_named_manifest(template_mapping, "simple_manifest") + return load_semantic_manifest(SIMPLE_MANIFEST_ANCHOR.directory, template_mapping) @pytest.fixture(scope="session") @@ -36,7 +51,7 @@ def simple_semantic_manifest_lookup( # noqa: D103 @pytest.fixture(scope="session") def multi_hop_join_manifest(template_mapping: Dict[str, str]) -> PydanticSemanticManifest: """Manifest used for many tests.""" - return load_named_manifest(template_mapping, "multi_hop_join_manifest") + return load_semantic_manifest(MULTI_HOP_JOIN_MANIFEST_ANCHOR.directory, template_mapping) @pytest.fixture(scope="session") @@ -49,7 +64,7 @@ def multi_hop_join_manifest_lookup( # noqa: D103 @pytest.fixture(scope="session") def simple_multi_hop_join_manifest(template_mapping: Dict[str, str]) -> PydanticSemanticManifest: """Manifest used for many tests.""" - return load_named_manifest(template_mapping, "simple_multi_hop_join_manifest") + return load_semantic_manifest(SIMPLE_MULTI_HOP_JOIN_MANIFEST_ANCHOR.directory, template_mapping) @pytest.fixture(scope="session") @@ -63,7 +78,7 @@ def simple_multi_hop_join_manifest_lookup( # noqa: D103 def partitioned_multi_hop_join_semantic_manifest( # noqa: D103 template_mapping: Dict[str, str] ) -> PydanticSemanticManifest: - return load_named_manifest(template_mapping, "partitioned_multi_hop_join_manifest") + return load_semantic_manifest(PARTITIONED_MULTI_HOP_JOIN_MANIFEST_ANCHOR.directory, template_mapping) @pytest.fixture(scope="session") @@ -75,7 +90,7 @@ def partitioned_multi_hop_join_semantic_manifest_lookup( # noqa: D103 @pytest.fixture(scope="session") def scd_semantic_manifest(template_mapping: Dict[str, str]) -> PydanticSemanticManifest: # noqa: D103 - return load_named_manifest(template_mapping, "scd_manifest") + return load_semantic_manifest(SCD_MANIFEST_ANCHOR.directory, template_mapping) @pytest.fixture(scope="session") @@ -87,7 +102,7 @@ def scd_semantic_manifest_lookup( # noqa: D103 @pytest.fixture(scope="session") def ambiguous_resolution_manifest(template_mapping: Dict[str, str]) -> PydanticSemanticManifest: # noqa: D103 - return load_named_manifest(template_mapping, "ambiguous_resolution_manifest") + return load_semantic_manifest(AMBIGUOUS_RESOLUTION_MANIFEST_ANCHOR.directory, template_mapping) @pytest.fixture(scope="session") @@ -99,7 +114,7 @@ def ambiguous_resolution_manifest_lookup( # noqa: D103 @pytest.fixture(scope="session") def cyclic_join_manifest(template_mapping: Dict[str, str]) -> PydanticSemanticManifest: # noqa: D103 - return load_named_manifest(template_mapping, "cyclic_join_manifest") + return load_semantic_manifest(CYCLIC_JOIN_MANIFEST_ANCHOR.directory, template_mapping) @pytest.fixture(scope="session") diff --git a/tests_metricflow/fixtures/manifest_fixtures.py b/tests_metricflow/fixtures/manifest_fixtures.py index 5ec01388b8..6ab1061a42 100644 --- a/tests_metricflow/fixtures/manifest_fixtures.py +++ b/tests_metricflow/fixtures/manifest_fixtures.py @@ -1,6 +1,7 @@ from __future__ import annotations import logging +import pathlib from collections import OrderedDict from dataclasses import dataclass from enum import Enum @@ -17,6 +18,29 @@ from metricflow_semantics.test_helpers.config_helpers import MetricFlowTestConfiguration from metricflow_semantics.test_helpers.id_helpers import IdNumberSpace, patch_id_generators_helper from metricflow_semantics.test_helpers.manifest_helpers import load_semantic_manifest +from metricflow_semantics.test_helpers.semantic_manifest_yamls.ambiguous_resolution_manifest import ( + AMBIGUOUS_RESOLUTION_MANIFEST_ANCHOR, +) +from metricflow_semantics.test_helpers.semantic_manifest_yamls.cyclic_join_manifest import CYCLIC_JOIN_MANIFEST_ANCHOR +from metricflow_semantics.test_helpers.semantic_manifest_yamls.data_warehouse_validation_manifest import ( + DW_VALIDATION_MANIFEST_ANCHOR, +) +from metricflow_semantics.test_helpers.semantic_manifest_yamls.extended_date_manifest import ( + EXTENDED_DATE_MANIFEST_ANCHOR, +) +from metricflow_semantics.test_helpers.semantic_manifest_yamls.join_types_manifest import JOIN_TYPES_MANIFEST_ANCHOR +from metricflow_semantics.test_helpers.semantic_manifest_yamls.multi_hop_join_manifest import ( + MULTI_HOP_JOIN_MANIFEST_ANCHOR, +) +from metricflow_semantics.test_helpers.semantic_manifest_yamls.non_sm_manifest import NON_SM_MANIFEST_ANCHOR +from metricflow_semantics.test_helpers.semantic_manifest_yamls.partitioned_multi_hop_join_manifest import ( + PARTITIONED_MULTI_HOP_JOIN_MANIFEST_ANCHOR, +) +from metricflow_semantics.test_helpers.semantic_manifest_yamls.scd_manifest import SCD_MANIFEST_ANCHOR +from metricflow_semantics.test_helpers.semantic_manifest_yamls.simple_manifest import SIMPLE_MANIFEST_ANCHOR +from metricflow_semantics.test_helpers.semantic_manifest_yamls.simple_multi_hop_join_manifest import ( + SIMPLE_MULTI_HOP_JOIN_MANIFEST_ANCHOR, +) from metricflow_semantics.test_helpers.time_helpers import ConfigurableTimeSource from metricflow.dataflow.builder.dataflow_plan_builder import DataflowPlanBuilder @@ -42,6 +66,8 @@ class SemanticManifestSetupPropertySet: # is modified. i.e. without this, modifying the first semantic manifest might cause all IDs in snapshots associated # with semantic manifests following the first one to change. id_number_space: IdNumberSpace + # Where the YAML files are located. + yaml_file_dir: pathlib.Path class SemanticManifestSetup(Enum): @@ -50,37 +76,58 @@ class SemanticManifestSetup(Enum): AMBIGUOUS_RESOLUTION_MANIFEST = SemanticManifestSetupPropertySet( semantic_manifest_name="ambiguous_resolution_manifest", id_number_space=IdNumberSpace.for_block(0), + yaml_file_dir=AMBIGUOUS_RESOLUTION_MANIFEST_ANCHOR.directory, ) # Not including CONFIG_LINTER_MANIFEST as it has intentional errors for running validations. CYCLIC_JOIN_MANIFEST = SemanticManifestSetupPropertySet( - semantic_manifest_name="cyclic_join_manifest", id_number_space=IdNumberSpace.for_block(1) + semantic_manifest_name="cyclic_join_manifest", + id_number_space=IdNumberSpace.for_block(1), + yaml_file_dir=CYCLIC_JOIN_MANIFEST_ANCHOR.directory, ) DATA_WAREHOUSE_VALIDATION_MANIFEST = SemanticManifestSetupPropertySet( - semantic_manifest_name="data_warehouse_validation_manifest", id_number_space=IdNumberSpace.for_block(2) + semantic_manifest_name="data_warehouse_validation_manifest", + id_number_space=IdNumberSpace.for_block(2), + yaml_file_dir=DW_VALIDATION_MANIFEST_ANCHOR.directory, ) EXTENDED_DATE_MANIFEST = SemanticManifestSetupPropertySet( - semantic_manifest_name="extended_date_manifest", id_number_space=IdNumberSpace.for_block(3) + semantic_manifest_name="extended_date_manifest", + id_number_space=IdNumberSpace.for_block(3), + yaml_file_dir=EXTENDED_DATE_MANIFEST_ANCHOR.directory, ) JOIN_TYPES_MANIFEST = SemanticManifestSetupPropertySet( - semantic_manifest_name="join_types_manifest", id_number_space=IdNumberSpace.for_block(4) + semantic_manifest_name="join_types_manifest", + id_number_space=IdNumberSpace.for_block(4), + yaml_file_dir=JOIN_TYPES_MANIFEST_ANCHOR.directory, ) MULTI_HOP_JOIN_MANIFEST = SemanticManifestSetupPropertySet( - semantic_manifest_name="multi_hop_join_manifest", id_number_space=IdNumberSpace.for_block(5) + semantic_manifest_name="multi_hop_join_manifest", + id_number_space=IdNumberSpace.for_block(5), + yaml_file_dir=MULTI_HOP_JOIN_MANIFEST_ANCHOR.directory, ) PARTITIONED_MULTI_HOP_JOIN_MANIFEST = SemanticManifestSetupPropertySet( - semantic_manifest_name="partitioned_multi_hop_join_manifest", id_number_space=IdNumberSpace.for_block(6) + semantic_manifest_name="partitioned_multi_hop_join_manifest", + id_number_space=IdNumberSpace.for_block(6), + yaml_file_dir=PARTITIONED_MULTI_HOP_JOIN_MANIFEST_ANCHOR.directory, ) NON_SM_MANIFEST = SemanticManifestSetupPropertySet( - semantic_manifest_name="non_sm_manifest", id_number_space=IdNumberSpace.for_block(7) + semantic_manifest_name="non_sm_manifest", + id_number_space=IdNumberSpace.for_block(7), + yaml_file_dir=NON_SM_MANIFEST_ANCHOR.directory, ) SCD_MANIFEST = SemanticManifestSetupPropertySet( - semantic_manifest_name="scd_manifest", id_number_space=IdNumberSpace.for_block(8) + semantic_manifest_name="scd_manifest", + id_number_space=IdNumberSpace.for_block(8), + yaml_file_dir=SCD_MANIFEST_ANCHOR.directory, ) SIMPLE_MANIFEST = SemanticManifestSetupPropertySet( - semantic_manifest_name="simple_manifest", id_number_space=IdNumberSpace.for_block(9) + semantic_manifest_name="simple_manifest", + id_number_space=IdNumberSpace.for_block(9), + yaml_file_dir=SIMPLE_MANIFEST_ANCHOR.directory, ) SIMPLE_MULTI_HOP_JOIN_MANIFEST = SemanticManifestSetupPropertySet( - semantic_manifest_name="simple_multi_hop_join_manifest", id_number_space=IdNumberSpace.for_block(10) + semantic_manifest_name="simple_multi_hop_join_manifest", + id_number_space=IdNumberSpace.for_block(10), + yaml_file_dir=SIMPLE_MULTI_HOP_JOIN_MANIFEST_ANCHOR.directory, ) @property @@ -91,6 +138,10 @@ def id_number_space(self) -> IdNumberSpace: # noqa: D102 def semantic_manifest_name(self) -> str: # noqa: D102 return self.value.semantic_manifest_name + @property + def yaml_file_dir(self) -> pathlib.Path: # noqa: D102 + return self.value.yaml_file_dir + @dataclass(frozen=True) class MetricFlowEngineTestFixture: @@ -211,13 +262,8 @@ def mf_engine_test_fixture_mapping( fixture_mapping: Dict[SemanticManifestSetup, MetricFlowEngineTestFixture] = {} for semantic_manifest_setup in SemanticManifestSetup: with patch_id_generators_helper(semantic_manifest_setup.id_number_space.start_value): - try: - build_result = load_semantic_manifest(semantic_manifest_setup.semantic_manifest_name, template_mapping) - except Exception as e: - raise RuntimeError(f"Error while loading semantic manifest: {semantic_manifest_setup}") from e - fixture_mapping[semantic_manifest_setup] = MetricFlowEngineTestFixture.from_parameters( - sql_client, build_result.semantic_manifest + sql_client, load_semantic_manifest(semantic_manifest_setup.yaml_file_dir, template_mapping) ) return fixture_mapping