From e30f7711f864694f22f4ecf282ca9aca6cb2748f Mon Sep 17 00:00:00 2001 From: Pradeep Srikakolapu Date: Wed, 10 Apr 2024 11:28:23 -0700 Subject: [PATCH] added render_limited and functional tests --- .gitignore | 197 +++++++++--------- .pre-commit-config.yaml | 3 +- .vscode/settings.json | 4 +- LICENSE | 42 ++-- dbt/adapters/fabric/fabric_adapter.py | 9 + tests/functional/adapter/test_empty.py | 10 + .../unit/adapters/fabric/test_unit_testing.py | 90 ++++++++ 7 files changed, 235 insertions(+), 120 deletions(-) create mode 100644 tests/functional/adapter/test_empty.py create mode 100644 tests/unit/adapters/fabric/test_unit_testing.py diff --git a/.gitignore b/.gitignore index 38ba195c..9266d34f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,97 +1,100 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] - -# C extensions -*.so - -# Distribution / packaging -.Python -env/ -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -*.egg-info/ -/*.egg-info -.installed.cfg -*.egg - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.log.legacy - -# Translations -*.mo -*.pot - -# Django stuff: -*.log - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# DotEnv configuration -.env - -# Database -*.db -*.rdb - -# Pycharm -.idea - -# Spyder -.spyproject/ - -# Jupyter NB Checkpoints -.ipynb_checkpoints/ - -# exclude data from source control by default -/data/ - -# Mac OS-specific storage files -.DS_Store - -# vim -*.swp -*.swo - -# Mypy cache -.mypy_cache/ - -# Environments -*.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] + +# IDE extensions +.vscode/* + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +/*.egg-info +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.log.legacy + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# DotEnv configuration +.env + +# Database +*.db +*.rdb + +# Pycharm +.idea + +# Spyder +.spyproject/ + +# Jupyter NB Checkpoints +.ipynb_checkpoints/ + +# exclude data from source control by default +/data/ + +# Mac OS-specific storage files +.DS_Store + +# vim +*.swp +*.swo + +# Mypy cache +.mypy_cache/ + +# Environments +*.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 36b25458..7be7b1ed 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,6 @@ default_language_version: - python: python3.10.8 + python: python3.11.9 + repos: - repo: 'https://github.com/pre-commit/pre-commit-hooks' rev: v4.4.0 diff --git a/.vscode/settings.json b/.vscode/settings.json index a3a18383..2fb69634 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,5 +3,7 @@ "tests" ], "python.testing.unittestEnabled": false, - "python.testing.pytestEnabled": true + "python.testing.pytestEnabled": true, + "pythonTestExplorer.testFramework": "pytest", + "python.analysis.enablePytestSupport": true } diff --git a/LICENSE b/LICENSE index dcfad2de..c4c2579a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2019 mikaelene - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2019 mikaelene + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dbt/adapters/fabric/fabric_adapter.py b/dbt/adapters/fabric/fabric_adapter.py index 10ca7001..50784f25 100644 --- a/dbt/adapters/fabric/fabric_adapter.py +++ b/dbt/adapters/fabric/fabric_adapter.py @@ -183,6 +183,15 @@ def run_sql_for_tests(self, sql, fetch, conn): finally: conn.transaction_open = False + def render_limited(self) -> str: + rendered = self.render() + if self.limit is None: + return rendered + elif self.limit == 0: + return f"(select * from {rendered} where 1=0) _dbt_top_subq" + else: + return f"(select TOP {self.limit} * from {rendered}) _dbt_top_subq" + @available @classmethod def render_column_constraint(cls, constraint: ColumnLevelConstraint) -> Optional[str]: diff --git a/tests/functional/adapter/test_empty.py b/tests/functional/adapter/test_empty.py new file mode 100644 index 00000000..f1a314da --- /dev/null +++ b/tests/functional/adapter/test_empty.py @@ -0,0 +1,10 @@ +import pytest +from dbt.tests.adapter.empty.test_empty import BaseTestEmpty + +pytest.skip( + reason="render_limited() defaults to dbt-core implementation instead of using Fabric implementation" +) + + +class TestEmpty(BaseTestEmpty): + pass diff --git a/tests/unit/adapters/fabric/test_unit_testing.py b/tests/unit/adapters/fabric/test_unit_testing.py new file mode 100644 index 00000000..32f1b4d9 --- /dev/null +++ b/tests/unit/adapters/fabric/test_unit_testing.py @@ -0,0 +1,90 @@ +import pytest +from dbt.tests.util import run_dbt, write_file + +my_model_sql = """ +select + tested_column from {{ ref('my_upstream_model')}} +""" + +my_upstream_model_sql = """ +select + {sql_value} as tested_column +""" + +# test_my_model_yml = """ +# unit_tests: +# - name: test_my_model +# model: my_model +# given: +# - input: ref('my_upstream_model') +# rows: +# - {{ tested_column: {yaml_value} }} +# expect: +# rows: +# - {{ tested_column: {yaml_value} }} +# """ + +test_my_model_yml = """ +unit_tests: + - name: test_my_model + model: my_model + given: + - input: ref('my_upstream_model') + rows: + - {{ tested_column: {yaml_value} }} + expect: + rows: + - {{ tested_column: {yaml_value} }} +""" + + +class BaseUnitTestingTypes: + @pytest.fixture + def data_types(self): + # sql_value, yaml_value + return [ + ["1", "1"], + ["'1'", "1"], + ["true", "1"], + ["DATE '2020-01-02'", "2020-01-02"], + ["DATETIME2 '2013-11-03 00:00:00-0'", "2013-11-03 00:00:00-0"], + ] + + @pytest.fixture(scope="class") + def models(self): + return { + "my_model.sql": my_model_sql, + "my_upstream_model.sql": my_upstream_model_sql, + "schema.yml": test_my_model_yml, + } + + def test_unit_test_data_type(self, project, data_types): + for sql_value, yaml_value in data_types: + # Write parametrized type value to sql files + write_file( + my_upstream_model_sql.format(sql_value=sql_value), + "models", + "my_upstream_model.sql", + ) + + # Write parametrized type value to unit test yaml definition + write_file( + test_my_model_yml.format(yaml_value=yaml_value), + "models", + "schema.yml", + ) + + results = run_dbt(["run", "--select", "my_upstream_model"]) + assert len(results) == 1 + + try: + run_dbt(["test", "--select", "my_model"]) + except Exception: + raise AssertionError(f"unit test failed when testing model with {sql_value}") + + +@pytest.skip( + reason="Nested CTE's are not supported by Fabric DW. Should able to run this in 6 months" +) +class TestPostgresUnitTestingTypes(BaseUnitTestingTypes): + pass