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

Create RuntimeConfig fixture #10242

Merged
merged 9 commits into from
May 31, 2024
51 changes: 50 additions & 1 deletion tests/functional/basic/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import pytest
import yaml

from dbt.exceptions import ProjectContractError
from dbt.cli.main import dbtRunner
from dbt.exceptions import DbtProjectError, ProjectContractError
from dbt.tests.util import run_dbt, update_config_file, write_config_file

simple_model_sql = """
Expand Down Expand Up @@ -118,3 +119,51 @@ def test_dbt_cloud_invalid(self, project):
with pytest.raises(ProjectContractError) as excinfo:
run_dbt()
assert expected_err in str(excinfo.value)


class TestVersionSpecifierChecksComeBeforeYamlValidation:
def test_version_specifier_checks_before_yaml_validation(self, project) -> None:
runner = dbtRunner()

# if no version specifier error, we should get a yaml validation error
config_update = {"this-is-not-a-valid-key": "my-value-for-invalid-key"}
update_config_file(config_update, "dbt_project.yml")
result = runner.invoke(["parse"])
assert result.exception is not None
assert isinstance(result.exception, ProjectContractError)
assert "Additional properties are not allowed" in str(result.exception)

# add bad version specifier, and assert we get the error for that
update_config_file({"require-dbt-version": [">0.0.0", "<=0.0.1"]}, "dbt_project.yml")
result = runner.invoke(["parse"])
assert result.exception is not None
assert isinstance(result.exception, DbtProjectError)
assert "This version of dbt is not supported"


class TestArchiveNotAllowed:
"""At one point in time we supported an 'archive' key in projects, but no longer"""

def test_archive_not_allowed(self, project):
runner = dbtRunner()

config_update = {
"archive": {
"source_schema": "a",
"target_schema": "b",
"tables": [
{
"source_table": "seed",
"target_table": "archive_actual",
"updated_at": "updated_at",
"unique_key": """id || '-' || first_name""",
},
],
}
}
update_config_file(config_update, "dbt_project.yml")

result = runner.invoke(["parse"])
assert result.exception is not None
assert isinstance(result.exception, ProjectContractError)
assert "Additional properties are not allowed" in str(result.exception)
55 changes: 53 additions & 2 deletions tests/unit/config/test_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import unittest
from copy import deepcopy
from typing import Any, Dict
from unittest import mock

import pytest
Expand All @@ -10,7 +11,7 @@
import dbt.exceptions
from dbt.adapters.contracts.connection import DEFAULT_QUERY_COMMENT, QueryComment
from dbt.adapters.factory import load_plugin
from dbt.config.project import Project
from dbt.config.project import Project, _get_required_version
from dbt.constants import DEPENDENCIES_FILE_NAME
from dbt.contracts.project import GitPackage, LocalPackage, PackageConfig
from dbt.flags import set_from_args
Expand Down Expand Up @@ -42,7 +43,7 @@ def test_fixture_paths(self, project: Project):
def test__str__(self, project: Project):
assert (
str(project)
== "{'name': 'test_project', 'version': 1.0, 'project-root': 'doesnt/actually/exist', 'profile': 'test_profile', 'model-paths': ['models'], 'macro-paths': ['macros'], 'seed-paths': ['seeds'], 'test-paths': ['tests'], 'analysis-paths': ['analyses'], 'docs-paths': ['docs'], 'asset-paths': ['assets'], 'target-path': 'target', 'snapshot-paths': ['snapshots'], 'clean-targets': ['target'], 'log-path': 'path/to/project/logs', 'quoting': {'database': True, 'schema': True, 'identifier': True}, 'models': {}, 'on-run-start': [], 'on-run-end': [], 'dispatch': [{'macro_namespace': 'dbt_utils', 'search_order': ['test_project', 'dbt_utils']}], 'seeds': {}, 'snapshots': {}, 'sources': {}, 'data_tests': {}, 'unit_tests': {}, 'metrics': {}, 'semantic-models': {}, 'saved-queries': {}, 'exposures': {}, 'vars': {}, 'require-dbt-version': ['=0.0.0'], 'restrict-access': False, 'dbt-cloud': {}, 'query-comment': {'comment': \"\\n{%- set comment_dict = {} -%}\\n{%- do comment_dict.update(\\n app='dbt',\\n dbt_version=dbt_version,\\n profile_name=target.get('profile_name'),\\n target_name=target.get('target_name'),\\n) -%}\\n{%- if node is not none -%}\\n {%- do comment_dict.update(\\n node_id=node.unique_id,\\n ) -%}\\n{% else %}\\n {# in the node context, the connection name is the node_id #}\\n {%- do comment_dict.update(connection_name=connection_name) -%}\\n{%- endif -%}\\n{{ return(tojson(comment_dict)) }}\\n\", 'append': False, 'job-label': False}, 'packages': []}"
== "{'name': 'test_project', 'version': 1.0, 'project-root': 'doesnt/actually/exist', 'profile': 'test_profile', 'model-paths': ['models'], 'macro-paths': ['macros'], 'seed-paths': ['seeds'], 'test-paths': ['tests'], 'analysis-paths': ['analyses'], 'docs-paths': ['docs'], 'asset-paths': ['assets'], 'target-path': 'target', 'snapshot-paths': ['snapshots'], 'clean-targets': ['target'], 'log-path': 'path/to/project/logs', 'quoting': {}, 'models': {}, 'on-run-start': [], 'on-run-end': [], 'dispatch': [{'macro_namespace': 'dbt_utils', 'search_order': ['test_project', 'dbt_utils']}], 'seeds': {}, 'snapshots': {}, 'sources': {}, 'data_tests': {}, 'unit_tests': {}, 'metrics': {}, 'semantic-models': {}, 'saved-queries': {}, 'exposures': {}, 'vars': {}, 'require-dbt-version': ['=0.0.0'], 'restrict-access': False, 'dbt-cloud': {}, 'query-comment': {'comment': \"\\n{%- set comment_dict = {} -%}\\n{%- do comment_dict.update(\\n app='dbt',\\n dbt_version=dbt_version,\\n profile_name=target.get('profile_name'),\\n target_name=target.get('target_name'),\\n) -%}\\n{%- if node is not none -%}\\n {%- do comment_dict.update(\\n node_id=node.unique_id,\\n ) -%}\\n{% else %}\\n {# in the node context, the connection name is the node_id #}\\n {%- do comment_dict.update(connection_name=connection_name) -%}\\n{%- endif -%}\\n{{ return(tojson(comment_dict)) }}\\n\", 'append': False, 'job-label': False}, 'packages': []}"
)

def test_get_selector(self, project: Project):
Expand Down Expand Up @@ -534,3 +535,53 @@ def setUp(self):
def test_setting_multiple_flags(self):
with pytest.raises(dbt.exceptions.DbtProjectError):
set_from_args(self.args, None)


class TestGetRequiredVersion:
@pytest.fixture
def project_dict(self) -> Dict[str, Any]:
return {
"name": "test_project",
"require-dbt-version": ">0.0.0",
}

def test_supported_version(self, project_dict: Dict[str, Any]) -> None:
specifiers = _get_required_version(project_dict=project_dict, verify_version=True)
assert set(x.to_version_string() for x in specifiers) == {">0.0.0"}

def test_unsupported_version(self, project_dict: Dict[str, Any]) -> None:
project_dict["require-dbt-version"] = ">99999.0.0"
with pytest.raises(
dbt.exceptions.DbtProjectError, match="This version of dbt is not supported"
):
_get_required_version(project_dict=project_dict, verify_version=True)

def test_unsupported_version_no_check(self, project_dict: Dict[str, Any]) -> None:
project_dict["require-dbt-version"] = ">99999.0.0"
specifiers = _get_required_version(project_dict=project_dict, verify_version=False)
assert set(x.to_version_string() for x in specifiers) == {">99999.0.0"}

def test_supported_version_range(self, project_dict: Dict[str, Any]) -> None:
project_dict["require-dbt-version"] = [">0.0.0", "<=99999.0.0"]
specifiers = _get_required_version(project_dict=project_dict, verify_version=True)
assert set(x.to_version_string() for x in specifiers) == {">0.0.0", "<=99999.0.0"}

def test_unsupported_version_range(self, project_dict: Dict[str, Any]) -> None:
project_dict["require-dbt-version"] = [">0.0.0", "<=0.0.1"]
with pytest.raises(
dbt.exceptions.DbtProjectError, match="This version of dbt is not supported"
):
_get_required_version(project_dict=project_dict, verify_version=True)

def test_unsupported_version_range_no_check(self, project_dict: Dict[str, Any]) -> None:
project_dict["require-dbt-version"] = [">0.0.0", "<=0.0.1"]
specifiers = _get_required_version(project_dict=project_dict, verify_version=False)
assert set(x.to_version_string() for x in specifiers) == {">0.0.0", "<=0.0.1"}

def test_impossible_version_range(self, project_dict: Dict[str, Any]) -> None:
project_dict["require-dbt-version"] = [">99999.0.0", "<=0.0.1"]
with pytest.raises(
dbt.exceptions.DbtProjectError,
match="The package version requirement can never be satisfied",
):
_get_required_version(project_dict=project_dict, verify_version=True)
Loading
Loading