From 41c6865f59cef289201b729449b987fda8f355f8 Mon Sep 17 00:00:00 2001 From: Michelle Ark Date: Mon, 9 Sep 2024 10:36:25 -0400 Subject: [PATCH] remove tests covered by dbt-core --- tests/functional/minimal_cli/fixtures.py | 111 ---- .../minimal_cli/test_minimal_cli.py | 52 -- tests/functional/test_dbt_runner.py | 73 --- tests/functional/test_init.py | 493 ------------------ 4 files changed, 729 deletions(-) delete mode 100644 tests/functional/minimal_cli/fixtures.py delete mode 100644 tests/functional/minimal_cli/test_minimal_cli.py delete mode 100644 tests/functional/test_dbt_runner.py delete mode 100644 tests/functional/test_init.py diff --git a/tests/functional/minimal_cli/fixtures.py b/tests/functional/minimal_cli/fixtures.py deleted file mode 100644 index dadfb130..00000000 --- a/tests/functional/minimal_cli/fixtures.py +++ /dev/null @@ -1,111 +0,0 @@ -import pytest -from click.testing import CliRunner - -models__schema_yml = """ -version: 2 -models: - - name: sample_model - columns: - - name: sample_num - data_tests: - - accepted_values: - values: [1, 2] - - not_null - - name: sample_bool - data_tests: - - not_null - - unique -""" - -models__sample_model = """ -select * from {{ ref('sample_seed') }} -""" - -snapshots__sample_snapshot = """ -{% snapshot orders_snapshot %} - -{{ - config( - target_database='dbt', - target_schema='snapshots', - unique_key='sample_num', - strategy='timestamp', - updated_at='updated_at', - ) -}} - -select * from {{ ref('sample_model') }} - -{% endsnapshot %} -""" - -seeds__sample_seed = """sample_num,sample_bool -1,true -2,false -,true -""" - -tests__failing_sql = """ -{{ config(severity = 'warn') }} -select 1 -""" - - -class BaseConfigProject: - @pytest.fixture() - def runner(self): - return CliRunner() - - @pytest.fixture(scope="class") - def project_config_update(self): - return { - "name": "jaffle_shop", - "profile": "jaffle_shop", - "version": "0.1.0", - "config-version": 2, - "clean-targets": ["target", "dbt_packages", "logs"], - } - - @pytest.fixture(scope="class") - def profiles_config_update(self): - return { - "jaffle_shop": { - "outputs": { - "dev": { - "type": "postgres", - "dbname": "dbt", - "schema": "jaffle_shop", - "host": "localhost", - "user": "root", - "port": 5432, - "pass": "password", - } - }, - "target": "dev", - } - } - - @pytest.fixture(scope="class") - def packages(self): - return {"packages": [{"package": "dbt-labs/dbt_utils", "version": "1.0.0"}]} - - @pytest.fixture(scope="class") - def models(self): - return { - "schema.yml": models__schema_yml, - "sample_model.sql": models__sample_model, - } - - @pytest.fixture(scope="class") - def snapshots(self): - return {"sample_snapshot.sql": snapshots__sample_snapshot} - - @pytest.fixture(scope="class") - def seeds(self): - return {"sample_seed.csv": seeds__sample_seed} - - @pytest.fixture(scope="class") - def tests(self): - return { - "failing.sql": tests__failing_sql, - } diff --git a/tests/functional/minimal_cli/test_minimal_cli.py b/tests/functional/minimal_cli/test_minimal_cli.py deleted file mode 100644 index 1fccbbd0..00000000 --- a/tests/functional/minimal_cli/test_minimal_cli.py +++ /dev/null @@ -1,52 +0,0 @@ -from dbt.cli.main import cli - -from tests.functional.minimal_cli.fixtures import BaseConfigProject -from tests.functional.utils import up_one - - -class TestClean(BaseConfigProject): - """Test the minimal/happy-path for the CLI using the Click CliRunner""" - - def test_clean(self, runner, project): - result = runner.invoke(cli, ["clean"]) - assert "target" in result.output - assert "dbt_packages" in result.output - assert "logs" in result.output - - -class TestCleanUpLevel(BaseConfigProject): - def test_clean_one_level_up(self, runner, project): - with up_one(): - result = runner.invoke(cli, ["clean"]) - assert result.exit_code == 2 - assert "Runtime Error" in result.output - assert "No dbt_project.yml" in result.output - - -class TestDeps(BaseConfigProject): - def test_deps(self, runner, project): - result = runner.invoke(cli, ["deps"]) - assert "dbt-labs/dbt_utils" in result.output - assert "1.0.0" in result.output - - -class TestBuild(BaseConfigProject): - def test_build(self, runner, project): - runner.invoke(cli, ["deps"]) - result = runner.invoke(cli, ["build"]) - # 1 seed, 1 model, 2 data tests - assert "PASS=4" in result.output - # 2 data tests - assert "ERROR=2" in result.output - # Singular test - assert "WARN=1" in result.output - # 1 snapshot - assert "SKIP=1" in result.output - - -class TestDocsGenerate(BaseConfigProject): - def test_docs_generate(self, runner, project): - runner.invoke(cli, ["deps"]) - result = runner.invoke(cli, ["docs", "generate"]) - assert "Building catalog" in result.output - assert "Catalog written" in result.output diff --git a/tests/functional/test_dbt_runner.py b/tests/functional/test_dbt_runner.py deleted file mode 100644 index d3db2d20..00000000 --- a/tests/functional/test_dbt_runner.py +++ /dev/null @@ -1,73 +0,0 @@ -from unittest import mock - -from dbt.cli.exceptions import DbtUsageException -from dbt.cli.main import dbtRunner -from dbt.exceptions import DbtProjectError -import pytest - - -class TestDbtRunner: - @pytest.fixture - def dbt(self) -> dbtRunner: - return dbtRunner() - - def test_group_invalid_option(self, dbt: dbtRunner) -> None: - res = dbt.invoke(["--invalid-option"]) - assert isinstance(res.exception, DbtUsageException) - - def test_command_invalid_option(self, dbt: dbtRunner) -> None: - res = dbt.invoke(["deps", "--invalid-option"]) - assert isinstance(res.exception, DbtUsageException) - - def test_command_mutually_exclusive_option(self, dbt: dbtRunner) -> None: - res = dbt.invoke(["--warn-error", "--warn-error-options", '{"include": "all"}', "deps"]) - assert isinstance(res.exception, DbtUsageException) - res = dbt.invoke(["deps", "--warn-error", "--warn-error-options", '{"include": "all"}']) - assert isinstance(res.exception, DbtUsageException) - - def test_invalid_command(self, dbt: dbtRunner) -> None: - res = dbt.invoke(["invalid-command"]) - assert isinstance(res.exception, DbtUsageException) - - def test_invoke_version(self, dbt: dbtRunner) -> None: - dbt.invoke(["--version"]) - - def test_callbacks(self) -> None: - mock_callback = mock.MagicMock() - dbt = dbtRunner(callbacks=[mock_callback]) - # the `debug` command is one of the few commands wherein you don't need - # to have a project to run it and it will emit events - dbt.invoke(["debug"]) - mock_callback.assert_called() - - def test_invoke_kwargs(self, project, dbt): - res = dbt.invoke( - ["run"], - log_format="json", - log_path="some_random_path", - version_check=False, - profile_name="some_random_profile_name", - target_dir="some_random_target_dir", - ) - assert res.result.args["log_format"] == "json" - assert res.result.args["log_path"] == "some_random_path" - assert res.result.args["version_check"] is False - assert res.result.args["profile_name"] == "some_random_profile_name" - assert res.result.args["target_dir"] == "some_random_target_dir" - - def test_invoke_kwargs_project_dir(self, project, dbt): - res = dbt.invoke(["run"], project_dir="some_random_project_dir") - assert isinstance(res.exception, DbtProjectError) - - msg = "No dbt_project.yml found at expected path some_random_project_dir" - assert msg in res.exception.msg - - def test_invoke_kwargs_profiles_dir(self, project, dbt): - res = dbt.invoke(["run"], profiles_dir="some_random_profiles_dir") - assert isinstance(res.exception, DbtProjectError) - msg = "Could not find profile named 'test'" - assert msg in res.exception.msg - - def test_invoke_kwargs_and_flags(self, project, dbt): - res = dbt.invoke(["--log-format=text", "run"], log_format="json") - assert res.result.args["log_format"] == "json" diff --git a/tests/functional/test_init.py b/tests/functional/test_init.py deleted file mode 100644 index 1c8202b7..00000000 --- a/tests/functional/test_init.py +++ /dev/null @@ -1,493 +0,0 @@ -import os -from pathlib import Path -from unittest.mock import Mock, call, patch - -import click -from dbt_common.exceptions import DbtRuntimeError -from dbt.tests.util import run_dbt -import pytest - - -class TestInitProjectWithExistingProfilesYml: - @patch("dbt.task.init._get_adapter_plugin_names") - @patch("click.confirm") - @patch("click.prompt") - def test_init_task_in_project_with_existing_profiles_yml( - self, mock_prompt, mock_confirm, mock_get_adapter, project - ): - manager = Mock() - manager.attach_mock(mock_prompt, "prompt") - manager.attach_mock(mock_confirm, "confirm") - manager.confirm.side_effect = ["y"] - manager.prompt.side_effect = [ - 1, - "localhost", - 5432, - "test_user", - "test_password", - "test_db", - "test_schema", - 4, - ] - mock_get_adapter.return_value = [project.adapter.type()] - - run_dbt(["init"]) - - manager.assert_has_calls( - [ - call.confirm( - f"The profile test already exists in {os.path.join(project.profiles_dir, 'profiles.yml')}. Continue and overwrite it?" - ), - call.prompt( - "Which database would you like to use?\n[1] postgres\n\n(Don't see the one you want? https://docs.getdbt.com/docs/available-adapters)\n\nEnter a number", - type=click.INT, - ), - call.prompt( - "host (hostname for the instance)", default=None, hide_input=False, type=None - ), - call.prompt("port", default=5432, hide_input=False, type=click.INT), - call.prompt("user (dev username)", default=None, hide_input=False, type=None), - call.prompt("pass (dev password)", default=None, hide_input=True, type=None), - call.prompt( - "dbname (default database that dbt will build objects in)", - default=None, - hide_input=False, - type=None, - ), - call.prompt( - "schema (default schema that dbt will build objects in)", - default=None, - hide_input=False, - type=None, - ), - call.prompt("threads (1 or more)", default=1, hide_input=False, type=click.INT), - ] - ) - - with open(os.path.join(project.profiles_dir, "profiles.yml"), "r") as f: - assert ( - f.read() - == """test: - outputs: - dev: - dbname: test_db - host: localhost - pass: test_password - port: 5432 - schema: test_schema - threads: 4 - type: postgres - user: test_user - target: dev -""" - ) - - def test_init_task_in_project_specifying_profile_errors(self): - with pytest.raises(DbtRuntimeError) as error: - run_dbt(["init", "--profile", "test"], expect_pass=False) - assert "Can not init existing project with specified profile" in str(error) - - -class TestInitProjectWithoutExistingProfilesYml: - @patch("dbt.task.init._get_adapter_plugin_names") - @patch("click.prompt") - @patch.object(Path, "exists", autospec=True) - def test_init_task_in_project_without_existing_profiles_yml( - self, exists, mock_prompt, mock_get_adapter, project - ): - def exists_side_effect(path): - # Override responses on specific files, default to 'real world' if not overriden - return {"profiles.yml": False}.get(path.name, os.path.exists(path)) - - exists.side_effect = exists_side_effect - manager = Mock() - manager.attach_mock(mock_prompt, "prompt") - manager.prompt.side_effect = [ - 1, - "localhost", - 5432, - "test_user", - "test_password", - "test_db", - "test_schema", - 4, - ] - mock_get_adapter.return_value = [project.adapter.type()] - - run_dbt(["init"]) - - manager.assert_has_calls( - [ - call.prompt( - "Which database would you like to use?\n[1] postgres\n\n(Don't see the one you want? https://docs.getdbt.com/docs/available-adapters)\n\nEnter a number", - type=click.INT, - ), - call.prompt( - "host (hostname for the instance)", default=None, hide_input=False, type=None - ), - call.prompt("port", default=5432, hide_input=False, type=click.INT), - call.prompt("user (dev username)", default=None, hide_input=False, type=None), - call.prompt("pass (dev password)", default=None, hide_input=True, type=None), - call.prompt( - "dbname (default database that dbt will build objects in)", - default=None, - hide_input=False, - type=None, - ), - call.prompt( - "schema (default schema that dbt will build objects in)", - default=None, - hide_input=False, - type=None, - ), - call.prompt("threads (1 or more)", default=1, hide_input=False, type=click.INT), - ] - ) - - with open(os.path.join(project.profiles_dir, "profiles.yml"), "r") as f: - assert ( - f.read() - == """test: - outputs: - dev: - dbname: test_db - host: localhost - pass: test_password - port: 5432 - schema: test_schema - threads: 4 - type: postgres - user: test_user - target: dev -""" - ) - - @patch.object(Path, "exists", autospec=True) - def test_init_task_in_project_without_profile_yml_specifying_profile_errors(self, exists): - def exists_side_effect(path): - # Override responses on specific files, default to 'real world' if not overriden - return {"profiles.yml": False}.get(path.name, os.path.exists(path)) - - exists.side_effect = exists_side_effect - - # Even through no profiles.yml file exists, the init will not modify project.yml, - # so this errors - with pytest.raises(DbtRuntimeError) as error: - run_dbt(["init", "--profile", "test"], expect_pass=False) - assert "Could not find profile named test" in str(error) - - -class TestInitProjectWithoutExistingProfilesYmlOrTemplate: - @patch("dbt.task.init._get_adapter_plugin_names") - @patch("click.confirm") - @patch("click.prompt") - @patch.object(Path, "exists", autospec=True) - def test_init_task_in_project_without_existing_profiles_yml_or_profile_template( - self, exists, mock_prompt, mock_confirm, mock_get_adapter, project - ): - def exists_side_effect(path): - # Override responses on specific files, default to 'real world' if not overriden - return { - "profiles.yml": False, - "profile_template.yml": False, - }.get(path.name, os.path.exists(path)) - - exists.side_effect = exists_side_effect - manager = Mock() - manager.attach_mock(mock_prompt, "prompt") - manager.attach_mock(mock_confirm, "confirm") - manager.prompt.side_effect = [ - 1, - ] - mock_get_adapter.return_value = [project.adapter.type()] - run_dbt(["init"]) - manager.assert_has_calls( - [ - call.prompt( - "Which database would you like to use?\n[1] postgres\n\n(Don't see the one you want? https://docs.getdbt.com/docs/available-adapters)\n\nEnter a number", - type=click.INT, - ), - ] - ) - - with open(os.path.join(project.profiles_dir, "profiles.yml"), "r") as f: - assert ( - f.read() - == """test: - outputs: - - dev: - type: postgres - threads: [1 or more] - host: [host] - port: [port] - user: [dev_username] - pass: [dev_password] - dbname: [dbname] - schema: [dev_schema] - - prod: - type: postgres - threads: [1 or more] - host: [host] - port: [port] - user: [prod_username] - pass: [prod_password] - dbname: [dbname] - schema: [prod_schema] - - target: dev -""" - ) - - -class TestInitProjectWithProfileTemplateWithoutExistingProfilesYml: - @patch("dbt.task.init._get_adapter_plugin_names") - @patch("click.confirm") - @patch("click.prompt") - @patch.object(Path, "exists", autospec=True) - def test_init_task_in_project_with_profile_template_without_existing_profiles_yml( - self, exists, mock_prompt, mock_confirm, mock_get_adapter, project - ): - def exists_side_effect(path): - # Override responses on specific files, default to 'real world' if not overriden - return { - "profiles.yml": False, - }.get(path.name, os.path.exists(path)) - - exists.side_effect = exists_side_effect - - with open("profile_template.yml", "w") as f: - f.write( - """fixed: - type: postgres - threads: 4 - host: localhost - dbname: my_db - schema: my_schema - target: my_target -prompts: - target: - hint: 'The target name' - type: string - port: - hint: 'The port (for integer test purposes)' - type: int - default: 5432 - user: - hint: 'Your username' - pass: - hint: 'Your password' - hide_input: true""" - ) - - manager = Mock() - manager.attach_mock(mock_prompt, "prompt") - manager.attach_mock(mock_confirm, "confirm") - manager.prompt.side_effect = ["my_target", 5432, "test_username", "test_password"] - mock_get_adapter.return_value = [project.adapter.type()] - run_dbt(["init"]) - manager.assert_has_calls( - [ - call.prompt( - "target (The target name)", default=None, hide_input=False, type=click.STRING - ), - call.prompt( - "port (The port (for integer test purposes))", - default=5432, - hide_input=False, - type=click.INT, - ), - call.prompt("user (Your username)", default=None, hide_input=False, type=None), - call.prompt("pass (Your password)", default=None, hide_input=True, type=None), - ] - ) - - with open(os.path.join(project.profiles_dir, "profiles.yml"), "r") as f: - assert ( - f.read() - == """test: - outputs: - my_target: - dbname: my_db - host: localhost - pass: test_password - port: 5432 - schema: my_schema - threads: 4 - type: postgres - user: test_username - target: my_target -""" - ) - - -class TestInitInvalidProfileTemplate: - @patch("dbt.task.init._get_adapter_plugin_names") - @patch("click.confirm") - @patch("click.prompt") - def test_init_task_in_project_with_invalid_profile_template( - self, mock_prompt, mock_confirm, mock_get_adapter, project - ): - """Test that when an invalid profile_template.yml is provided in the project, - init command falls back to the target's profile_template.yml""" - with open(os.path.join(project.project_root, "profile_template.yml"), "w") as f: - f.write("""invalid template""") - - manager = Mock() - manager.attach_mock(mock_prompt, "prompt") - manager.attach_mock(mock_confirm, "confirm") - manager.confirm.side_effect = ["y"] - manager.prompt.side_effect = [ - 1, - "localhost", - 5432, - "test_username", - "test_password", - "test_db", - "test_schema", - 4, - ] - mock_get_adapter.return_value = [project.adapter.type()] - - run_dbt(["init"]) - - manager.assert_has_calls( - [ - call.confirm( - f"The profile test already exists in {os.path.join(project.profiles_dir, 'profiles.yml')}. Continue and overwrite it?" - ), - call.prompt( - "Which database would you like to use?\n[1] postgres\n\n(Don't see the one you want? https://docs.getdbt.com/docs/available-adapters)\n\nEnter a number", - type=click.INT, - ), - call.prompt( - "host (hostname for the instance)", default=None, hide_input=False, type=None - ), - call.prompt("port", default=5432, hide_input=False, type=click.INT), - call.prompt("user (dev username)", default=None, hide_input=False, type=None), - call.prompt("pass (dev password)", default=None, hide_input=True, type=None), - call.prompt( - "dbname (default database that dbt will build objects in)", - default=None, - hide_input=False, - type=None, - ), - call.prompt( - "schema (default schema that dbt will build objects in)", - default=None, - hide_input=False, - type=None, - ), - call.prompt("threads (1 or more)", default=1, hide_input=False, type=click.INT), - ] - ) - - with open(os.path.join(project.profiles_dir, "profiles.yml"), "r") as f: - assert ( - f.read() - == """test: - outputs: - dev: - dbname: test_db - host: localhost - pass: test_password - port: 5432 - schema: test_schema - threads: 4 - type: postgres - user: test_username - target: dev -""" - ) - - -class TestInitInsideOfProjectBase: - @pytest.fixture(scope="class") - def project_name(self, unique_schema): - return f"my_project_{unique_schema}" - - -class TestInitOutsideOfProjectBase: - @pytest.fixture(scope="class") - def project_name(self, unique_schema): - return f"my_project_{unique_schema}" - - @pytest.fixture(scope="class", autouse=True) - def setup(self, project): - # Start by removing the dbt_project.yml so that we're not in an existing project - os.remove(os.path.join(project.project_root, "dbt_project.yml")) - - -class TestInitInsideProjectAndSkipProfileSetup(TestInitInsideOfProjectBase): - @patch("dbt.task.init._get_adapter_plugin_names") - @patch("click.confirm") - @patch("click.prompt") - def test_init_inside_project_and_skip_profile_setup( - self, mock_prompt, mock_confirm, mock_get, project, project_name - ): - manager = Mock() - manager.attach_mock(mock_prompt, "prompt") - manager.attach_mock(mock_confirm, "confirm") - - assert Path("dbt_project.yml").exists() - - # skip interactive profile setup - run_dbt(["init", "--skip-profile-setup"]) - assert len(manager.mock_calls) == 0 - - -class TestInitOutsideOfProjectSpecifyingInvalidProfile(TestInitOutsideOfProjectBase): - @patch("dbt.task.init._get_adapter_plugin_names") - @patch("click.prompt") - def test_init_task_outside_project_specifying_invalid_profile_errors( - self, mock_prompt, mock_get_adapter, project, project_name - ): - manager = Mock() - manager.attach_mock(mock_prompt, "prompt") - manager.prompt.side_effect = [ - project_name, - ] - mock_get_adapter.return_value = [project.adapter.type()] - - with pytest.raises(DbtRuntimeError) as error: - run_dbt(["init", "--profile", "invalid"], expect_pass=False) - assert "Could not find profile named invalid" in str(error) - - manager.assert_has_calls( - [ - call.prompt("Enter a name for your project (letters, digits, underscore)"), - ] - ) - - -class TestInitOutsideOfProjectSpecifyingProfileNoProfilesYml(TestInitOutsideOfProjectBase): - @patch("dbt.task.init._get_adapter_plugin_names") - @patch("click.prompt") - def test_init_task_outside_project_specifying_profile_no_profiles_yml_errors( - self, mock_prompt, mock_get_adapter, project, project_name - ): - manager = Mock() - manager.attach_mock(mock_prompt, "prompt") - manager.prompt.side_effect = [ - project_name, - ] - mock_get_adapter.return_value = [project.adapter.type()] - - # Override responses on specific files, default to 'real world' if not overriden - original_isfile = os.path.isfile - with patch( - "os.path.isfile", - new=lambda path: {"profiles.yml": False}.get( - os.path.basename(path), original_isfile(path) - ), - ): - with pytest.raises(DbtRuntimeError) as error: - run_dbt(["init", "--profile", "test"], expect_pass=False) - assert "Could not find profile named invalid" in str(error) - - manager.assert_has_calls( - [ - call.prompt("Enter a name for your project (letters, digits, underscore)"), - ] - )