Skip to content

Commit

Permalink
Even more functional tests (#512)
Browse files Browse the repository at this point in the history
  • Loading branch information
benc-db authored Nov 21, 2023
2 parents ceae0e4 + 347520f commit bbdb10a
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from dbt.tests.adapter.dbt_show.test_dbt_show import BaseShowLimit, BaseShowSqlHeader


class TestShowLimitDatabricks(BaseShowLimit):
class TestShowLimit(BaseShowLimit):
pass


class TestShowSqlHeaderDatabricks(BaseShowSqlHeader):
class TestShowSqlHeader(BaseShowSqlHeader):
pass
67 changes: 67 additions & 0 deletions tests/functional/adapter/ephemeral/test_ephemeral.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import os
import re
from dbt.tests.adapter.ephemeral.test_ephemeral import BaseEphemeralMulti, BaseEphemeral
from dbt.tests.adapter.ephemeral import test_ephemeral
from dbt.tests import util
import pytest


class TestEphemeralMulti(BaseEphemeralMulti):
def test_ephemeral_multi(self, project):
util.run_dbt(["seed"])
results = util.run_dbt(["run"])
assert len(results) == 3

util.check_relations_equal(project.adapter, ["seed", "dependent"])
util.check_relations_equal(project.adapter, ["seed", "double_dependent"])
util.check_relations_equal(project.adapter, ["seed", "super_dependent"])


class TestEphemeralNested(BaseEphemeral):
@pytest.fixture(scope="class")
def models(self):
return {
"ephemeral_level_two.sql": test_ephemeral.models_n__ephemeral_level_two_sql,
"root_view.sql": test_ephemeral.models_n__root_view_sql,
"ephemeral.sql": test_ephemeral.models_n__ephemeral_sql,
"source_table.sql": test_ephemeral.models_n__source_table_sql,
}

def test_ephemeral_nested(self, project):
results = util.run_dbt(["run"])
assert len(results) == 2
assert os.path.exists("./target/run/test/models/root_view.sql")
with open("./target/run/test/models/root_view.sql", "r") as fp:
sql_file = fp.read()

sql_file = re.sub(r"\d+", "", sql_file)
expected_sql = (
f"create or replace view `{project.database}`.`test_test_ephemeral`.`root_view` as "
"with __dbt__cte__ephemeral_level_two as ("
f"select * from `{project.database}`.`test_test_ephemeral`.`source_table`"
"), __dbt__cte__ephemeral as ("
"select * from __dbt__cte__ephemeral_level_two"
")select * from __dbt__cte__ephemeral"
)

sql_file = "".join(sql_file.split())
expected_sql = "".join(expected_sql.split())
assert sql_file == expected_sql


class TestEphemeralErrorHandling(BaseEphemeral):
@pytest.fixture(scope="class")
def models(self):
return {
"dependent.sql": test_ephemeral.ephemeral_errors__dependent_sql,
"base": {
"base.sql": test_ephemeral.ephemeral_errors__base__base_sql,
"base_copy.sql": test_ephemeral.ephemeral_errors__base__base_copy_sql,
},
}

def test_ephemeral_error_handling(self, project):
results = util.run_dbt(["run"], expect_pass=False)
assert len(results) == 1
assert results[0].status == "skipped"
assert "Compilation Error" in results[0].message
13 changes: 0 additions & 13 deletions tests/functional/adapter/ephemeral/test_ephemeral_multi.py

This file was deleted.

File renamed without changes.
76 changes: 76 additions & 0 deletions tests/functional/adapter/hooks/fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
create_table_statement = """
create table {database}.`{schema}`.`on_model_hook` (
test_state STRING, -- start|end
target_dbname STRING,
target_host STRING,
target_name STRING,
target_schema STRING,
target_type STRING,
target_user STRING,
target_pass STRING,
target_threads INT,
run_started_at STRING,
invocation_id STRING,
thread_id STRING
)
"""

MODEL_PRE_HOOK = """
insert into `{{this.database}}`.`{{this.schema}}`.`on_model_hook` (
test_state,
target_dbname,
target_host,
target_name,
target_schema,
target_type,
target_user,
target_pass,
target_threads,
run_started_at,
invocation_id,
thread_id
) VALUES (
'start',
'{{ target.dbname }}',
'{{ target.host }}',
'{{ target.name }}',
'{{ target.schema }}',
'{{ target.type }}',
'{{ target.user }}',
'{{ target.get("pass", "") }}',
{{ target.threads }},
'{{ run_started_at }}',
'{{ invocation_id }}',
'{{ thread_id }}'
)
"""

MODEL_POST_HOOK = """
insert into `{{this.database}}`.`{{this.schema}}`.`on_model_hook` (
test_state,
target_dbname,
target_host,
target_name,
target_schema,
target_type,
target_user,
target_pass,
target_threads,
run_started_at,
invocation_id,
thread_id
) VALUES (
'end',
'{{ target.dbname }}',
'{{ target.host }}',
'{{ target.name }}',
'{{ target.schema }}',
'{{ target.type }}',
'{{ target.user }}',
'{{ target.get("pass", "") }}',
{{ target.threads }},
'{{ run_started_at }}',
'{{ invocation_id }}',
'{{ thread_id }}'
)
"""
81 changes: 81 additions & 0 deletions tests/functional/adapter/hooks/test_model_hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from dbt.tests.adapter.hooks.test_model_hooks import BaseTestPrePost
from dbt.tests import util
from dbt.tests.adapter.hooks import fixtures

import pytest

from tests.functional.adapter.hooks import fixtures as override_fixtures


class TestPrePostModelHooks(BaseTestPrePost):
@pytest.fixture(scope="class", autouse=True)
def setUp(self, project):
util.run_sql_with_adapter(project.adapter, override_fixtures.create_table_statement)

@pytest.fixture(scope="class")
def project_config_update(self):
return {
"models": {
"test": {
"pre-hook": [
override_fixtures.MODEL_PRE_HOOK,
],
"post-hook": [
override_fixtures.MODEL_POST_HOOK,
],
}
}
}

@pytest.fixture(scope="class")
def models(self):
return {"hooks.sql": fixtures.models__hooks}

def get_ctx_vars(self, state, count, project):
fields = [
"test_state",
"target_dbname",
"target_host",
"target_name",
"target_schema",
"target_threads",
"target_type",
"target_user",
"target_pass",
"run_started_at",
"invocation_id",
"thread_id",
]
field_list = ", ".join(["{}".format(f) for f in fields])
query = (
f"select {field_list} from {project.test_schema}.on_model_hook"
f" where test_state = '{state}'"
)
vals = project.run_sql(query, fetch="all")
assert len(vals) != 0, "nothing inserted into hooks table"
assert len(vals) >= count, "too few rows in hooks table"
assert len(vals) <= count, "too many rows in hooks table"
return [{k: v for k, v in zip(fields, val)} for val in vals]

def check_hooks(self, state, project, target, count=1):
ctxs = self.get_ctx_vars(state, count=count, project=project)
for ctx in ctxs:
assert ctx["test_state"] == state
assert ctx["target_dbname"] == target.get("database", "")
assert ctx["target_host"] == target.get("host", "")
assert ctx["target_name"] == "default"
assert ctx["target_schema"] == project.test_schema
assert ctx["target_type"] == "databricks"

assert (
ctx["run_started_at"] is not None and len(ctx["run_started_at"]) > 0
), "run_started_at was not set"
assert (
ctx["invocation_id"] is not None and len(ctx["invocation_id"]) > 0
), "invocation_id was not set"
assert ctx["thread_id"].startswith("Thread-")

def test_pre_and_post_run_hooks(self, project, dbt_profile_target):
util.run_dbt()
self.check_hooks("start", project, dbt_profile_target)
self.check_hooks("end", project, dbt_profile_target)

0 comments on commit bbdb10a

Please sign in to comment.