Compare commits

...

2 Commits

Author SHA1 Message Date
Michelle Ark
52e2e8531e test adapter pre hooks for unit testing 2024-06-07 12:14:34 -04:00
McKnight-42
ef67cffc0a init push for issue 10198 2024-06-03 15:02:40 -05:00
3 changed files with 82 additions and 7 deletions

View File

@@ -126,6 +126,8 @@ class TestRunner(CompileRunner):
def execute_data_test(self, data_test: TestNode, manifest: Manifest) -> TestResultData:
context = generate_runtime_model_context(data_test, self.config, manifest)
hook_ctx = self.adapter.pre_model_hook(context)
materialization_macro = manifest.find_materialization_macro_by_name(
self.config.project_name, data_test.get_materialization(), self.adapter.type()
)
@@ -140,10 +142,13 @@ class TestRunner(CompileRunner):
"Invalid materialization context generated, missing config: {}".format(context)
)
# generate materialization macro
macro_func = MacroGenerator(materialization_macro, context)
# execute materialization macro
macro_func()
try:
# generate materialization macro
macro_func = MacroGenerator(materialization_macro, context)
# execute materialization macro
macro_func()
finally:
self.adapter.post_model_hook(context, hook_ctx)
# load results from context
# could eventually be returned directly by materialization
result = context["load_result"]("main")
@@ -198,6 +203,8 @@ class TestRunner(CompileRunner):
# materialization, not compile the node.compiled_code
context = generate_runtime_model_context(unit_test_node, self.config, unit_test_manifest)
hook_ctx = self.adapter.pre_model_hook(context)
materialization_macro = unit_test_manifest.find_materialization_macro_by_name(
self.config.project_name, unit_test_node.get_materialization(), self.adapter.type()
)
@@ -213,16 +220,18 @@ class TestRunner(CompileRunner):
"Invalid materialization context generated, missing config: {}".format(context)
)
# generate materialization macro
macro_func = MacroGenerator(materialization_macro, context)
# execute materialization macro
try:
# generate materialization macro
macro_func = MacroGenerator(materialization_macro, context)
# execute materialization macro
macro_func()
except DbtBaseException as e:
raise DbtRuntimeError(
f"An error occurred during execution of unit test '{unit_test_def.name}'. "
f"There may be an error in the unit test definition: check the data types.\n {e}"
)
finally:
self.adapter.post_model_hook(context, hook_ctx)
# load results from context
# could eventually be returned directly by materialization

View File

@@ -116,6 +116,23 @@ unit_tests:
tags: test_this
"""
test_my_model_pass_yml = """
unit_tests:
- name: test_my_model
model: my_model
given:
- input: ref('my_model_a')
rows:
- {id: 1, a: 1}
- input: ref('my_model_b')
rows:
- {id: 1, b: 2}
- {id: 2, b: 2}
expect:
rows:
- {c: 3}
"""
test_my_model_simple_fixture_yml = """
unit_tests:

View File

@@ -0,0 +1,49 @@
from unittest import mock
import pytest
from dbt.tests.util import run_dbt
from dbt_common.exceptions import CompilationError
from tests.functional.unit_testing.fixtures import (
my_model_a_sql,
my_model_b_sql,
my_model_sql,
test_my_model_pass_yml,
)
class BaseUnitTestAdapterHook:
@pytest.fixture(scope="class")
def models(self):
return {
"my_model.sql": my_model_sql,
"my_model_a.sql": my_model_a_sql,
"my_model_b.sql": my_model_b_sql,
"test_my_model.yml": test_my_model_pass_yml,
}
class TestUnitTestAdapterHookPasses(BaseUnitTestAdapterHook):
def test_unit_test_runs_adapter_pre_hook(self, project):
results = run_dbt(["run"])
assert len(results) == 3
mock_pre_model_hook = mock.Mock()
with mock.patch.object(type(project.adapter), "pre_model_hook", mock_pre_model_hook):
results = run_dbt(["test", "--select", "test_name:test_my_model"], expect_pass=True)
assert len(results) == 1
mock_pre_model_hook.assert_called_once()
class TestUnitTestAdapterHookFails(BaseUnitTestAdapterHook):
def test_unit_test_runs_adapter_pre_hook_fails(self, project):
results = run_dbt(["run"])
assert len(results) == 3
mock_pre_model_hook = mock.Mock()
mock_pre_model_hook.side_effect = CompilationError("exception from adapter.pre_model_hook")
with mock.patch.object(type(project.adapter), "pre_model_hook", mock_pre_model_hook):
run_dbt(["test", "--select", "test_name:test_my_model"], expect_pass=False)
mock_pre_model_hook.assert_called_once()