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

Even more functional tests #512

Merged
merged 3 commits into from
Nov 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
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.

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)
Loading