Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate Semantic Manifests Used in Tests #777

Merged
merged 4 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
357 changes: 11 additions & 346 deletions metricflow/test/dataset/test_convert_semantic_model.py

Large diffs are not rendered by default.

73 changes: 27 additions & 46 deletions metricflow/test/fixtures/model_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import os
from collections import OrderedDict
from dataclasses import dataclass
from typing import Dict, List, Sequence
from typing import Dict, List, Optional, Sequence

import pytest
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,
parse_yaml_files_to_validation_ready_semantic_manifest,
)
Expand Down Expand Up @@ -148,6 +150,20 @@ def create_data_sets(
return data_sets


def load_semantic_manifest(
relative_manifest_path: str,
template_mapping: Optional[Dict[str, str]] = None,
) -> SemanticManifestBuildResult:
"""Reads the manifest YAMLs from the standard location, applies transformations, runs validations."""
yaml_file_directory = os.path.join(os.path.dirname(__file__), f"semantic_manifest_yamls/{relative_manifest_path}")
build_result = parse_directory_of_yaml_files_to_semantic_manifest(
yaml_file_directory, template_mapping=template_mapping
)
validator = SemanticManifestValidator[PydanticSemanticManifest]()
validator.checked_validations(build_result.semantic_manifest)
return build_result


@pytest.fixture(scope="session")
def template_mapping(mf_test_session_state: MetricFlowTestSessionState) -> Dict[str, str]:
"""Mapping for template variables in the model YAML files."""
Expand All @@ -156,64 +172,41 @@ def template_mapping(mf_test_session_state: MetricFlowTestSessionState) -> Dict[

@pytest.fixture(scope="session")
def simple_semantic_manifest_lookup_non_ds(template_mapping: Dict[str, str]) -> SemanticManifestLookup: # noqa: D
build_result = parse_directory_of_yaml_files_to_semantic_manifest(
os.path.join(os.path.dirname(__file__), "semantic_manifest_yamls/non_sm_manifest"),
template_mapping=template_mapping,
)
build_result = load_semantic_manifest("non_sm_manifest", template_mapping)
return SemanticManifestLookup(build_result.semantic_manifest)


@pytest.fixture(scope="session")
def simple_semantic_manifest_lookup(template_mapping: Dict[str, str]) -> SemanticManifestLookup: # noqa: D
build_result = parse_directory_of_yaml_files_to_semantic_manifest(
os.path.join(os.path.dirname(__file__), "semantic_manifest_yamls/simple_manifest"),
template_mapping=template_mapping,
)
build_result = load_semantic_manifest("simple_manifest", template_mapping)
return SemanticManifestLookup(build_result.semantic_manifest)


@pytest.fixture(scope="session")
def multi_hop_join_semantic_manifest_lookup(template_mapping: Dict[str, str]) -> SemanticManifestLookup: # noqa: D
build_result = parse_directory_of_yaml_files_to_semantic_manifest(
os.path.join(
os.path.dirname(__file__), "semantic_manifest_yamls/multi_hop_join_manifest/partitioned_semantic_models"
),
template_mapping=template_mapping,
)
build_result = load_semantic_manifest("multi_hop_join_manifest/partitioned_semantic_models", template_mapping)
return SemanticManifestLookup(build_result.semantic_manifest)


@pytest.fixture(scope="session")
def unpartitioned_multi_hop_join_semantic_manifest_lookup( # noqa: D
template_mapping: Dict[str, str]
) -> SemanticManifestLookup:
build_result = parse_directory_of_yaml_files_to_semantic_manifest(
os.path.join(
os.path.dirname(__file__), "semantic_manifest_yamls/multi_hop_join_manifest/unpartitioned_semantic_models"
),
template_mapping=template_mapping,
)
build_result = load_semantic_manifest("multi_hop_join_manifest/unpartitioned_semantic_models", template_mapping)
return SemanticManifestLookup(build_result.semantic_manifest)


@pytest.fixture(scope="session")
def simple_semantic_manifest(template_mapping: Dict[str, str]) -> SemanticManifest:
"""Model used for many tests."""
build_result = parse_directory_of_yaml_files_to_semantic_manifest(
os.path.join(os.path.dirname(__file__), "semantic_manifest_yamls/simple_manifest"),
template_mapping=template_mapping,
)
build_result = load_semantic_manifest("simple_manifest", template_mapping)
return build_result.semantic_manifest


@pytest.fixture(scope="session")
def simple_model__with_primary_transforms(template_mapping: Dict[str, str]) -> SemanticManifest:
"""Model used for tests pre-transformations."""
build_result = parse_directory_of_yaml_files_to_semantic_manifest(
os.path.join(os.path.dirname(__file__), "semantic_manifest_yamls/simple_manifest"),
template_mapping=template_mapping,
apply_transformations=False,
)
build_result = load_semantic_manifest("simple_manifest", template_mapping)
transformed_model = PydanticSemanticManifestTransformer().transform(
model=build_result.semantic_manifest,
ordered_rule_sequences=(PydanticSemanticManifestTransformRuleSet().primary_rules,),
Expand All @@ -223,38 +216,26 @@ def simple_model__with_primary_transforms(template_mapping: Dict[str, str]) -> S

@pytest.fixture(scope="session")
def extended_date_semantic_manifest_lookup(template_mapping: Dict[str, str]) -> SemanticManifestLookup: # noqa: D
build_result = parse_directory_of_yaml_files_to_semantic_manifest(
os.path.join(os.path.dirname(__file__), "semantic_manifest_yamls/extended_date_manifest"),
template_mapping=template_mapping,
)
build_result = load_semantic_manifest("extended_date_manifest", template_mapping)
return SemanticManifestLookup(build_result.semantic_manifest)


@pytest.fixture(scope="session")
def scd_semantic_manifest_lookup(template_mapping: Dict[str, str]) -> SemanticManifestLookup:
"""Initialize semantic model for SCD tests."""
build_result = parse_directory_of_yaml_files_to_semantic_manifest(
os.path.join(os.path.dirname(__file__), "semantic_manifest_yamls/scd_manifest"),
template_mapping=template_mapping,
)
build_result = load_semantic_manifest("scd_manifest", template_mapping)
return SemanticManifestLookup(build_result.semantic_manifest)


@pytest.fixture(scope="session")
def data_warehouse_validation_model(template_mapping: Dict[str, str]) -> SemanticManifest:
"""Model used for data warehouse validation tests."""
build_result = parse_directory_of_yaml_files_to_semantic_manifest(
os.path.join(os.path.dirname(__file__), "semantic_manifest_yamls/data_warehouse_validation_manifest"),
template_mapping=template_mapping,
)
build_result = load_semantic_manifest("data_warehouse_validation_manifest", template_mapping)
return build_result.semantic_manifest


@pytest.fixture(scope="session")
def cyclic_join_semantic_manifest_lookup(template_mapping: Dict[str, str]) -> SemanticManifestLookup:
"""Manifest that contains a potential cycle in the join graph (if not handled properly)."""
build_result = parse_directory_of_yaml_files_to_semantic_manifest(
os.path.join(os.path.dirname(__file__), "semantic_manifest_yamls/cyclic_join_manifest"),
template_mapping=template_mapping,
)
build_result = load_semantic_manifest("cyclic_join_manifest", template_mapping)
return SemanticManifestLookup(build_result.semantic_manifest)

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,23 @@ semantic_model:
alias: fct_bookings_extended_monthly

defaults:
agg_time_dimension: ds
agg_time_dimension: monthly_ds

measures:
- name: bookings_monthly
agg: sum
create_metric: true

primary_entity: booking_id
primary_entity: booking

dimensions:
- name: ds
- name: monthly_ds
expr: ds
type: time
type_params:
time_granularity: month
- name: is_instant
type: categorical

entities:
- name: listing
expr: listing_id
type: foreign
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ semantic_model:
type: time
type_params:
time_granularity: day
- name: is_instant
type: categorical

entities:
- name: booking_id
- name: booking
expr: booking_id
type: primary
- name: listing_id
- name: listing
expr: listing_id
type: foreign
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ semantic_model:
alias: dim_listings_extended

dimensions:
- name: listing_creation_ds
- name: ds
expr: listing_creation_ds
type: time
type_params:
time_granularity: day

entities:
- name: listing_id
- name: listing
expr: listing_id
type: primary
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ semantic_model:
time_granularity: day
is_partition: true

primary_entity: bridge_account

entities:
- name: account_id
type: primary
type: unique
- name: customer_id
type: foreign
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ semantic_model:
- name: account_type
type: categorical

primary_entity: scd_user

entities:
- name: user
type: natural
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ semantic_model:
alias: dim_users_latest

dimensions:
- name: ds
- name: ds_latest
type: time
expr: ds
type_params:
time_granularity: day
- name: home_state_latest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ table_snapshot:
- name: listing_creation_ds
type: TIME
- name: listing_id
type: INT
type: STRING
rows:
- ["2020-01-01", "0"]
- ["2020-01-02", "1"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ table_snapshot:
- name: booking
type: INT
- name: listing_id
type: INT
type: STRING
- name: is_instant
type: BOOLEAN
rows:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,30 @@ table_snapshot:
type: INT
- name: is_instant
type: BOOLEAN
- name: listing_id
type: STRING
rows:
- ["2020-01-01", "10", "True"]
- ["2020-01-01", "5", "False"]
- ["2020-02-01", "10", "True"]
- ["2020-02-01", "5", "False"]
- ["2020-03-01", "10", "True"]
- ["2020-03-01", "5", "False"]
- ["2020-04-01", "10", "True"]
- ["2020-04-01", "5", "False"]
- ["2020-05-01", "10", "True"]
- ["2020-05-01", "5", "False"]
- ["2020-06-01", "10", "True"]
- ["2020-06-01", "5", "False"]
- ["2020-07-01", "10", "True"]
- ["2020-07-01", "5", "False"]
- ["2020-08-01", "10", "True"]
- ["2020-08-01", "5", "False"]
- ["2020-09-01", "10", "True"]
- ["2020-09-01", "5", "False"]
- ["2020-10-01", "10", "True"]
- ["2020-10-01", "5", "False"]
- ["2020-11-01", "10", "True"]
- ["2020-11-01", "5", "False"]
- ["2020-12-01", "10", "True"]
- ["2020-12-01", "5", "False"]
- ["2020-01-01", "10", "True", "0"]
- ["2020-01-01", "5", "False", "1"]
- ["2020-02-01", "10", "True", "2"]
- ["2020-02-01", "5", "False", "3"]
- ["2020-03-01", "10", "True", "4"]
- ["2020-03-01", "5", "False", "5"]
- ["2020-04-01", "10", "True", "6"]
- ["2020-04-01", "5", "False", "7"]
- ["2020-05-01", "10", "True", "8"]
- ["2020-05-01", "5", "False", "9"]
- ["2020-06-01", "10", "True", "0"]
- ["2020-06-01", "5", "False", "0"]
- ["2020-07-01", "10", "True", "1"]
- ["2020-07-01", "5", "False", "2"]
- ["2020-08-01", "10", "True", "3"]
- ["2020-08-01", "5", "False", "4"]
- ["2020-09-01", "10", "True", "5"]
- ["2020-09-01", "5", "False", "6"]
- ["2020-10-01", "10", "True", "7"]
- ["2020-10-01", "5", "False", "8"]
- ["2020-11-01", "10", "True", "9"]
- ["2020-11-01", "5", "False", "0"]
- ["2020-12-01", "10", "True", "0"]
- ["2020-12-01", "5", "False", "1"]
Loading