Skip to content

Commit

Permalink
Reorganize a number of our unit tests (#9972)
Browse files Browse the repository at this point in the history
* Move `tests/unit/test_yaml_renderer.py` to `tests/unit/parser/test_schema_renderer.py`

* Move `tests/unit/test_unit_test_parser.py` to `tests/unit/parser/test_unit_tests.py`

* Convert `tests/unit/test_tracking.py` to use pytest fixtures

* Delete `tests/unit/test_sql_result.py` as it was moved to `dbt-adapters`

* Move `tests/unit/test_semantic_models.py` to `tests/unit/graph/test_nodes.py

* Group tests of `SemanticModel` in `test_nodes.py` into a `TestSemanticModel` class

* Move `tests/unit/test_selector_errors.py` to `tests/unit/config/test_selectors.py`
  • Loading branch information
QMalcolm authored Apr 24, 2024
1 parent 9a0b714 commit 1e4bed0
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 147 deletions.
File renamed without changes.
106 changes: 106 additions & 0 deletions tests/unit/graph/test_nodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
from copy import deepcopy
import pytest
from typing import List

from dbt.artifacts.resources import Dimension, Entity, Measure, Defaults
from dbt.contracts.graph.nodes import SemanticModel
from dbt.artifacts.resources.v1.semantic_model import NodeRelation
from dbt.node_types import NodeType
from dbt_semantic_interfaces.references import MeasureReference
from dbt_semantic_interfaces.type_enums import AggregationType, DimensionType, EntityType


class TestSemanticModel:
@pytest.fixture(scope="function")
def dimensions(self) -> List[Dimension]:
return [Dimension(name="ds", type=DimensionType)]

@pytest.fixture(scope="function")
def entities(self) -> List[Entity]:
return [Entity(name="test_entity", type=EntityType.PRIMARY, expr="id")]

@pytest.fixture(scope="function")
def measures(self) -> List[Measure]:
return [Measure(name="test_measure", agg=AggregationType.COUNT, expr="id")]

@pytest.fixture(scope="function")
def default_semantic_model(
self, dimensions: List[Dimension], entities: List[Entity], measures: List[Measure]
) -> SemanticModel:
return SemanticModel(
name="test_semantic_model",
resource_type=NodeType.SemanticModel,
model="ref('test_model')",
package_name="test",
path="test_path",
original_file_path="test_fixture",
unique_id=f"{NodeType.SemanticModel}.test.test_semantic_model",
fqn=[],
defaults=Defaults(agg_time_dimension="ds"),
dimensions=dimensions,
entities=entities,
measures=measures,
node_relation=NodeRelation(
alias="test_alias", schema_name="test_schema", database="test_database"
),
)

def test_checked_agg_time_dimension_for_measure_via_defaults(
self,
default_semantic_model: SemanticModel,
):
assert default_semantic_model.defaults.agg_time_dimension is not None
measure = default_semantic_model.measures[0]
measure.agg_time_dimension = None
default_semantic_model.checked_agg_time_dimension_for_measure(
MeasureReference(element_name=measure.name)
)

def test_checked_agg_time_dimension_for_measure_via_measure(
self, default_semantic_model: SemanticModel
):
default_semantic_model.defaults = None
measure = default_semantic_model.measures[0]
measure.agg_time_dimension = default_semantic_model.dimensions[0].name
default_semantic_model.checked_agg_time_dimension_for_measure(
MeasureReference(element_name=measure.name)
)

def test_checked_agg_time_dimension_for_measure_exception(
self, default_semantic_model: SemanticModel
):
default_semantic_model.defaults = None
measure = default_semantic_model.measures[0]
measure.agg_time_dimension = None

with pytest.raises(AssertionError) as execinfo:
default_semantic_model.checked_agg_time_dimension_for_measure(
MeasureReference(measure.name)
)

assert (
f"Aggregation time dimension for measure {measure.name} on semantic model {default_semantic_model.name}"
in str(execinfo.value)
)

def test_semantic_model_same_contents(self, default_semantic_model: SemanticModel):
default_semantic_model_copy = deepcopy(default_semantic_model)

assert default_semantic_model.same_contents(default_semantic_model_copy)

def test_semantic_model_same_contents_update_model(
self, default_semantic_model: SemanticModel
):
default_semantic_model_copy = deepcopy(default_semantic_model)
default_semantic_model_copy.model = "ref('test_another_model')"

assert not default_semantic_model.same_contents(default_semantic_model_copy)

def test_semantic_model_same_contents_different_node_relation(
self,
default_semantic_model: SemanticModel,
):
default_semantic_model_copy = deepcopy(default_semantic_model)
default_semantic_model_copy.node_relation.alias = "test_another_alias"
# Relation should not be consided in same_contents
assert default_semantic_model.same_contents(default_semantic_model_copy)
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from dbt.parser import SchemaParser
from dbt.parser.unit_tests import UnitTestParser

from .utils import MockNode
from .test_parser import SchemaParserTest, assertEqualNodes
from tests.unit.utils import MockNode
from tests.unit.test_parser import SchemaParserTest, assertEqualNodes

from unittest import mock
from dbt.contracts.graph.unparsed import UnitTestOutputFixture
Expand Down
106 changes: 0 additions & 106 deletions tests/unit/test_semantic_models.py

This file was deleted.

19 changes: 0 additions & 19 deletions tests/unit/test_sql_result.py

This file was deleted.

39 changes: 19 additions & 20 deletions tests/unit/test_tracking.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
import pytest

import dbt.tracking
import datetime
import shutil
import tempfile
import unittest


class TestTracking(unittest.TestCase):
def setUp(self):
dbt.tracking.active_user = None
self.tempdir = tempfile.mkdtemp()
@pytest.fixture(scope="function")
def active_user_none() -> None:
dbt.tracking.active_user = None


@pytest.fixture(scope="function")
def tempdir(active_user_none) -> str:
return tempfile.mkdtemp()

def tearDown(self):
dbt.tracking.active_user = None
shutil.rmtree(self.tempdir)

def test_tracking_initial(self):
class TestTracking:
def test_tracking_initial(self, tempdir):
assert dbt.tracking.active_user is None
dbt.tracking.initialize_from_flags(True, self.tempdir)
dbt.tracking.initialize_from_flags(True, tempdir)
assert isinstance(dbt.tracking.active_user, dbt.tracking.User)

invocation_id = dbt.tracking.active_user.invocation_id
Expand Down Expand Up @@ -48,7 +50,7 @@ def test_tracking_initial(self):
# if you use `!=`, you might hit a race condition (especially on windows)
assert dbt.tracking.active_user.run_started_at is not run_started_at

def test_tracking_never_ok(self):
def test_tracking_never_ok(self, active_user_none):
assert dbt.tracking.active_user is None

# this should generate a whole new user object -> new invocation_id/run_started_at
Expand All @@ -60,7 +62,7 @@ def test_tracking_never_ok(self):
assert isinstance(dbt.tracking.active_user.invocation_id, str)
assert isinstance(dbt.tracking.active_user.run_started_at, datetime.datetime)

def test_disable_never_enabled(self):
def test_disable_never_enabled(self, active_user_none):
assert dbt.tracking.active_user is None

# this should generate a whole new user object -> new invocation_id/run_started_at
Expand All @@ -72,10 +74,7 @@ def test_disable_never_enabled(self):
assert isinstance(dbt.tracking.active_user.invocation_id, str)
assert isinstance(dbt.tracking.active_user.run_started_at, datetime.datetime)

def test_initialize_from_flags(self):
for send_anonymous_usage_stats in [True, False]:
with self.subTest(send_anonymous_usage_stats=send_anonymous_usage_stats):

dbt.tracking.initialize_from_flags(send_anonymous_usage_stats, self.tempdir)

assert dbt.tracking.active_user.do_not_track != send_anonymous_usage_stats
@pytest.mark.parametrize("send_anonymous_usage_stats", [True, False])
def test_initialize_from_flags(self, tempdir, send_anonymous_usage_stats):
dbt.tracking.initialize_from_flags(send_anonymous_usage_stats, tempdir)
assert dbt.tracking.active_user.do_not_track != send_anonymous_usage_stats

0 comments on commit 1e4bed0

Please sign in to comment.