From 46a3acc1038d30a7a3533de64ba816b1d3a8ec91 Mon Sep 17 00:00:00 2001 From: Doug Beatty <44704949+dbeatty10@users.noreply.github.com> Date: Fri, 13 May 2022 14:34:38 -0600 Subject: [PATCH] Functional testing (#588) * Initial functional testing * Skip BigQuery dateadd for now * Split into one fixture and test per cross-database macro * Move the skip decorator * Scaffolding for fixtures and tests * Functional tests for any_value macro * Remove TODO * Functional tests for bool_or macro * Functional tests for concat macro * Functional tests for date_trunc macro * Functional tests for hash macro * Functional tests for last_day macro * Functional tests for length macro * Functional tests for listagg macro * Functional tests for position macro * Functional tests for replace macro * Functional tests for right macro * Functional tests for safe_cast macro * Functional tests for split_part macro * Missing newline * Conform bool_or macro to actual/expected test pattern * Conform any_value macro to actual/expected test pattern * Functional tests for current_timestamp macro * Remove extraneous newline * Functional tests for current_timestamp_in_utc macro * Functional tests for cast_bool_to_text macro * Functional tests for string_literal macro * Functional tests for escape_single_quotes macro * Functional tests for except macro * Functional tests for intersect macro * Fix scaffolded SQL so that tests can pass * Postgres does not treat integers as booleans without casting * Refactor test case override into the base class * Refactor the two variants for escaping single quotes into two different test cases * Fix functional tests for dateadd macro for BigQuery Co-authored-by: Jeremy Cohen --- .circleci/config.yml | 33 ++++-- .gitignore | 3 + dev-requirements.txt | 3 + pytest.ini | 8 ++ run_functional_test.sh | 13 ++ tests/__init__.py | 0 tests/conftest.py | 98 ++++++++++++++++ .../cross_db_utils/base_cross_db_macro.py | 30 +++++ .../cross_db_utils/fixture_any_value.py | 61 ++++++++++ .../cross_db_utils/fixture_bool_or.py | 63 ++++++++++ .../fixture_cast_bool_to_text.py | 30 +++++ .../cross_db_utils/fixture_concat.py | 36 ++++++ .../cross_db_utils/fixture_cross_db_macro.py | 6 + .../fixture_current_timestamp.py | 20 ++++ .../fixture_current_timestamp_in_utc.py | 20 ++++ .../cross_db_utils/fixture_date_trunc.py | 41 +++++++ .../cross_db_utils/fixture_dateadd.py | 41 +++++++ .../cross_db_utils/fixture_datediff.py | 66 +++++++++++ .../fixture_escape_single_quotes.py | 25 ++++ .../cross_db_utils/fixture_except.py | 65 ++++++++++ .../functional/cross_db_utils/fixture_hash.py | 35 ++++++ .../cross_db_utils/fixture_intersect.py | 59 ++++++++++ .../cross_db_utils/fixture_last_day.py | 40 +++++++ .../cross_db_utils/fixture_length.py | 36 ++++++ .../cross_db_utils/fixture_listagg.py | 111 ++++++++++++++++++ .../cross_db_utils/fixture_position.py | 36 ++++++ .../cross_db_utils/fixture_replace.py | 40 +++++++ .../cross_db_utils/fixture_right.py | 36 ++++++ .../cross_db_utils/fixture_safe_cast.py | 34 ++++++ .../cross_db_utils/fixture_split_part.py | 50 ++++++++ .../cross_db_utils/fixture_string_literal.py | 20 ++++ .../cross_db_utils/fixture_type_bigint.py | 36 ++++++ .../cross_db_utils/fixture_type_boolean.py | 36 ++++++ .../cross_db_utils/fixture_type_float.py | 36 ++++++ .../cross_db_utils/fixture_type_int.py | 36 ++++++ .../cross_db_utils/fixture_type_numeric.py | 36 ++++++ .../cross_db_utils/fixture_type_string.py | 36 ++++++ .../cross_db_utils/fixture_type_timestamp.py | 36 ++++++ .../cross_db_utils/test_any_value.py | 28 +++++ .../functional/cross_db_utils/test_bool_or.py | 28 +++++ .../cross_db_utils/test_cast_bool_to_text.py | 19 +++ .../functional/cross_db_utils/test_concat.py | 24 ++++ .../cross_db_utils/test_current_timestamp.py | 19 +++ .../test_current_timestamp_in_utc.py | 19 +++ .../cross_db_utils/test_date_trunc.py | 24 ++++ .../functional/cross_db_utils/test_dateadd.py | 40 +++++++ .../cross_db_utils/test_datediff.py | 24 ++++ .../test_escape_single_quotes.py | 45 +++++++ .../functional/cross_db_utils/test_except.py | 72 ++++++++++++ tests/functional/cross_db_utils/test_hash.py | 24 ++++ .../cross_db_utils/test_intersect.py | 70 +++++++++++ .../cross_db_utils/test_last_day.py | 24 ++++ .../functional/cross_db_utils/test_length.py | 24 ++++ .../functional/cross_db_utils/test_listagg.py | 28 +++++ .../cross_db_utils/test_position.py | 24 ++++ .../functional/cross_db_utils/test_replace.py | 24 ++++ tests/functional/cross_db_utils/test_right.py | 24 ++++ .../cross_db_utils/test_safe_cast.py | 24 ++++ .../cross_db_utils/test_split_part.py | 24 ++++ .../cross_db_utils/test_string_literal.py | 19 +++ .../cross_db_utils/test_type_bigint.py | 25 ++++ .../cross_db_utils/test_type_boolean.py | 25 ++++ .../cross_db_utils/test_type_float.py | 25 ++++ .../cross_db_utils/test_type_int.py | 25 ++++ .../cross_db_utils/test_type_numeric.py | 25 ++++ .../cross_db_utils/test_type_string.py | 25 ++++ .../cross_db_utils/test_type_timestamp.py | 25 ++++ 67 files changed, 2227 insertions(+), 10 deletions(-) create mode 100644 dev-requirements.txt create mode 100644 pytest.ini create mode 100755 run_functional_test.sh create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/functional/cross_db_utils/base_cross_db_macro.py create mode 100644 tests/functional/cross_db_utils/fixture_any_value.py create mode 100644 tests/functional/cross_db_utils/fixture_bool_or.py create mode 100644 tests/functional/cross_db_utils/fixture_cast_bool_to_text.py create mode 100644 tests/functional/cross_db_utils/fixture_concat.py create mode 100644 tests/functional/cross_db_utils/fixture_cross_db_macro.py create mode 100644 tests/functional/cross_db_utils/fixture_current_timestamp.py create mode 100644 tests/functional/cross_db_utils/fixture_current_timestamp_in_utc.py create mode 100644 tests/functional/cross_db_utils/fixture_date_trunc.py create mode 100644 tests/functional/cross_db_utils/fixture_dateadd.py create mode 100644 tests/functional/cross_db_utils/fixture_datediff.py create mode 100644 tests/functional/cross_db_utils/fixture_escape_single_quotes.py create mode 100644 tests/functional/cross_db_utils/fixture_except.py create mode 100644 tests/functional/cross_db_utils/fixture_hash.py create mode 100644 tests/functional/cross_db_utils/fixture_intersect.py create mode 100644 tests/functional/cross_db_utils/fixture_last_day.py create mode 100644 tests/functional/cross_db_utils/fixture_length.py create mode 100644 tests/functional/cross_db_utils/fixture_listagg.py create mode 100644 tests/functional/cross_db_utils/fixture_position.py create mode 100644 tests/functional/cross_db_utils/fixture_replace.py create mode 100644 tests/functional/cross_db_utils/fixture_right.py create mode 100644 tests/functional/cross_db_utils/fixture_safe_cast.py create mode 100644 tests/functional/cross_db_utils/fixture_split_part.py create mode 100644 tests/functional/cross_db_utils/fixture_string_literal.py create mode 100644 tests/functional/cross_db_utils/fixture_type_bigint.py create mode 100644 tests/functional/cross_db_utils/fixture_type_boolean.py create mode 100644 tests/functional/cross_db_utils/fixture_type_float.py create mode 100644 tests/functional/cross_db_utils/fixture_type_int.py create mode 100644 tests/functional/cross_db_utils/fixture_type_numeric.py create mode 100644 tests/functional/cross_db_utils/fixture_type_string.py create mode 100644 tests/functional/cross_db_utils/fixture_type_timestamp.py create mode 100644 tests/functional/cross_db_utils/test_any_value.py create mode 100644 tests/functional/cross_db_utils/test_bool_or.py create mode 100644 tests/functional/cross_db_utils/test_cast_bool_to_text.py create mode 100644 tests/functional/cross_db_utils/test_concat.py create mode 100644 tests/functional/cross_db_utils/test_current_timestamp.py create mode 100644 tests/functional/cross_db_utils/test_current_timestamp_in_utc.py create mode 100644 tests/functional/cross_db_utils/test_date_trunc.py create mode 100644 tests/functional/cross_db_utils/test_dateadd.py create mode 100644 tests/functional/cross_db_utils/test_datediff.py create mode 100644 tests/functional/cross_db_utils/test_escape_single_quotes.py create mode 100644 tests/functional/cross_db_utils/test_except.py create mode 100644 tests/functional/cross_db_utils/test_hash.py create mode 100644 tests/functional/cross_db_utils/test_intersect.py create mode 100644 tests/functional/cross_db_utils/test_last_day.py create mode 100644 tests/functional/cross_db_utils/test_length.py create mode 100644 tests/functional/cross_db_utils/test_listagg.py create mode 100644 tests/functional/cross_db_utils/test_position.py create mode 100644 tests/functional/cross_db_utils/test_replace.py create mode 100644 tests/functional/cross_db_utils/test_right.py create mode 100644 tests/functional/cross_db_utils/test_safe_cast.py create mode 100644 tests/functional/cross_db_utils/test_split_part.py create mode 100644 tests/functional/cross_db_utils/test_string_literal.py create mode 100644 tests/functional/cross_db_utils/test_type_bigint.py create mode 100644 tests/functional/cross_db_utils/test_type_boolean.py create mode 100644 tests/functional/cross_db_utils/test_type_float.py create mode 100644 tests/functional/cross_db_utils/test_type_int.py create mode 100644 tests/functional/cross_db_utils/test_type_numeric.py create mode 100644 tests/functional/cross_db_utils/test_type_string.py create mode 100644 tests/functional/cross_db_utils/test_type_timestamp.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 74d9f25d..db3529a8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,16 +9,20 @@ jobs: - image: cimg/postgres:9.6 environment: POSTGRES_USER: root + environment: + POSTGRES_TEST_HOST: localhost + POSTGRES_TEST_USER: root + POSTGRES_TEST_PASS: '' + POSTGRES_TEST_PORT: 5432 + POSTGRES_TEST_DBNAME: circle_test + steps: - checkout - run: - name: "Run Tests - Postgres" - environment: - POSTGRES_TEST_HOST: localhost - POSTGRES_TEST_USER: root - POSTGRES_TEST_PASS: '' - POSTGRES_TEST_PORT: 5432 - POSTGRES_TEST_DBNAME: circle_test + name: "Run Functional Tests - Postgres" + command: ./run_functional_test.sh postgres + - run: + name: "Run OG Tests - Postgres" command: ./run_test.sh postgres - store_artifacts: path: ./logs @@ -29,7 +33,10 @@ jobs: steps: - checkout - run: - name: "Run Tests - Redshift" + name: "Run Functional Tests - Redshift" + command: ./run_functional_test.sh redshift + - run: + name: "Run OG Tests - Redshift" command: ./run_test.sh redshift - store_artifacts: path: ./logs @@ -40,7 +47,10 @@ jobs: steps: - checkout - run: - name: "Run Tests - Snowflake" + name: "Run Functional Tests - Snowflake" + command: ./run_functional_test.sh snowflake + - run: + name: "Run OG Tests - Snowflake" command: ./run_test.sh snowflake - store_artifacts: path: ./logs @@ -56,7 +66,10 @@ jobs: name: "Set up credentials" command: echo $BIGQUERY_SERVICE_ACCOUNT_JSON > ${HOME}/bigquery-service-key.json - run: - name: "Run Tests - BigQuery" + name: "Run Functional Tests - BigQuery" + command: ./run_functional_test.sh bigquery + - run: + name: "Run OG Tests - BigQuery" command: ./run_test.sh bigquery - store_artifacts: path: ./logs diff --git a/.gitignore b/.gitignore index 49ca155a..d155937f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,6 @@ dbt_modules/ dbt_packages/ logs/ venv/ +env/ +test.env +__pycache__ \ No newline at end of file diff --git a/dev-requirements.txt b/dev-requirements.txt new file mode 100644 index 00000000..92c07876 --- /dev/null +++ b/dev-requirements.txt @@ -0,0 +1,3 @@ +pytest +pytest-dotenv +dbt-tests-adapter diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..a81f2a6b --- /dev/null +++ b/pytest.ini @@ -0,0 +1,8 @@ +[pytest] +filterwarnings = + ignore:.*'soft_unicode' has been renamed to 'soft_str'*:DeprecationWarning + ignore:unclosed file .*:ResourceWarning +env_files = + test.env +testpaths = + tests/functional \ No newline at end of file diff --git a/run_functional_test.sh b/run_functional_test.sh new file mode 100755 index 00000000..11140e9b --- /dev/null +++ b/run_functional_test.sh @@ -0,0 +1,13 @@ +#!/bin/bash +VENV="venv/bin/activate" + +if [[ ! -f $VENV ]]; then + python3 -m venv venv + . $VENV + + pip install --upgrade pip setuptools + pip install --pre "dbt-$1" -r dev-requirements.txt +fi + +. $VENV +python3 -m pytest tests/functional --profile $1 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..4858b21f --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,98 @@ +import pytest +import os + +pytest_plugins = ["dbt.tests.fixtures.project"] + + +def pytest_addoption(parser): + parser.addoption("--profile", action="store", default="apache_spark", type=str) + + +# Using @pytest.mark.skip_adapter('apache_spark') uses the 'skip_by_adapter_type' +# autouse fixture below +def pytest_configure(config): + config.addinivalue_line( + "markers", + "skip_profile(profile): skip test for the given profile", + ) + config.addinivalue_line( + "markers", + "only_profile(profile): only test the given profile", + ) + + +@pytest.fixture(scope="session") +def dbt_profile_target(request): + profile_type = request.config.getoption("--profile") + if profile_type == "postgres": + target = postgres_target() + elif profile_type == "redshift": + target = redshift_target() + elif profile_type == "snowflake": + target = snowflake_target() + elif profile_type == "bigquery": + target = bigquery_target() + else: + raise ValueError(f"Invalid profile type '{profile_type}'") + return target + + +def postgres_target(): + return { + "type": "postgres", + "host": os.getenv('POSTGRES_TEST_HOST'), + "user": os.getenv('POSTGRES_TEST_USER'), + "pass": os.getenv('POSTGRES_TEST_PASS'), + "port": int(os.getenv('POSTGRES_TEST_PORT')), + "dbname": os.getenv('POSTGRES_TEST_DBNAME'), + } + + +def redshift_target(): + return { + "type": "redshift", + "host": os.getenv('REDSHIFT_TEST_HOST'), + "user": os.getenv('REDSHIFT_TEST_USER'), + "pass": os.getenv('REDSHIFT_TEST_PASS'), + "port": int(os.getenv('REDSHIFT_TEST_PORT')), + "dbname": os.getenv('REDSHIFT_TEST_DBNAME'), + } + + +def bigquery_target(): + return { + "type": "bigquery", + "method": "service-account", + "keyfile": os.getenv('BIGQUERY_SERVICE_KEY_PATH'), + "project": os.getenv('BIGQUERY_TEST_DATABASE'), + } + + +def snowflake_target(): + return { + "type": "snowflake", + "account": os.getenv('SNOWFLAKE_TEST_ACCOUNT'), + "user": os.getenv('SNOWFLAKE_TEST_USER'), + "password": os.getenv('SNOWFLAKE_TEST_PASSWORD'), + "role": os.getenv('SNOWFLAKE_TEST_ROLE'), + "database": os.getenv('SNOWFLAKE_TEST_DATABASE'), + "warehouse": os.getenv('SNOWFLAKE_TEST_WAREHOUSE'), + } + + +@pytest.fixture(autouse=True) +def skip_by_profile_type(request): + profile_type = request.config.getoption("--profile") + if request.node.get_closest_marker("skip_profile"): + for skip_profile_type in request.node.get_closest_marker("skip_profile").args: + if skip_profile_type == profile_type: + pytest.skip("skipped on '{profile_type}' profile") + + +@pytest.fixture(autouse=True) +def only_profile_type(request): + profile_type = request.config.getoption("--profile") + if request.node.get_closest_marker("only_profile"): + for only_profile_type in request.node.get_closest_marker("only_profile").args: + if only_profile_type != profile_type: + pytest.skip("skipped on '{profile_type}' profile") diff --git a/tests/functional/cross_db_utils/base_cross_db_macro.py b/tests/functional/cross_db_utils/base_cross_db_macro.py new file mode 100644 index 00000000..a504aaf5 --- /dev/null +++ b/tests/functional/cross_db_utils/base_cross_db_macro.py @@ -0,0 +1,30 @@ +import os +import pytest +from dbt.tests.util import run_dbt +from tests.functional.cross_db_utils.fixture_cross_db_macro import ( + macros__test_assert_equal_sql, +) + + +class BaseCrossDbMacro: + # install this repo as a package! + @pytest.fixture(scope="class") + def packages(self): + return {"packages": [{"local": os.getcwd()}]} + + # setup + @pytest.fixture(scope="class") + def macros(self): + return {"test_assert_equal.sql": macros__test_assert_equal_sql} + + # each child class will reimplement 'models' + 'seeds' + def seeds(self): + return {} + + def models(self): + return {} + + # actual test sequence + def test_build_assert_equal(self, project): + run_dbt(['deps']) + run_dbt(['build']) # seed, model, test -- all handled by dbt diff --git a/tests/functional/cross_db_utils/fixture_any_value.py b/tests/functional/cross_db_utils/fixture_any_value.py new file mode 100644 index 00000000..81ac11d5 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_any_value.py @@ -0,0 +1,61 @@ + +# any_value + +seeds__data_any_value_csv = """id,key_name,static_col +1,abc,dbt +2,abc,dbt +3,jkl,dbt +4,jkl,dbt +5,jkl,dbt +6,xyz,test +""" + + +seeds__data_any_value_expected_csv = """key_name,static_col,num_rows +abc,dbt,2 +jkl,dbt,3 +xyz,test,1 +""" + + +models__test_any_value_sql = """ +with data as ( + + select * from {{ ref('data_any_value') }} + +), + +data_output as ( + + select * from {{ ref('data_any_value_expected') }} + +), + +calculate as ( + select + key_name, + {{ dbt_utils.any_value('static_col') }} as static_col, + count(id) as num_rows + from data + group by key_name +) + +select + calculate.num_rows as actual, + data_output.num_rows as expected +from calculate +left join data_output +on calculate.key_name = data_output.key_name +and calculate.static_col = data_output.static_col +""" + + +models__test_any_value_yml = """ +version: 2 +models: + - name: test_any_value + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_bool_or.py b/tests/functional/cross_db_utils/fixture_bool_or.py new file mode 100644 index 00000000..ca76a54a --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_bool_or.py @@ -0,0 +1,63 @@ + +# bool_or + +seeds__data_bool_or_csv = """key,val1,val2 +abc,1,1 +abc,1,0 +def,1,0 +hij,1,1 +hij,1, +klm,1,0 +klm,1, +""" + + +seeds__data_bool_or_expected_csv = """key,value +abc,true +def,false +hij,true +klm,false +""" + + +models__test_bool_or_sql = """ +with data as ( + + select * from {{ ref('data_bool_or') }} + +), + +data_output as ( + + select * from {{ ref('data_bool_or_expected') }} + +), + +calculate as ( + + select + key, + {{ dbt_utils.bool_or('val1 = val2') }} as value + from data + group by key + +) + +select + calculate.value as actual, + data_output.value as expected +from calculate +left join data_output +on calculate.key = data_output.key +""" + + +models__test_bool_or_yml = """ +version: 2 +models: + - name: test_bool_or + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_cast_bool_to_text.py b/tests/functional/cross_db_utils/fixture_cast_bool_to_text.py new file mode 100644 index 00000000..acdf13e0 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_cast_bool_to_text.py @@ -0,0 +1,30 @@ + +# cast_bool_to_text + +models__test_cast_bool_to_text_sql = """ +with data as ( + + select 0=1 as input, 'false' as expected union all + select 1=1 as input, 'true' as expected union all + select null as input, null as expected + +) + +select + + {{ dbt_utils.cast_bool_to_text("input") }} as actual, + expected + +from data +""" + + +models__test_cast_bool_to_text_yml = """ +version: 2 +models: + - name: test_cast_bool_to_text + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_concat.py b/tests/functional/cross_db_utils/fixture_concat.py new file mode 100644 index 00000000..778d8bd3 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_concat.py @@ -0,0 +1,36 @@ + + +# concat + +seeds__data_concat_csv = """input_1,input_2,output +a,b,ab +a,,a +,b,b +,, +""" + + +models__test_concat_sql = """ +with data as ( + + select * from {{ ref('data_concat') }} + +) + +select + {{ dbt_utils.concat(['input_1', 'input_2']) }} as actual, + output as expected + +from data +""" + + +models__test_concat_yml = """ +version: 2 +models: + - name: test_concat + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_cross_db_macro.py b/tests/functional/cross_db_utils/fixture_cross_db_macro.py new file mode 100644 index 00000000..76fdb0fb --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_cross_db_macro.py @@ -0,0 +1,6 @@ +macros__test_assert_equal_sql = """ +{% test assert_equal(model, actual, expected) %} +select * from {{ model }} where {{ actual }} != {{ expected }} + +{% endtest %} +""" diff --git a/tests/functional/cross_db_utils/fixture_current_timestamp.py b/tests/functional/cross_db_utils/fixture_current_timestamp.py new file mode 100644 index 00000000..dcd38aa2 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_current_timestamp.py @@ -0,0 +1,20 @@ + +# current_timestamp + +# TODO how can we test this better? +models__test_current_timestamp_sql = """ +select + {{ dbt_utils.current_timestamp() }} as actual, + {{ dbt_utils.current_timestamp() }} as expected +""" + + +models__test_current_timestamp_yml = """ +version: 2 +models: + - name: test_current_timestamp + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_current_timestamp_in_utc.py b/tests/functional/cross_db_utils/fixture_current_timestamp_in_utc.py new file mode 100644 index 00000000..61caef35 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_current_timestamp_in_utc.py @@ -0,0 +1,20 @@ + +# current_timestamp_in_utc + +# TODO how can we test this better? +models__test_current_timestamp_in_utc_sql = """ +select + {{ dbt_utils.current_timestamp_in_utc() }} as actual, + {{ dbt_utils.current_timestamp_in_utc() }} as expected +""" + + +models__test_current_timestamp_in_utc_yml = """ +version: 2 +models: + - name: test_current_timestamp_in_utc + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_date_trunc.py b/tests/functional/cross_db_utils/fixture_date_trunc.py new file mode 100644 index 00000000..91eb5c23 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_date_trunc.py @@ -0,0 +1,41 @@ + +# date_trunc + +seeds__data_date_trunc_csv = """updated_at,day,month +2018-01-05 12:00:00,2018-01-05,2018-01-01 +,, +""" + + +models__test_date_trunc_sql = """ +with data as ( + + select * from {{ ref('data_date_trunc') }} + +) + +select + cast({{dbt_utils.date_trunc('day', 'updated_at') }} as date) as actual, + day as expected + +from data + +union all + +select + cast({{ dbt_utils.date_trunc('month', 'updated_at') }} as date) as actual, + month as expected + +from data +""" + + +models__test_date_trunc_yml = """ +version: 2 +models: + - name: test_date_trunc + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_dateadd.py b/tests/functional/cross_db_utils/fixture_dateadd.py new file mode 100644 index 00000000..95d8cce5 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_dateadd.py @@ -0,0 +1,41 @@ + +# dateadd + +seeds__data_dateadd_csv = """from_time,interval_length,datepart,result +2018-01-01 01:00:00,1,day,2018-01-02 01:00:00 +2018-01-01 01:00:00,1,month,2018-02-01 01:00:00 +2018-01-01 01:00:00,1,year,2019-01-01 01:00:00 +2018-01-01 01:00:00,1,hour,2018-01-01 02:00:00 +,1,day, +""" + + +models__test_dateadd_sql = """ +with data as ( + + select * from {{ ref('data_dateadd') }} + +) + +select + case + when datepart = 'hour' then cast({{ dbt_utils.dateadd('hour', 'interval_length', 'from_time') }} as {{dbt_utils.type_timestamp()}}) + when datepart = 'day' then cast({{ dbt_utils.dateadd('day', 'interval_length', 'from_time') }} as {{dbt_utils.type_timestamp()}}) + when datepart = 'month' then cast({{ dbt_utils.dateadd('month', 'interval_length', 'from_time') }} as {{dbt_utils.type_timestamp()}}) + when datepart = 'year' then cast({{ dbt_utils.dateadd('year', 'interval_length', 'from_time') }} as {{dbt_utils.type_timestamp()}}) + else null + end as actual, + result as expected + +from data +""" + +models__test_dateadd_yml = """ +version: 2 +models: + - name: test_dateadd + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_datediff.py b/tests/functional/cross_db_utils/fixture_datediff.py new file mode 100644 index 00000000..0ac216a6 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_datediff.py @@ -0,0 +1,66 @@ + +# datediff + +seeds__data_datediff_csv = """first_date,second_date,datepart,result +2018-01-01 01:00:00,2018-01-02 01:00:00,day,1 +2018-01-01 01:00:00,2018-02-01 01:00:00,month,1 +2018-01-01 01:00:00,2019-01-01 01:00:00,year,1 +2018-01-01 01:00:00,2018-01-01 02:00:00,hour,1 +2018-01-01 01:00:00,2018-01-01 02:01:00,minute,61 +2018-01-01 01:00:00,2018-01-01 02:00:01,second,3601 +2019-12-31 00:00:00,2019-12-27 00:00:00,week,-1 +2019-12-31 00:00:00,2019-12-30 00:00:00,week,0 +2019-12-31 00:00:00,2020-01-02 00:00:00,week,0 +2019-12-31 00:00:00,2020-01-06 02:00:00,week,1 +,2018-01-01 02:00:00,hour, +2018-01-01 02:00:00,,hour, +""" + + +models__test_datediff_sql = """ +with data as ( + + select * from {{ ref('data_datediff') }} + +) + +select + + case + when datepart = 'second' then {{ dbt_utils.datediff('first_date', 'second_date', 'second') }} + when datepart = 'minute' then {{ dbt_utils.datediff('first_date', 'second_date', 'minute') }} + when datepart = 'hour' then {{ dbt_utils.datediff('first_date', 'second_date', 'hour') }} + when datepart = 'day' then {{ dbt_utils.datediff('first_date', 'second_date', 'day') }} + when datepart = 'week' then {{ dbt_utils.datediff('first_date', 'second_date', 'week') }} + when datepart = 'month' then {{ dbt_utils.datediff('first_date', 'second_date', 'month') }} + when datepart = 'year' then {{ dbt_utils.datediff('first_date', 'second_date', 'year') }} + else null + end as actual, + result as expected + +from data + +-- Also test correct casting of literal values. + +union all select {{ dbt_utils.datediff("'1999-12-31 23:59:59.999999'", "'2000-01-01 00:00:00.000000'", "microsecond") }} as actual, 1 as expected +union all select {{ dbt_utils.datediff("'1999-12-31 23:59:59.999999'", "'2000-01-01 00:00:00.000000'", "millisecond") }} as actual, 1 as expected +union all select {{ dbt_utils.datediff("'1999-12-31 23:59:59.999999'", "'2000-01-01 00:00:00.000000'", "second") }} as actual, 1 as expected +union all select {{ dbt_utils.datediff("'1999-12-31 23:59:59.999999'", "'2000-01-01 00:00:00.000000'", "minute") }} as actual, 1 as expected +union all select {{ dbt_utils.datediff("'1999-12-31 23:59:59.999999'", "'2000-01-01 00:00:00.000000'", "hour") }} as actual, 1 as expected +union all select {{ dbt_utils.datediff("'1999-12-31 23:59:59.999999'", "'2000-01-01 00:00:00.000000'", "day") }} as actual, 1 as expected +union all select {{ dbt_utils.datediff("'1999-12-31 23:59:59.999999'", "'2000-01-03 00:00:00.000000'", "week") }} as actual, 1 as expected +union all select {{ dbt_utils.datediff("'1999-12-31 23:59:59.999999'", "'2000-01-01 00:00:00.000000'", "month") }} as actual, 1 as expected +union all select {{ dbt_utils.datediff("'1999-12-31 23:59:59.999999'", "'2000-01-01 00:00:00.000000'", "quarter") }} as actual, 1 as expected +union all select {{ dbt_utils.datediff("'1999-12-31 23:59:59.999999'", "'2000-01-01 00:00:00.000000'", "year") }} as actual, 1 as expected +""" + + +models__test_datediff_yml = """ +version: 2 +models: + - name: test_datediff + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_escape_single_quotes.py b/tests/functional/cross_db_utils/fixture_escape_single_quotes.py new file mode 100644 index 00000000..3264d056 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_escape_single_quotes.py @@ -0,0 +1,25 @@ + +# escape_single_quotes + +models__test_escape_single_quotes_quote_sql = """ +select '{{ dbt_utils.escape_single_quotes("they're") }}' as actual, 'they''re' as expected union all +select '{{ dbt_utils.escape_single_quotes("they are") }}' as actual, 'they are' as expected +""" + + +# The expected literal is 'they\'re'. The second backslash is to escape it from Python. +models__test_escape_single_quotes_backslash_sql = """ +select '{{ dbt_utils.escape_single_quotes("they're") }}' as actual, 'they\\'re' as expected union all +select '{{ dbt_utils.escape_single_quotes("they are") }}' as actual, 'they are' as expected +""" + + +models__test_escape_single_quotes_yml = """ +version: 2 +models: + - name: test_escape_single_quotes + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_except.py b/tests/functional/cross_db_utils/fixture_except.py new file mode 100644 index 00000000..013b7943 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_except.py @@ -0,0 +1,65 @@ + +# except + +seeds__data_except_a_csv = """id +1 +2 +3 +""" + +seeds__data_except_b_csv = """id +3 +4 +5 +""" + +seeds__data_except_a_minus_b_csv = """id +1 +2 +""" + +seeds__data_except_b_minus_a_csv = """id +4 +5 +""" + +models__data_except_empty_sql = """ +select * from {{ ref('data_except_a') }} +where 0=1 +""" + +models__test_except_a_minus_b_sql = """ +select * from {{ ref('data_except_a') }} +{{ dbt_utils.except() }} +select * from {{ ref('data_except_b') }} +""" + +models__test_except_b_minus_a_sql = """ +select * from {{ ref('data_except_b') }} +{{ dbt_utils.except() }} +select * from {{ ref('data_except_a') }} +""" + +models__test_except_a_minus_a_sql = """ +select * from {{ ref('data_except_a') }} +{{ dbt_utils.except() }} +select * from {{ ref('data_except_a') }} +""" + +models__test_except_a_minus_empty_sql = """ +select * from {{ ref('data_except_a') }} +{{ dbt_utils.except() }} +select * from {{ ref('data_except_empty') }} +""" + +models__test_except_empty_minus_a_sql = """ +select * from {{ ref('data_except_empty') }} +{{ dbt_utils.except() }} +select * from {{ ref('data_except_a') }} +""" + +models__test_except_empty_minus_empty_sql = """ +select * from {{ ref('data_except_empty') }} +{{ dbt_utils.except() }} +select * from {{ ref('data_except_empty') }} +""" diff --git a/tests/functional/cross_db_utils/fixture_hash.py b/tests/functional/cross_db_utils/fixture_hash.py new file mode 100644 index 00000000..1f0b5543 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_hash.py @@ -0,0 +1,35 @@ + +# hash + +seeds__data_hash_csv = """input_1,output +ab,187ef4436122d1cc2f40dc2b92f0eba0 +a,0cc175b9c0f1b6a831c399e269772661 +1,c4ca4238a0b923820dcc509a6f75849b +,d41d8cd98f00b204e9800998ecf8427e +""" + + +models__test_hash_sql = """ +with data as ( + + select * from {{ ref('data_hash') }} + +) + +select + {{ dbt_utils.hash('input_1') }} as actual, + output as expected + +from data +""" + + +models__test_hash_yml = """ +version: 2 +models: + - name: test_hash + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_intersect.py b/tests/functional/cross_db_utils/fixture_intersect.py new file mode 100644 index 00000000..934d93af --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_intersect.py @@ -0,0 +1,59 @@ + +# intersect + +seeds__data_intersect_a_csv = """id +1 +2 +3 +""" + +seeds__data_intersect_b_csv = """id +3 +4 +5 +""" + +seeds__data_intersect_a_overlap_b_csv = """id +3 +""" + +models__data_intersect_empty_sql = """ +select * from {{ ref('data_intersect_a') }} +where 0=1 +""" + +models__test_intersect_a_overlap_b_sql = """ +select * from {{ ref('data_intersect_a') }} +{{ dbt_utils.intersect() }} +select * from {{ ref('data_intersect_b') }} +""" + +models__test_intersect_b_overlap_a_sql = """ +select * from {{ ref('data_intersect_b') }} +{{ dbt_utils.intersect() }} +select * from {{ ref('data_intersect_a') }} +""" + +models__test_intersect_a_overlap_a_sql = """ +select * from {{ ref('data_intersect_a') }} +{{ dbt_utils.intersect() }} +select * from {{ ref('data_intersect_a') }} +""" + +models__test_intersect_a_overlap_empty_sql = """ +select * from {{ ref('data_intersect_a') }} +{{ dbt_utils.intersect() }} +select * from {{ ref('data_intersect_empty') }} +""" + +models__test_intersect_empty_overlap_a_sql = """ +select * from {{ ref('data_intersect_empty') }} +{{ dbt_utils.intersect() }} +select * from {{ ref('data_intersect_a') }} +""" + +models__test_intersect_empty_overlap_empty_sql = """ +select * from {{ ref('data_intersect_empty') }} +{{ dbt_utils.intersect() }} +select * from {{ ref('data_intersect_empty') }} +""" diff --git a/tests/functional/cross_db_utils/fixture_last_day.py b/tests/functional/cross_db_utils/fixture_last_day.py new file mode 100644 index 00000000..72fbd352 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_last_day.py @@ -0,0 +1,40 @@ + +# last_day + +seeds__data_last_day_csv = """date_day,date_part,result +2018-01-02,month,2018-01-31 +2018-01-02,quarter,2018-03-31 +2018-01-02,year,2018-12-31 +,month, +""" + + +models__test_last_day_sql = """ +with data as ( + + select * from {{ ref('data_last_day') }} + +) + +select + case + when date_part = 'month' then {{ dbt_utils.last_day('date_day', 'month') }} + when date_part = 'quarter' then {{ dbt_utils.last_day('date_day', 'quarter') }} + when date_part = 'year' then {{ dbt_utils.last_day('date_day', 'year') }} + else null + end as actual, + result as expected + +from data +""" + + +models__test_last_day_yml = """ +version: 2 +models: + - name: test_last_day + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_length.py b/tests/functional/cross_db_utils/fixture_length.py new file mode 100644 index 00000000..e6264741 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_length.py @@ -0,0 +1,36 @@ + +# length + +seeds__data_length_csv = """expression,output +abcdef,6 +fishtown,8 +december,8 +www.google.com/path,19 +""" + + +models__test_length_sql = """ +with data as ( + + select * from {{ ref('data_length') }} + +) + +select + + {{ dbt_utils.length('expression') }} as actual, + output as expected + +from data +""" + + +models__test_length_yml = """ +version: 2 +models: + - name: test_length + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_listagg.py b/tests/functional/cross_db_utils/fixture_listagg.py new file mode 100644 index 00000000..9a2380d6 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_listagg.py @@ -0,0 +1,111 @@ + +# listagg + +seeds__data_listagg_csv = """group_col,string_text,order_col +1,a,1 +1,b,2 +1,c,3 +2,a,2 +2,1,1 +2,p,3 +3,g,1 +3,g,2 +3,g,3 +""" + + +seeds__data_listagg_output_csv = """group_col,expected,version +1,"a_|_b_|_c",bottom_ordered +2,"1_|_a_|_p",bottom_ordered +3,"g_|_g_|_g",bottom_ordered +1,"a_|_b",bottom_ordered_limited +2,"1_|_a",bottom_ordered_limited +3,"g_|_g",bottom_ordered_limited +3,"g, g, g",comma_whitespace_unordered +3,"g",distinct_comma +3,"g,g,g",no_params +""" + + +models__test_listagg_sql = """ +with data as ( + + select * from {{ ref('data_listagg') }} + +), + +data_output as ( + + select * from {{ ref('data_listagg_output') }} + +), + +calculate as ( + + select + group_col, + {{ dbt_utils.listagg('string_text', "'_|_'", "order by order_col") }} as actual, + 'bottom_ordered' as version + from data + group by group_col + + union all + + select + group_col, + {{ dbt_utils.listagg('string_text', "'_|_'", "order by order_col", 2) }} as actual, + 'bottom_ordered_limited' as version + from data + group by group_col + + union all + + select + group_col, + {{ dbt_utils.listagg('string_text', "', '") }} as actual, + 'comma_whitespace_unordered' as version + from data + where group_col = 3 + group by group_col + + union all + + select + group_col, + {{ dbt_utils.listagg('DISTINCT string_text', "','") }} as actual, + 'distinct_comma' as version + from data + where group_col = 3 + group by group_col + + union all + + select + group_col, + {{ dbt_utils.listagg('string_text') }} as actual, + 'no_params' as version + from data + where group_col = 3 + group by group_col + +) + +select + calculate.actual, + data_output.expected +from calculate +left join data_output +on calculate.group_col = data_output.group_col +and calculate.version = data_output.version +""" + + +models__test_listagg_yml = """ +version: 2 +models: + - name: test_listagg + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_position.py b/tests/functional/cross_db_utils/fixture_position.py new file mode 100644 index 00000000..9f66c6a7 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_position.py @@ -0,0 +1,36 @@ + +# position + +seeds__data_position_csv = """substring_text,string_text,result +def,abcdef,4 +land,earth,0 +town,fishtown,5 +ember,december,4 +""" + + +models__test_position_sql = """ +with data as ( + + select * from {{ ref('data_position') }} + +) + +select + + {{ dbt_utils.position('substring_text', 'string_text') }} as actual, + result as expected + +from data +""" + + +models__test_position_yml = """ +version: 2 +models: + - name: test_position + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_replace.py b/tests/functional/cross_db_utils/fixture_replace.py new file mode 100644 index 00000000..c9565016 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_replace.py @@ -0,0 +1,40 @@ + +# replace + +seeds__data_replace_csv = """string_text,search_chars,replace_chars,result +a,a,b,b +http://google.com,http://,"",google.com +""" + + +models__test_replace_sql = """ +with data as ( + + select + + *, + coalesce(search_chars, '') as old_chars, + coalesce(replace_chars, '') as new_chars + + from {{ ref('data_replace') }} + +) + +select + + {{ dbt_utils.replace('string_text', 'old_chars', 'new_chars') }} as actual, + result as expected + +from data +""" + + +models__test_replace_yml = """ +version: 2 +models: + - name: test_replace + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_right.py b/tests/functional/cross_db_utils/fixture_right.py new file mode 100644 index 00000000..face6ca0 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_right.py @@ -0,0 +1,36 @@ + +# right + +seeds__data_right_csv = """string_text,length_expression,output +abcdef,3,def +fishtown,4,town +december,5,ember +december,0, +""" + + +models__test_right_sql = """ +with data as ( + + select * from {{ ref('data_right') }} + +) + +select + + {{ dbt_utils.right('string_text', 'length_expression') }} as actual, + coalesce(output, '') as expected + +from data +""" + + +models__test_right_yml = """ +version: 2 +models: + - name: test_right + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_safe_cast.py b/tests/functional/cross_db_utils/fixture_safe_cast.py new file mode 100644 index 00000000..918d3bb7 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_safe_cast.py @@ -0,0 +1,34 @@ + +# safe_cast + +seeds__data_safe_cast_csv = """field,output +abc,abc +123,123 +, +""" + + +models__test_safe_cast_sql = """ +with data as ( + + select * from {{ ref('data_safe_cast') }} + +) + +select + {{ dbt_utils.safe_cast('field', dbt_utils.type_string()) }} as actual, + output as expected + +from data +""" + + +models__test_safe_cast_yml = """ +version: 2 +models: + - name: test_safe_cast + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_split_part.py b/tests/functional/cross_db_utils/fixture_split_part.py new file mode 100644 index 00000000..ba65a2ab --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_split_part.py @@ -0,0 +1,50 @@ + +# split_part + +seeds__data_split_part_csv = """parts,split_on,result_1,result_2,result_3 +a|b|c,|,a,b,c +1|2|3,|,1,2,3 +,|,,, +""" + + +models__test_split_part_sql = """ +with data as ( + + select * from {{ ref('data_split_part') }} + +) + +select + {{ dbt_utils.split_part('parts', 'split_on', 1) }} as actual, + result_1 as expected + +from data + +union all + +select + {{ dbt_utils.split_part('parts', 'split_on', 2) }} as actual, + result_2 as expected + +from data + +union all + +select + {{ dbt_utils.split_part('parts', 'split_on', 3) }} as actual, + result_3 as expected + +from data +""" + + +models__test_split_part_yml = """ +version: 2 +models: + - name: test_split_part + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_string_literal.py b/tests/functional/cross_db_utils/fixture_string_literal.py new file mode 100644 index 00000000..188208a4 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_string_literal.py @@ -0,0 +1,20 @@ + +# string_literal + +models__test_string_literal_sql = """ +select {{ dbt_utils.string_literal("abc") }} as actual, 'abc' as expected union all +select {{ dbt_utils.string_literal("1") }} as actual, '1' as expected union all +select {{ dbt_utils.string_literal("") }} as actual, '' as expected union all +select {{ dbt_utils.string_literal(none) }} as actual, 'None' as expected +""" + + +models__test_string_literal_yml = """ +version: 2 +models: + - name: test_string_literal + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_type_bigint.py b/tests/functional/cross_db_utils/fixture_type_bigint.py new file mode 100644 index 00000000..c1f3ba9f --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_type_bigint.py @@ -0,0 +1,36 @@ + + +# type_bigint + +# TODO - implement expected results here +seeds__data_type_bigint_csv = """todo,result +TODO,1 +""" + + +models__test_type_bigint_sql = """ +with data as ( + + select * from {{ ref('data_type_bigint') }} + +) + +-- TODO - implement actual logic here +select + + 1 as actual, + 1 as expected + +from data +""" + + +models__test_type_bigint_yml = """ +version: 2 +models: + - name: test_type_bigint + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_type_boolean.py b/tests/functional/cross_db_utils/fixture_type_boolean.py new file mode 100644 index 00000000..fbde496b --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_type_boolean.py @@ -0,0 +1,36 @@ + + +# type_boolean + +# TODO - implement expected results here +seeds__data_type_boolean_csv = """todo,result +TODO,1 +""" + + +models__test_type_boolean_sql = """ +with data as ( + + select * from {{ ref('data_type_boolean') }} + +) + +-- TODO - implement actual logic here +select + + 1 as actual, + 1 as expected + +from data +""" + + +models__test_type_boolean_yml = """ +version: 2 +models: + - name: test_type_boolean + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_type_float.py b/tests/functional/cross_db_utils/fixture_type_float.py new file mode 100644 index 00000000..9333f637 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_type_float.py @@ -0,0 +1,36 @@ + + +# type_float + +# TODO - implement expected results here +seeds__data_type_float_csv = """todo,result +TODO,1 +""" + + +models__test_type_float_sql = """ +with data as ( + + select * from {{ ref('data_type_float') }} + +) + +-- TODO - implement actual logic here +select + + 1 as actual, + 1 as expected + +from data +""" + + +models__test_type_float_yml = """ +version: 2 +models: + - name: test_type_float + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_type_int.py b/tests/functional/cross_db_utils/fixture_type_int.py new file mode 100644 index 00000000..982a401e --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_type_int.py @@ -0,0 +1,36 @@ + + +# type_int + +# TODO - implement expected results here +seeds__data_type_int_csv = """todo,result +TODO,1 +""" + + +models__test_type_int_sql = """ +with data as ( + + select * from {{ ref('data_type_int') }} + +) + +-- TODO - implement actual logic here +select + + 1 as actual, + 1 as expected + +from data +""" + + +models__test_type_int_yml = """ +version: 2 +models: + - name: test_type_int + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_type_numeric.py b/tests/functional/cross_db_utils/fixture_type_numeric.py new file mode 100644 index 00000000..a4929cbd --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_type_numeric.py @@ -0,0 +1,36 @@ + + +# type_numeric + +# TODO - implement expected results here +seeds__data_type_numeric_csv = """todo,result +TODO,1 +""" + + +models__test_type_numeric_sql = """ +with data as ( + + select * from {{ ref('data_type_numeric') }} + +) + +-- TODO - implement actual logic here +select + + 1 as actual, + 1 as expected + +from data +""" + + +models__test_type_numeric_yml = """ +version: 2 +models: + - name: test_type_numeric + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_type_string.py b/tests/functional/cross_db_utils/fixture_type_string.py new file mode 100644 index 00000000..38a00016 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_type_string.py @@ -0,0 +1,36 @@ + + +# type_string + +# TODO - implement expected results here +seeds__data_type_string_csv = """todo,result +TODO,1 +""" + + +models__test_type_string_sql = """ +with data as ( + + select * from {{ ref('data_type_string') }} + +) + +-- TODO - implement actual logic here +select + + 1 as actual, + 1 as expected + +from data +""" + + +models__test_type_string_yml = """ +version: 2 +models: + - name: test_type_string + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/fixture_type_timestamp.py b/tests/functional/cross_db_utils/fixture_type_timestamp.py new file mode 100644 index 00000000..3b28adc8 --- /dev/null +++ b/tests/functional/cross_db_utils/fixture_type_timestamp.py @@ -0,0 +1,36 @@ + + +# type_timestamp + +# TODO - implement expected results here +seeds__data_type_timestamp_csv = """todo,result +TODO,1 +""" + + +models__test_type_timestamp_sql = """ +with data as ( + + select * from {{ ref('data_type_timestamp') }} + +) + +-- TODO - implement actual logic here +select + + 1 as actual, + 1 as expected + +from data +""" + + +models__test_type_timestamp_yml = """ +version: 2 +models: + - name: test_type_timestamp + tests: + - assert_equal: + actual: actual + expected: expected +""" diff --git a/tests/functional/cross_db_utils/test_any_value.py b/tests/functional/cross_db_utils/test_any_value.py new file mode 100644 index 00000000..f0a3acd6 --- /dev/null +++ b/tests/functional/cross_db_utils/test_any_value.py @@ -0,0 +1,28 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_any_value import ( + seeds__data_any_value_csv, + seeds__data_any_value_expected_csv, + models__test_any_value_sql, + models__test_any_value_yml, +) + + +class BaseAnyValue(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return { + "data_any_value.csv": seeds__data_any_value_csv, + "data_any_value_expected.csv": seeds__data_any_value_expected_csv, + } + + @pytest.fixture(scope="class") + def models(self): + return { + "test_any_value.yml": models__test_any_value_yml, + "test_any_value.sql": models__test_any_value_sql, + } + + +class TestAnyValue(BaseAnyValue): + pass diff --git a/tests/functional/cross_db_utils/test_bool_or.py b/tests/functional/cross_db_utils/test_bool_or.py new file mode 100644 index 00000000..c8c7a569 --- /dev/null +++ b/tests/functional/cross_db_utils/test_bool_or.py @@ -0,0 +1,28 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_bool_or import ( + seeds__data_bool_or_csv, + seeds__data_bool_or_expected_csv, + models__test_bool_or_sql, + models__test_bool_or_yml, +) + + +class BaseBoolOr(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return { + "data_bool_or.csv": seeds__data_bool_or_csv, + "data_bool_or_expected.csv": seeds__data_bool_or_expected_csv + } + + @pytest.fixture(scope="class") + def models(self): + return { + "test_bool_or.yml": models__test_bool_or_yml, + "test_bool_or.sql": models__test_bool_or_sql, + } + + +class TestBoolOr(BaseBoolOr): + pass diff --git a/tests/functional/cross_db_utils/test_cast_bool_to_text.py b/tests/functional/cross_db_utils/test_cast_bool_to_text.py new file mode 100644 index 00000000..0670cc2a --- /dev/null +++ b/tests/functional/cross_db_utils/test_cast_bool_to_text.py @@ -0,0 +1,19 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_cast_bool_to_text import ( + models__test_cast_bool_to_text_sql, + models__test_cast_bool_to_text_yml, +) + + +class BaseCastBoolToText(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def models(self): + return { + "test_cast_bool_to_text.yml": models__test_cast_bool_to_text_yml, + "test_cast_bool_to_text.sql": models__test_cast_bool_to_text_sql, + } + + +class TestCastBoolToText(BaseCastBoolToText): + pass diff --git a/tests/functional/cross_db_utils/test_concat.py b/tests/functional/cross_db_utils/test_concat.py new file mode 100644 index 00000000..1cee2f23 --- /dev/null +++ b/tests/functional/cross_db_utils/test_concat.py @@ -0,0 +1,24 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_concat import ( + seeds__data_concat_csv, + models__test_concat_sql, + models__test_concat_yml, +) + + +class BaseConcat(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_concat.csv": seeds__data_concat_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_concat.yml": models__test_concat_yml, + "test_concat.sql": models__test_concat_sql, + } + + +class TestConcat(BaseConcat): + pass diff --git a/tests/functional/cross_db_utils/test_current_timestamp.py b/tests/functional/cross_db_utils/test_current_timestamp.py new file mode 100644 index 00000000..ba1a52d5 --- /dev/null +++ b/tests/functional/cross_db_utils/test_current_timestamp.py @@ -0,0 +1,19 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_current_timestamp import ( + models__test_current_timestamp_sql, + models__test_current_timestamp_yml, +) + + +class BaseCurrentTimestamp(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def models(self): + return { + "test_current_timestamp.yml": models__test_current_timestamp_yml, + "test_current_timestamp.sql": models__test_current_timestamp_sql, + } + + +class TestCurrentTimestamp(BaseCurrentTimestamp): + pass diff --git a/tests/functional/cross_db_utils/test_current_timestamp_in_utc.py b/tests/functional/cross_db_utils/test_current_timestamp_in_utc.py new file mode 100644 index 00000000..adcedc22 --- /dev/null +++ b/tests/functional/cross_db_utils/test_current_timestamp_in_utc.py @@ -0,0 +1,19 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_current_timestamp_in_utc import ( + models__test_current_timestamp_in_utc_sql, + models__test_current_timestamp_in_utc_yml, +) + + +class BaseCurrentTimestampInUtc(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def models(self): + return { + "test_current_timestamp_in_utc.yml": models__test_current_timestamp_in_utc_yml, + "test_current_timestamp_in_utc.sql": models__test_current_timestamp_in_utc_sql, + } + + +class TestCurrentTimestampInUtc(BaseCurrentTimestampInUtc): + pass diff --git a/tests/functional/cross_db_utils/test_date_trunc.py b/tests/functional/cross_db_utils/test_date_trunc.py new file mode 100644 index 00000000..6722c2cf --- /dev/null +++ b/tests/functional/cross_db_utils/test_date_trunc.py @@ -0,0 +1,24 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_date_trunc import ( + seeds__data_date_trunc_csv, + models__test_date_trunc_sql, + models__test_date_trunc_yml, +) + + +class BaseDateTrunc(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_date_trunc.csv": seeds__data_date_trunc_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_date_trunc.yml": models__test_date_trunc_yml, + "test_date_trunc.sql": models__test_date_trunc_sql, + } + + +class TestDateTrunc(BaseDateTrunc): + pass diff --git a/tests/functional/cross_db_utils/test_dateadd.py b/tests/functional/cross_db_utils/test_dateadd.py new file mode 100644 index 00000000..ef9e7910 --- /dev/null +++ b/tests/functional/cross_db_utils/test_dateadd.py @@ -0,0 +1,40 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_dateadd import ( + seeds__data_dateadd_csv, + models__test_dateadd_sql, + models__test_dateadd_yml, +) + + +class BaseDateAdd(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def project_config_update(self): + return { + "name": "test", + "seeds": { + "test": { + "data_dateadd": { + "+column_types": { + "from_time": "timestamp", + "result": "timestamp", + }, + }, + }, + }, + } + + @pytest.fixture(scope="class") + def seeds(self): + return {"data_dateadd.csv": seeds__data_dateadd_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_dateadd.yml": models__test_dateadd_yml, + "test_dateadd.sql": models__test_dateadd_sql, + } + + +class TestDateAdd(BaseDateAdd): + pass diff --git a/tests/functional/cross_db_utils/test_datediff.py b/tests/functional/cross_db_utils/test_datediff.py new file mode 100644 index 00000000..6a58eae7 --- /dev/null +++ b/tests/functional/cross_db_utils/test_datediff.py @@ -0,0 +1,24 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_datediff import ( + seeds__data_datediff_csv, + models__test_datediff_sql, + models__test_datediff_yml, +) + + +class BaseDateDiff(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_datediff.csv": seeds__data_datediff_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_datediff.yml": models__test_datediff_yml, + "test_datediff.sql": models__test_datediff_sql, + } + + +class TestDateDiff(BaseDateDiff): + pass diff --git a/tests/functional/cross_db_utils/test_escape_single_quotes.py b/tests/functional/cross_db_utils/test_escape_single_quotes.py new file mode 100644 index 00000000..1462ee5e --- /dev/null +++ b/tests/functional/cross_db_utils/test_escape_single_quotes.py @@ -0,0 +1,45 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_escape_single_quotes import ( + models__test_escape_single_quotes_quote_sql, + models__test_escape_single_quotes_backslash_sql, + models__test_escape_single_quotes_yml, +) + + +class BaseEscapeSingleQuotesQuote(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def models(self): + return { + "test_escape_single_quotes.yml": models__test_escape_single_quotes_yml, + "test_escape_single_quotes.sql": models__test_escape_single_quotes_quote_sql, + } + + +class BaseEscapeSingleQuotesBackslash(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def models(self): + return { + "test_escape_single_quotes.yml": models__test_escape_single_quotes_yml, + "test_escape_single_quotes.sql": models__test_escape_single_quotes_backslash_sql, + } + + +@pytest.mark.only_profile("postgres") +class TestEscapeSingleQuotesPostgres(BaseEscapeSingleQuotesQuote): + pass + + +@pytest.mark.only_profile("redshift") +class TestEscapeSingleQuotesRedshift(BaseEscapeSingleQuotesQuote): + pass + + +@pytest.mark.only_profile("snowflake") +class TestEscapeSingleQuotesSnowflake(BaseEscapeSingleQuotesBackslash): + pass + + +@pytest.mark.only_profile("bigquery") +class TestEscapeSingleQuotesBigQuery(BaseEscapeSingleQuotesBackslash): + pass diff --git a/tests/functional/cross_db_utils/test_except.py b/tests/functional/cross_db_utils/test_except.py new file mode 100644 index 00000000..ad0c415c --- /dev/null +++ b/tests/functional/cross_db_utils/test_except.py @@ -0,0 +1,72 @@ +import pytest +from dbt.tests.util import run_dbt, check_relations_equal +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_except import ( + seeds__data_except_a_csv, + seeds__data_except_b_csv, + seeds__data_except_a_minus_b_csv, + seeds__data_except_b_minus_a_csv, + models__data_except_empty_sql, + models__test_except_a_minus_b_sql, + models__test_except_b_minus_a_sql, + models__test_except_a_minus_a_sql, + models__test_except_a_minus_empty_sql, + models__test_except_empty_minus_a_sql, + models__test_except_empty_minus_empty_sql, +) + + +class BaseExcept(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return { + "data_except_a.csv": seeds__data_except_a_csv, + "data_except_b.csv": seeds__data_except_b_csv, + "data_except_a_minus_b.csv": seeds__data_except_a_minus_b_csv, + "data_except_b_minus_a.csv": seeds__data_except_b_minus_a_csv, + } + + @pytest.fixture(scope="class") + def models(self): + return { + "data_except_empty.sql": models__data_except_empty_sql, + "test_except_a_minus_b.sql": models__test_except_a_minus_b_sql, + "test_except_b_minus_a.sql": models__test_except_b_minus_a_sql, + "test_except_a_minus_a.sql": models__test_except_a_minus_a_sql, + "test_except_a_minus_empty.sql": models__test_except_a_minus_empty_sql, + "test_except_empty_minus_a.sql": models__test_except_empty_minus_a_sql, + "test_except_empty_minus_empty.sql": models__test_except_empty_minus_empty_sql, + } + + def test_build_assert_equal(self, project): + run_dbt(['deps']) + run_dbt(['build']) + + check_relations_equal( + project.adapter, + ["test_except_a_minus_b", "data_except_a_minus_b"], + ) + check_relations_equal( + project.adapter, + ["test_except_b_minus_a", "data_except_b_minus_a"], + ) + check_relations_equal( + project.adapter, + ["test_except_a_minus_a", "data_except_empty"], + ) + check_relations_equal( + project.adapter, + ["test_except_a_minus_empty", "data_except_a"], + ) + check_relations_equal( + project.adapter, + ["test_except_empty_minus_a", "data_except_empty"], + ) + check_relations_equal( + project.adapter, + ["test_except_empty_minus_empty", "data_except_empty"], + ) + + +class TestExcept(BaseExcept): + pass diff --git a/tests/functional/cross_db_utils/test_hash.py b/tests/functional/cross_db_utils/test_hash.py new file mode 100644 index 00000000..d8454b26 --- /dev/null +++ b/tests/functional/cross_db_utils/test_hash.py @@ -0,0 +1,24 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_hash import ( + seeds__data_hash_csv, + models__test_hash_sql, + models__test_hash_yml, +) + + +class BaseHash(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_hash.csv": seeds__data_hash_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_hash.yml": models__test_hash_yml, + "test_hash.sql": models__test_hash_sql, + } + + +class TestHash(BaseHash): + pass diff --git a/tests/functional/cross_db_utils/test_intersect.py b/tests/functional/cross_db_utils/test_intersect.py new file mode 100644 index 00000000..b7e0ca92 --- /dev/null +++ b/tests/functional/cross_db_utils/test_intersect.py @@ -0,0 +1,70 @@ +import pytest +from dbt.tests.util import run_dbt, check_relations_equal +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_intersect import ( + seeds__data_intersect_a_csv, + seeds__data_intersect_b_csv, + seeds__data_intersect_a_overlap_b_csv, + models__data_intersect_empty_sql, + models__test_intersect_a_overlap_b_sql, + models__test_intersect_b_overlap_a_sql, + models__test_intersect_a_overlap_a_sql, + models__test_intersect_a_overlap_empty_sql, + models__test_intersect_empty_overlap_a_sql, + models__test_intersect_empty_overlap_empty_sql, +) + + +class BaseIntersect(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return { + "data_intersect_a.csv": seeds__data_intersect_a_csv, + "data_intersect_b.csv": seeds__data_intersect_b_csv, + "data_intersect_a_overlap_b.csv": seeds__data_intersect_a_overlap_b_csv, + } + + @pytest.fixture(scope="class") + def models(self): + return { + "data_intersect_empty.sql": models__data_intersect_empty_sql, + "test_intersect_a_overlap_b.sql": models__test_intersect_a_overlap_b_sql, + "test_intersect_b_overlap_a.sql": models__test_intersect_b_overlap_a_sql, + "test_intersect_a_overlap_a.sql": models__test_intersect_a_overlap_a_sql, + "test_intersect_a_overlap_empty.sql": models__test_intersect_a_overlap_empty_sql, + "test_intersect_empty_overlap_a.sql": models__test_intersect_empty_overlap_a_sql, + "test_intersect_empty_overlap_empty.sql": models__test_intersect_empty_overlap_empty_sql, + } + + def test_build_assert_equal(self, project): + run_dbt(['deps']) + run_dbt(['build']) + + check_relations_equal( + project.adapter, + ["test_intersect_a_overlap_b", "data_intersect_a_overlap_b"], + ) + check_relations_equal( + project.adapter, + ["test_intersect_b_overlap_a", "data_intersect_a_overlap_b"], + ) + check_relations_equal( + project.adapter, + ["test_intersect_a_overlap_a", "data_intersect_a"], + ) + check_relations_equal( + project.adapter, + ["test_intersect_a_overlap_empty", "data_intersect_empty"], + ) + check_relations_equal( + project.adapter, + ["test_intersect_empty_overlap_a", "data_intersect_empty"], + ) + check_relations_equal( + project.adapter, + ["test_intersect_empty_overlap_empty", "data_intersect_empty"], + ) + + +class TestIntersect(BaseIntersect): + pass diff --git a/tests/functional/cross_db_utils/test_last_day.py b/tests/functional/cross_db_utils/test_last_day.py new file mode 100644 index 00000000..f97e53ae --- /dev/null +++ b/tests/functional/cross_db_utils/test_last_day.py @@ -0,0 +1,24 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_last_day import ( + seeds__data_last_day_csv, + models__test_last_day_sql, + models__test_last_day_yml, +) + + +class BaseLastDay(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_last_day.csv": seeds__data_last_day_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_last_day.yml": models__test_last_day_yml, + "test_last_day.sql": models__test_last_day_sql, + } + + +class TestLastDay(BaseLastDay): + pass diff --git a/tests/functional/cross_db_utils/test_length.py b/tests/functional/cross_db_utils/test_length.py new file mode 100644 index 00000000..de6400ef --- /dev/null +++ b/tests/functional/cross_db_utils/test_length.py @@ -0,0 +1,24 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_length import ( + seeds__data_length_csv, + models__test_length_sql, + models__test_length_yml, +) + + +class BaseLength(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_length.csv": seeds__data_length_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_length.yml": models__test_length_yml, + "test_length.sql": models__test_length_sql, + } + + +class TestLength(BaseLength): + pass diff --git a/tests/functional/cross_db_utils/test_listagg.py b/tests/functional/cross_db_utils/test_listagg.py new file mode 100644 index 00000000..a62cf183 --- /dev/null +++ b/tests/functional/cross_db_utils/test_listagg.py @@ -0,0 +1,28 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_listagg import ( + seeds__data_listagg_csv, + seeds__data_listagg_output_csv, + models__test_listagg_sql, + models__test_listagg_yml, +) + + +class BaseListagg(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return { + "data_listagg.csv": seeds__data_listagg_csv, + "data_listagg_output.csv": seeds__data_listagg_output_csv, + } + + @pytest.fixture(scope="class") + def models(self): + return { + "test_listagg.yml": models__test_listagg_yml, + "test_listagg.sql": models__test_listagg_sql, + } + + +class TestListagg(BaseListagg): + pass diff --git a/tests/functional/cross_db_utils/test_position.py b/tests/functional/cross_db_utils/test_position.py new file mode 100644 index 00000000..6ab65120 --- /dev/null +++ b/tests/functional/cross_db_utils/test_position.py @@ -0,0 +1,24 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_position import ( + seeds__data_position_csv, + models__test_position_sql, + models__test_position_yml, +) + + +class BasePosition(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_position.csv": seeds__data_position_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_position.yml": models__test_position_yml, + "test_position.sql": models__test_position_sql, + } + + +class TestPosition(BasePosition): + pass diff --git a/tests/functional/cross_db_utils/test_replace.py b/tests/functional/cross_db_utils/test_replace.py new file mode 100644 index 00000000..6568cbc0 --- /dev/null +++ b/tests/functional/cross_db_utils/test_replace.py @@ -0,0 +1,24 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_replace import ( + seeds__data_replace_csv, + models__test_replace_sql, + models__test_replace_yml, +) + + +class BaseReplace(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_replace.csv": seeds__data_replace_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_replace.yml": models__test_replace_yml, + "test_replace.sql": models__test_replace_sql, + } + + +class TestReplace(BaseReplace): + pass diff --git a/tests/functional/cross_db_utils/test_right.py b/tests/functional/cross_db_utils/test_right.py new file mode 100644 index 00000000..13b24a81 --- /dev/null +++ b/tests/functional/cross_db_utils/test_right.py @@ -0,0 +1,24 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_right import ( + seeds__data_right_csv, + models__test_right_sql, + models__test_right_yml, +) + + +class BaseRight(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_right.csv": seeds__data_right_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_right.yml": models__test_right_yml, + "test_right.sql": models__test_right_sql, + } + + +class TestRight(BaseRight): + pass diff --git a/tests/functional/cross_db_utils/test_safe_cast.py b/tests/functional/cross_db_utils/test_safe_cast.py new file mode 100644 index 00000000..979bd5df --- /dev/null +++ b/tests/functional/cross_db_utils/test_safe_cast.py @@ -0,0 +1,24 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_safe_cast import ( + seeds__data_safe_cast_csv, + models__test_safe_cast_sql, + models__test_safe_cast_yml, +) + + +class BaseSafeCast(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_safe_cast.csv": seeds__data_safe_cast_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_safe_cast.yml": models__test_safe_cast_yml, + "test_safe_cast.sql": models__test_safe_cast_sql, + } + + +class TestSafeCast(BaseSafeCast): + pass diff --git a/tests/functional/cross_db_utils/test_split_part.py b/tests/functional/cross_db_utils/test_split_part.py new file mode 100644 index 00000000..5968f412 --- /dev/null +++ b/tests/functional/cross_db_utils/test_split_part.py @@ -0,0 +1,24 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_split_part import ( + seeds__data_split_part_csv, + models__test_split_part_sql, + models__test_split_part_yml, +) + + +class BaseSplitPart(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_split_part.csv": seeds__data_split_part_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_split_part.yml": models__test_split_part_yml, + "test_split_part.sql": models__test_split_part_sql, + } + + +class TestSplitPart(BaseSplitPart): + pass diff --git a/tests/functional/cross_db_utils/test_string_literal.py b/tests/functional/cross_db_utils/test_string_literal.py new file mode 100644 index 00000000..9fb01cf7 --- /dev/null +++ b/tests/functional/cross_db_utils/test_string_literal.py @@ -0,0 +1,19 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_string_literal import ( + models__test_string_literal_sql, + models__test_string_literal_yml, +) + + +class BaseStringLiteral(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def models(self): + return { + "test_string_literal.yml": models__test_string_literal_yml, + "test_string_literal.sql": models__test_string_literal_sql, + } + + +class TestStringLiteral(BaseStringLiteral): + pass diff --git a/tests/functional/cross_db_utils/test_type_bigint.py b/tests/functional/cross_db_utils/test_type_bigint.py new file mode 100644 index 00000000..81b04231 --- /dev/null +++ b/tests/functional/cross_db_utils/test_type_bigint.py @@ -0,0 +1,25 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_type_bigint import ( + seeds__data_type_bigint_csv, + models__test_type_bigint_sql, + models__test_type_bigint_yml, +) + + +class BaseTypeBigint(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_type_bigint.csv": seeds__data_type_bigint_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_type_bigint.yml": models__test_type_bigint_yml, + "test_type_bigint.sql": models__test_type_bigint_sql, + } + + +@pytest.mark.skip(reason="TODO - implement this test") +class TestTypeBigint(BaseTypeBigint): + pass diff --git a/tests/functional/cross_db_utils/test_type_boolean.py b/tests/functional/cross_db_utils/test_type_boolean.py new file mode 100644 index 00000000..83c7d765 --- /dev/null +++ b/tests/functional/cross_db_utils/test_type_boolean.py @@ -0,0 +1,25 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_type_boolean import ( + seeds__data_type_boolean_csv, + models__test_type_boolean_sql, + models__test_type_boolean_yml, +) + + +class BaseTypeBoolean(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_type_boolean.csv": seeds__data_type_boolean_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_type_boolean.yml": models__test_type_boolean_yml, + "test_type_boolean.sql": models__test_type_boolean_sql, + } + + +@pytest.mark.skip(reason="TODO - implement this test") +class TestTypeBoolean(BaseTypeBoolean): + pass diff --git a/tests/functional/cross_db_utils/test_type_float.py b/tests/functional/cross_db_utils/test_type_float.py new file mode 100644 index 00000000..90380979 --- /dev/null +++ b/tests/functional/cross_db_utils/test_type_float.py @@ -0,0 +1,25 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_type_float import ( + seeds__data_type_float_csv, + models__test_type_float_sql, + models__test_type_float_yml, +) + + +class BaseTypeFloat(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_type_float.csv": seeds__data_type_float_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_type_float.yml": models__test_type_float_yml, + "test_type_float.sql": models__test_type_float_sql, + } + + +@pytest.mark.skip(reason="TODO - implement this test") +class TestTypeFloat(BaseTypeFloat): + pass diff --git a/tests/functional/cross_db_utils/test_type_int.py b/tests/functional/cross_db_utils/test_type_int.py new file mode 100644 index 00000000..d05669ef --- /dev/null +++ b/tests/functional/cross_db_utils/test_type_int.py @@ -0,0 +1,25 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_type_int import ( + seeds__data_type_int_csv, + models__test_type_int_sql, + models__test_type_int_yml, +) + + +class BaseTypeInt(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_type_int.csv": seeds__data_type_int_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_type_int.yml": models__test_type_int_yml, + "test_type_int.sql": models__test_type_int_sql, + } + + +@pytest.mark.skip(reason="TODO - implement this test") +class TestTypeInt(BaseTypeInt): + pass diff --git a/tests/functional/cross_db_utils/test_type_numeric.py b/tests/functional/cross_db_utils/test_type_numeric.py new file mode 100644 index 00000000..a337e575 --- /dev/null +++ b/tests/functional/cross_db_utils/test_type_numeric.py @@ -0,0 +1,25 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_type_numeric import ( + seeds__data_type_numeric_csv, + models__test_type_numeric_sql, + models__test_type_numeric_yml, +) + + +class BaseTypeNumeric(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_type_numeric.csv": seeds__data_type_numeric_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_type_numeric.yml": models__test_type_numeric_yml, + "test_type_numeric.sql": models__test_type_numeric_sql, + } + + +@pytest.mark.skip(reason="TODO - implement this test") +class TestTypeNumeric(BaseTypeNumeric): + pass diff --git a/tests/functional/cross_db_utils/test_type_string.py b/tests/functional/cross_db_utils/test_type_string.py new file mode 100644 index 00000000..16e9478e --- /dev/null +++ b/tests/functional/cross_db_utils/test_type_string.py @@ -0,0 +1,25 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_type_string import ( + seeds__data_type_string_csv, + models__test_type_string_sql, + models__test_type_string_yml, +) + + +class BaseTypeString(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_type_string.csv": seeds__data_type_string_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_type_string.yml": models__test_type_string_yml, + "test_type_string.sql": models__test_type_string_sql, + } + + +@pytest.mark.skip(reason="TODO - implement this test") +class TestTypeString(BaseTypeString): + pass diff --git a/tests/functional/cross_db_utils/test_type_timestamp.py b/tests/functional/cross_db_utils/test_type_timestamp.py new file mode 100644 index 00000000..3244f5c3 --- /dev/null +++ b/tests/functional/cross_db_utils/test_type_timestamp.py @@ -0,0 +1,25 @@ +import pytest +from tests.functional.cross_db_utils.base_cross_db_macro import BaseCrossDbMacro +from tests.functional.cross_db_utils.fixture_type_timestamp import ( + seeds__data_type_timestamp_csv, + models__test_type_timestamp_sql, + models__test_type_timestamp_yml, +) + + +class BaseTypeTimestamp(BaseCrossDbMacro): + @pytest.fixture(scope="class") + def seeds(self): + return {"data_type_timestamp.csv": seeds__data_type_timestamp_csv} + + @pytest.fixture(scope="class") + def models(self): + return { + "test_type_timestamp.yml": models__test_type_timestamp_yml, + "test_type_timestamp.sql": models__test_type_timestamp_sql, + } + + +@pytest.mark.skip(reason="TODO - implement this test") +class TestTypeTimestamp(BaseTypeTimestamp): + pass