From c878026ca9e744f07e3cf8dd54d999985ec2fbbf Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 15:44:24 -0600 Subject: [PATCH 01/15] added unit test for uniqueness, fixed quoting bug --- .../uniqueness_colnames_with_spaces.sql | 32 +++++++++++++++++++ .../get_test_suggestions.sql | 0 .../merge_dbt_configs.sql | 0 .../generate_uniqueness_tests.sql | 6 +++- 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 integration_tests/tests/generate_uniqueness_tests/uniqueness_colnames_with_spaces.sql rename macros/{test_selection => test_aggregation}/get_test_suggestions.sql (100%) rename macros/{helpers => test_aggregation}/merge_dbt_configs.sql (100%) diff --git a/integration_tests/tests/generate_uniqueness_tests/uniqueness_colnames_with_spaces.sql b/integration_tests/tests/generate_uniqueness_tests/uniqueness_colnames_with_spaces.sql new file mode 100644 index 0000000..71e9850 --- /dev/null +++ b/integration_tests/tests/generate_uniqueness_tests/uniqueness_colnames_with_spaces.sql @@ -0,0 +1,32 @@ + + +{% set actual_yaml = toyaml(fromjson(tojson( + testgen.get_uniqueness_test_suggestions( + ref('colnames_with_spaces'), + compound_key_length = 1 + ) + ))) +%} + +{% set expected_yaml %} +models: +- name: colnames_with_spaces + columns: + - name: First Name + description: Uniqueness test generated by dbt-testgen + tests: + - unique + - not_null + - name: Age (Years) + description: Uniqueness test generated by dbt-testgen + tests: + - unique + - not_null + - name: Current City + description: Uniqueness test generated by dbt-testgen + tests: + - unique + - not_null +{% endset %} + +{{ assert_equal (actual_yaml | trim, expected_yaml | trim) }} \ No newline at end of file diff --git a/macros/test_selection/get_test_suggestions.sql b/macros/test_aggregation/get_test_suggestions.sql similarity index 100% rename from macros/test_selection/get_test_suggestions.sql rename to macros/test_aggregation/get_test_suggestions.sql diff --git a/macros/helpers/merge_dbt_configs.sql b/macros/test_aggregation/merge_dbt_configs.sql similarity index 100% rename from macros/helpers/merge_dbt_configs.sql rename to macros/test_aggregation/merge_dbt_configs.sql diff --git a/macros/test_generation/generate_uniqueness_tests.sql b/macros/test_generation/generate_uniqueness_tests.sql index 93aeeec..d2a6098 100644 --- a/macros/test_generation/generate_uniqueness_tests.sql +++ b/macros/test_generation/generate_uniqueness_tests.sql @@ -82,11 +82,15 @@ {% set count_distinct_exprs = [] %} {% for column_combo in column_combinations %} + {% set column_combo_quoted = [] %} + {% for col in column_combo %} + {% do column_combo_quoted.append(adapter.quote(col))%} + {% endfor %} {% do count_distinct_exprs.append( "SELECT " ~ loop.index ~ " AS ordering, count(1) AS cardinality from ( SELECT 1 FROM " ~ table_relation ~ " - GROUP BY " ~ column_combo|join(", ") ~ " + GROUP BY " ~ column_combo_quoted|join(", ") ~ " ) t" ) %} {% endfor %} From 03f8d9971e80ae3955c1dfe749cfce9906323ba7 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 20:26:36 -0600 Subject: [PATCH 02/15] added tests for the generated tests --- .github/workflows/dbt_test.yml | 40 +++++----- README.md | 32 ++++++-- integration_tests/dbt_project.yml | 5 +- .../uniqueness_colnames_with_spaces.sql | 2 +- .../uniqueness_users.sql | 2 +- .../test_selection_users.sql | 7 +- macros/helpers/to_yaml.sql | 3 + .../test_aggregation/get_test_suggestions.sql | 24 ++++-- macros/test_aggregation/merge_dbt_configs.sql | 26 +++---- ... get_accepted_values_test_suggestions.sql} | 74 ++++++++----------- ...sts.sql => get_range_test_suggestions.sql} | 31 ++++---- ...ql => get_uniqueness_test_suggestions.sql} | 37 +++++----- 12 files changed, 156 insertions(+), 127 deletions(-) create mode 100644 macros/helpers/to_yaml.sql rename macros/test_generation/{generate_accepted_values_tests.sql => get_accepted_values_test_suggestions.sql} (61%) rename macros/test_generation/{generate_range_tests.sql => get_range_test_suggestions.sql} (79%) rename macros/test_generation/{generate_uniqueness_tests.sql => get_uniqueness_test_suggestions.sql} (87%) diff --git a/.github/workflows/dbt_test.yml b/.github/workflows/dbt_test.yml index 78b0caf..1debf87 100644 --- a/.github/workflows/dbt_test.yml +++ b/.github/workflows/dbt_test.yml @@ -12,17 +12,25 @@ defaults: working-directory: integration_tests jobs: + setup-testing: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + test-duckdb: name: Test on DuckDB runs-on: ubuntu-latest - #environment: production - container: - image: python:3.11 + needs: setup-testing steps: - - name: Checkout - uses: actions/checkout@v3 - - name: pip install run: pip install dbt-core duckdb dbt-duckdb @@ -32,30 +40,27 @@ jobs: - name: load test data run: dbt seed --target duckdb + - name: Generate tests + run: dbt compile -q --inline "{{ testgen.get_test_suggestions(ref('users'), resource_type='seeds') }}" > seeds/users_test_suggestions.yml + + - name: Generate tests + run: dbt compile -q --inline "{{ testgen.get_test_suggestions(ref('colnames_with_spaces'), resource_type='seeds') }}" > seeds/colnames_with_spaces_test_suggestions.yml + - name: dbt test run: dbt test --target duckdb test-postgres: name: Test on Postgres runs-on: ubuntu-latest - #environment: production - container: - image: python:3.11 + needs: setup-testing - # Service containers to run with `container-job` services: - # Label used to access the service container postgres: - # Docker Hub image image: postgres - # Provide the password for postgres env: POSTGRES_PASSWORD: postgres steps: - - name: Checkout - uses: actions/checkout@v3 - - name: pip install run: pip install dbt-core duckdb dbt-postgres @@ -67,6 +72,3 @@ jobs: - name: dbt test run: dbt test --target postgres - - - diff --git a/README.md b/README.md index 5b45e76..0afed7c 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,33 @@ dbt-testgen autogenerates dbt test yaml based on real data. Inspired by [dbt-codegen]() and [deequ Constraint Suggestion](https://github.com/awslabs/deequ/blob/master/src/main/scala/com/amazon/deequ/examples/constraint_suggestion_example.md) +## Usage +The DBT config YAML is generated by a Jinja macro, `get_test_suggestions`, which you can run like this: +```powershell +dbt compile -q --inline "{{ testgen.get_test_suggestions(ref('mymodel')) }}" +``` +Output: +```yaml +models: +- name: mymodel + columns: + - name: user_id + tests: + - unique + - not_null + - dbt_utils.accepted_range: + min_value: 1 + max_value: 30 +``` + ## Test types -- uniqueness -- not_null -- string length -- range -- accepted_values -- freshness +dbt-testgen can generate these types of tests: +- [uniqueness](#uniqueness) +- [not_null](#not-null) +- [string length](#string-length) +- [range](#range) +- [accepted_values](#accepted-values) +- [freshness](#freshness) ### Uniqueness diff --git a/integration_tests/dbt_project.yml b/integration_tests/dbt_project.yml index e20e93c..f32a8d4 100644 --- a/integration_tests/dbt_project.yml +++ b/integration_tests/dbt_project.yml @@ -4,8 +4,6 @@ config-version: 2 profile: 'integration_tests' -model-paths: ["models"] -analysis-paths: ["analyses"] test-paths: ["tests"] seed-paths: ["seeds"] macro-paths: ["macros"] @@ -17,4 +15,5 @@ clean-targets: seeds: +schema: integration_test_data - +quote_columns: true \ No newline at end of file + +quote_columns: true + diff --git a/integration_tests/tests/generate_uniqueness_tests/uniqueness_colnames_with_spaces.sql b/integration_tests/tests/generate_uniqueness_tests/uniqueness_colnames_with_spaces.sql index 71e9850..101f5d6 100644 --- a/integration_tests/tests/generate_uniqueness_tests/uniqueness_colnames_with_spaces.sql +++ b/integration_tests/tests/generate_uniqueness_tests/uniqueness_colnames_with_spaces.sql @@ -3,7 +3,7 @@ {% set actual_yaml = toyaml(fromjson(tojson( testgen.get_uniqueness_test_suggestions( ref('colnames_with_spaces'), - compound_key_length = 1 + composite_key_length = 1 ) ))) %} diff --git a/integration_tests/tests/generate_uniqueness_tests/uniqueness_users.sql b/integration_tests/tests/generate_uniqueness_tests/uniqueness_users.sql index 9d478ff..263e193 100644 --- a/integration_tests/tests/generate_uniqueness_tests/uniqueness_users.sql +++ b/integration_tests/tests/generate_uniqueness_tests/uniqueness_users.sql @@ -3,7 +3,7 @@ {% set actual_yaml = toyaml(fromjson(tojson( testgen.get_uniqueness_test_suggestions( ref('users'), - compound_key_length = 1 + composite_key_length = 1 ) ))) %} diff --git a/integration_tests/tests/test_test_selection/test_selection_users.sql b/integration_tests/tests/test_test_selection/test_selection_users.sql index 88fae6c..0ae535f 100644 --- a/integration_tests/tests/test_test_selection/test_selection_users.sql +++ b/integration_tests/tests/test_test_selection/test_selection_users.sql @@ -1,10 +1,11 @@ -{% set actual_yaml = toyaml(fromjson(tojson( +{% set actual_yaml = testgen.to_yaml( testgen.get_test_suggestions( - ref('users') + ref('users'), + return_object=true ) - ))) + ) %} {% set expected_yaml %} diff --git a/macros/helpers/to_yaml.sql b/macros/helpers/to_yaml.sql new file mode 100644 index 0000000..e060bb0 --- /dev/null +++ b/macros/helpers/to_yaml.sql @@ -0,0 +1,3 @@ +{% macro to_yaml(the_obj) %} +{{ return(toyaml(fromjson(tojson(the_obj)))) }} +{% endmacro %} \ No newline at end of file diff --git a/macros/test_aggregation/get_test_suggestions.sql b/macros/test_aggregation/get_test_suggestions.sql index 4670174..c1770d1 100644 --- a/macros/test_aggregation/get_test_suggestions.sql +++ b/macros/test_aggregation/get_test_suggestions.sql @@ -3,12 +3,15 @@ table_relation, sample = false, limit = None, - is_source = false, + resource_type = "models", + column_config = {}, exclude_types = [], exclude_cols = [], tags = [], tests = ["uniqueness", "accepted_values", "range"], - dbt_config = None + composite_key_length = 1, + dbt_config = None, + return_object = false ) %} {# Run macro for the specific target DB #} {% if execute %} @@ -17,10 +20,12 @@ table_relation=table_relation, sample=sample, limit=limit, - is_source=is_source, + resource_type=resource_type, + column_config=column_config, exclude_types=exclude_types, exclude_cols=exclude_cols, tags=tags, + composite_key_length=composite_key_length, dbt_config=dbt_config ) %} {% endif %} @@ -30,7 +35,8 @@ table_relation=table_relation, sample=sample, limit=limit, - is_source=is_source, + resource_type=resource_type, + column_config=column_config, exclude_types=exclude_types, exclude_cols=exclude_cols, tags=tags, @@ -43,7 +49,8 @@ table_relation=table_relation, sample=sample, limit=limit, - is_source=is_source, + resource_type=resource_type, + column_config=column_config, exclude_types=exclude_types, exclude_cols=exclude_cols, tags=tags, @@ -51,7 +58,10 @@ ) %} {% endif %} - {{ return(dbt_config) }} - + {% if return_object %} + {{ return(dbt_config) }} + {% else %} + {{ print(testgen.to_yaml(dbt_config)) }} + {% endif %} {% endif %} {%- endmacro %} diff --git a/macros/test_aggregation/merge_dbt_configs.sql b/macros/test_aggregation/merge_dbt_configs.sql index 24c33a5..f11109e 100644 --- a/macros/test_aggregation/merge_dbt_configs.sql +++ b/macros/test_aggregation/merge_dbt_configs.sql @@ -12,31 +12,31 @@ {% set new_config = {} %} {# Want to preserve ordering, so don't use sets #} - {% set model_types = [] %} - {% for model_type in dbt_config_1.keys()|list + dbt_config_2.keys()|list %} - {% if model_type not in model_types %} - {% do model_types.append(model_type) %} + {% set resource_types = [] %} + {% for resource_type in dbt_config_1.keys()|list + dbt_config_2.keys()|list %} + {% if resource_type not in resource_types %} + {% do resource_types.append(resource_type) %} {% endif %} {% endfor %} - {% for model_type in model_types %} - {% do new_config.update({model_type: []}) %} + {% for resource_type in resource_types %} + {% do new_config.update({resource_type: []}) %} - {% if model_type not in dbt_config_1.keys() %} - {% do new_config.update({model_type: dbt_config_2[model_type]}) %} - {% elif model_type not in dbt_config_2.keys() %} - {% do new_config.update({model_type: dbt_config_1[model_type]}) %} + {% if resource_type not in dbt_config_1.keys() %} + {% do new_config.update({resource_type: dbt_config_2[resource_type]}) %} + {% elif resource_type not in dbt_config_2.keys() %} + {% do new_config.update({resource_type: dbt_config_1[resource_type]}) %} {% else %} {% set model_names = [] %} {% set config_1_model_lookup = {} %} - {% for model in dbt_config_1[model_type] %} + {% for model in dbt_config_1[resource_type] %} {% do model_names.append(model["name"]) %} {% do config_1_model_lookup.update({model["name"]: model}) %} {% endfor %} {% set config_2_model_lookup = {} %} - {% for model in dbt_config_2[model_type] %} + {% for model in dbt_config_2[resource_type] %} {% if model["name"] not in model_names %} {% do model_names.append(model["name"]) %} {% endif %} @@ -96,7 +96,7 @@ {% do new_models.append(model)%} {% endfor %} - {% do new_config.update({model_type: new_models}) %} + {% do new_config.update({resource_type: new_models}) %} {% endif %} {% endfor %} diff --git a/macros/test_generation/generate_accepted_values_tests.sql b/macros/test_generation/get_accepted_values_test_suggestions.sql similarity index 61% rename from macros/test_generation/generate_accepted_values_tests.sql rename to macros/test_generation/get_accepted_values_test_suggestions.sql index d00426d..f6c2e11 100644 --- a/macros/test_generation/generate_accepted_values_tests.sql +++ b/macros/test_generation/get_accepted_values_test_suggestions.sql @@ -6,13 +6,12 @@ {{ return("array_agg(" ~ adapter.quote(colname) ~ "::VARCHAR)") }} {% endmacro %} - - {% macro get_accepted_values_test_suggestions( table_relation, sample = false, limit = None, - is_source = false, + resource_type = "models", + column_config = {}, exclude_types = ["float"], exclude_cols = [], tags = ["accepted_values"], @@ -21,16 +20,31 @@ ) %} {# Run macro for the specific target DB #} {% if execute %} - {{ return(adapter.dispatch('get_accepted_values_test_suggestions', 'testgen')(table_relation, sample, limit, is_source, exclude_types, exclude_cols, tags, max_cardinality, dbt_config, **kwargs)) }} + {{ return( + adapter.dispatch('get_accepted_values_test_suggestions', 'testgen')( + table_relation, + sample, + limit, + resource_type, + column_config, + exclude_types, + exclude_cols, + tags, + max_cardinality, + dbt_config, + **kwargs) + ) + }} {% endif%} -{%- endmacro %} +{% endmacro %} {% macro default__get_accepted_values_test_suggestions( table_relation, sample = false, limit = None, - is_source = false, + resource_type = "models", + column_config = {}, exclude_types = ["float"], exclude_cols = [], tags = ["accepted_values"], @@ -39,17 +53,11 @@ ) %} {# kwargs is used for test configurations #} - {% set test_config = kwargs %} + {# {% set test_config = kwargs %} #} {# {% if tags != None %} {% do test_config.update({"tags": tags}) %} {% endif %} #} - {% if is_source == true %} - {% set models_or_sources = "sources" %} - {% else %} - {% set models_or_sources = "models" %} - {% endif %} - {% set columns = adapter.get_columns_in_relation(table_relation) %} {% set columns = testgen.exclude_column_types(columns, exclude_types) %} {% set columns = testgen.exclude_column_names(columns, exclude_cols) %} @@ -83,46 +91,26 @@ {% set column_tests = [] %} {% for cardinality_result in cardinality_results %} - {% do column_tests.append({ + + {% set col_config = { "name": cardinality_result.colname, "description": "Accepted values test generated by dbt-testgen", "tests": [ {"accepted_values": {"values": fromjson(cardinality_result.unique_values)|sort}} ] - } - ) %} + } + %} + {% for k,v in column_config.items() %} + {% do col_config.update({k: v}) %} + {% endfor %} + + {% do column_tests.append(col_config) %} {% endfor %} - {% set new_dbt_config = {models_or_sources: [{"name": table_relation.identifier, "columns": column_tests}]} %} + {% set new_dbt_config = {resource_type: [{"name": table_relation.identifier, "columns": column_tests}]} %} {% set merged_dbt_config = testgen.merge_dbt_configs(dbt_config, new_dbt_config) %} {% do return(merged_dbt_config) %} {% endmacro %} - - - - -{# {% for model_1 in config_1[model_type] %} - {% for model_2 in config_2[model_type] %} - {% if model_1["name"] == model_2["name"] %} - {% set merged_columns = [] %} - {% for col_1 in model_1["columns"] %} - {% for col_2 in model_2["columns"] %} - {% if col_1 == col_2 %} - {% set merged_col = { - "name": model_1["name"], - "tests": col_1["tests"] + col_2["tests"] - } - %} - - {% endif %} - {% endfor %} - {% endfor %} - {% do dbt_config[model_type].append({"name": , "columns": merged_columns}) %} - {% else %} - - {% endif %} - {% endfor %} - {% endfor %} #} \ No newline at end of file diff --git a/macros/test_generation/generate_range_tests.sql b/macros/test_generation/get_range_test_suggestions.sql similarity index 79% rename from macros/test_generation/generate_range_tests.sql rename to macros/test_generation/get_range_test_suggestions.sql index 1226793..30734b5 100644 --- a/macros/test_generation/generate_range_tests.sql +++ b/macros/test_generation/get_range_test_suggestions.sql @@ -3,7 +3,8 @@ table_relation, sample = false, limit = None, - is_source = false, + resource_type = "models", + column_config = {}, exclude_types = [], exclude_cols = [], tags = ["range"], @@ -11,7 +12,7 @@ ) %} {# Run macro for the specific target DB #} {% if execute %} - {{ return(adapter.dispatch('get_range_test_suggestions', 'testgen')(table_relation, sample, limit, is_source, exclude_types, exclude_cols, tags, dbt_config, **kwargs)) }} + {{ return(adapter.dispatch('get_range_test_suggestions', 'testgen')(table_relation, sample, limit, resource_type, column_config, exclude_types, exclude_cols, tags, dbt_config, **kwargs)) }} {% endif%} {%- endmacro %} @@ -20,7 +21,8 @@ table_relation, sample = false, limit = None, - is_source = false, + resource_type = "models", + column_config = {}, exclude_types = [], exclude_cols = [], tags = ["range"], @@ -28,17 +30,10 @@ ) %} {# kwargs is used for test configurations #} - {% set test_config = kwargs %} {# {% if tags != None %} {% do test_config.update({"tags": tags}) %} {% endif %} #} - {% if is_source == true %} - {% set models_or_sources = "sources" %} - {% else %} - {% set models_or_sources = "models" %} - {% endif %} - {% set columns = adapter.get_columns_in_relation(table_relation) %} {% set columns = testgen.exclude_column_types(columns, exclude_types) %} {% set columns = testgen.exclude_column_names(columns, exclude_cols) %} @@ -71,7 +66,7 @@ {% set column_tests = [] %} {% for result in results %} - {% do column_tests.append({ + {% set col_config = { "name": result.colname, "description": "Numeric range test generated by dbt-testgen", "tests": [ @@ -83,10 +78,20 @@ } ] } - ) %} + %} + + {% for k,v in column_config.items() %} + {% do col_config.update({k: v}) %} + {% endfor %} + + {% do column_tests.append(col_config) %} {% endfor %} - {% set new_dbt_config = {models_or_sources: [{"name": table_relation.identifier, "columns": column_tests}]} %} + + + {% set model = {"name": table_relation.identifier, "columns": column_tests} %} + + {% set new_dbt_config = {resource_type: [model]} %} {% set merged_dbt_config = testgen.merge_dbt_configs(dbt_config, new_dbt_config) %} diff --git a/macros/test_generation/generate_uniqueness_tests.sql b/macros/test_generation/get_uniqueness_test_suggestions.sql similarity index 87% rename from macros/test_generation/generate_uniqueness_tests.sql rename to macros/test_generation/get_uniqueness_test_suggestions.sql index d2a6098..380ff05 100644 --- a/macros/test_generation/generate_uniqueness_tests.sql +++ b/macros/test_generation/get_uniqueness_test_suggestions.sql @@ -5,17 +5,17 @@ table_relation, sample = false, limit = None, - is_source = false, + resource_type = "models", exclude_types = ["float"], exclude_cols = [], tags = ["uniqueness"], - compound_key_length = 1, + composite_key_length = 1, dbt_config = None ) %} {# Run macro for the specific target DB #} {% if execute %} {{ return( - adapter.dispatch('get_uniqueness_test_suggestions', 'testgen')(table_relation, sample, limit, is_source, exclude_types, exclude_cols, tags, compound_key_length, dbt_config, **kwargs) + adapter.dispatch('get_uniqueness_test_suggestions', 'testgen')(table_relation, sample, limit, resource_type, exclude_types, exclude_cols, tags, composite_key_length, dbt_config, **kwargs) ) }} {% endif %} {% endmacro %} @@ -25,11 +25,11 @@ table_relation, sample = false, limit = None, - is_source = false, + resource_type = "models", exclude_types = ["float"], exclude_cols = [], tags = ["uniqueness"], - compound_key_length = 1, + composite_key_length = 1, dbt_config = None ) %} @@ -40,12 +40,6 @@ {% do test_config.update({"tags": tags}) %} {% endif %} #} - {% if is_source == true %} - {% set models_or_sources = "sources" %} - {% else %} - {% set models_or_sources = "models" %} - {% endif %} - {% set columns = adapter.get_columns_in_relation(table_relation) %} {% set column_names = [] %} @@ -68,7 +62,7 @@ {% endfor %} {% set column_combinations = [] %} - {% for i in range(compound_key_length) %} + {% for i in range(composite_key_length) %} {% for col_combo in modules.itertools.combinations(column_names, i + 1)%} {% do column_combinations.append(col_combo) %} {% endfor %} @@ -157,11 +151,18 @@ {% set tests = ["unique", "not_null"] %} {% endif %} - {% do column_tests.append({ - "name": unique_key[0], - "description": "Uniqueness test generated by dbt-testgen", - "tests": tests - }) %} + {% set col_config = { + "name": unique_key[0], + "description": "Uniqueness test generated by dbt-testgen", + "tests": tests + } + %} + + {% for k,v in column_config.items() %} + {% do col_config.update({k: v}) %} + {% endfor %} + + {% do column_tests.append(col_config) %} {% else %} {% do table_tests.append({ @@ -177,7 +178,7 @@ {% do model.update({"tests": table_tests}) %} {% endif %} - {% set new_dbt_config = {models_or_sources: [model]} %} + {% set new_dbt_config = {resource_type: [model]} %} {% set merged_dbt_config = testgen.merge_dbt_configs(dbt_config, new_dbt_config) %} From 50b6354366e6e734cd2c084ad8e81723cb201c90 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 20:29:31 -0600 Subject: [PATCH 03/15] added tests for the generated tests --- .github/workflows/dbt_test.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/dbt_test.yml b/.github/workflows/dbt_test.yml index 1debf87..5cf3508 100644 --- a/.github/workflows/dbt_test.yml +++ b/.github/workflows/dbt_test.yml @@ -7,9 +7,6 @@ on: permissions: contents: read -defaults: - run: - working-directory: integration_tests jobs: setup-testing: @@ -24,6 +21,7 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} + - run: cd integration_tests/ test-duckdb: name: Test on DuckDB From edfb4f5c14890e516494763346de77561edc91e3 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 20:34:01 -0600 Subject: [PATCH 04/15] added tests for the generated tests --- .github/workflows/dbt_test.yml | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/.github/workflows/dbt_test.yml b/.github/workflows/dbt_test.yml index 5cf3508..e30c113 100644 --- a/.github/workflows/dbt_test.yml +++ b/.github/workflows/dbt_test.yml @@ -7,28 +7,22 @@ on: permissions: contents: read - jobs: - setup-testing: + test-duckdb: + name: Test on DuckDB runs-on: ubuntu-latest strategy: matrix: python-version: ["3.9", "3.10", "3.11", "3.12"] steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - run: cd integration_tests/ + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - run: cd integration_tests/ - test-duckdb: - name: Test on DuckDB - runs-on: ubuntu-latest - needs: setup-testing - - steps: - name: pip install run: pip install dbt-core duckdb dbt-duckdb @@ -50,7 +44,9 @@ jobs: test-postgres: name: Test on Postgres runs-on: ubuntu-latest - needs: setup-testing + strategy: + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12"] services: postgres: @@ -59,6 +55,12 @@ jobs: POSTGRES_PASSWORD: postgres steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - run: cd integration_tests/ - name: pip install run: pip install dbt-core duckdb dbt-postgres From 3f315481e1a79075297953c861e50a2371528b63 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 20:35:42 -0600 Subject: [PATCH 05/15] added tests for the generated tests --- .github/workflows/dbt_test.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dbt_test.yml b/.github/workflows/dbt_test.yml index e30c113..0cfcf10 100644 --- a/.github/workflows/dbt_test.yml +++ b/.github/workflows/dbt_test.yml @@ -7,6 +7,10 @@ on: permissions: contents: read +defaults: + run: + working-directory: integration_tests + jobs: test-duckdb: name: Test on DuckDB @@ -21,7 +25,6 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - run: cd integration_tests/ - name: pip install run: pip install dbt-core duckdb dbt-duckdb From f0b331496db19c53aa92572e8b286c9b46a8659e Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 20:38:22 -0600 Subject: [PATCH 06/15] added tests for the generated tests --- .github/workflows/dbt_test.yml | 2 +- macros/test_generation/get_uniqueness_test_suggestions.sql | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dbt_test.yml b/.github/workflows/dbt_test.yml index 0cfcf10..258df86 100644 --- a/.github/workflows/dbt_test.yml +++ b/.github/workflows/dbt_test.yml @@ -63,7 +63,7 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - run: cd integration_tests/ + - name: pip install run: pip install dbt-core duckdb dbt-postgres diff --git a/macros/test_generation/get_uniqueness_test_suggestions.sql b/macros/test_generation/get_uniqueness_test_suggestions.sql index 380ff05..4094d77 100644 --- a/macros/test_generation/get_uniqueness_test_suggestions.sql +++ b/macros/test_generation/get_uniqueness_test_suggestions.sql @@ -6,6 +6,7 @@ sample = false, limit = None, resource_type = "models", + column_config = {}, exclude_types = ["float"], exclude_cols = [], tags = ["uniqueness"], @@ -15,7 +16,7 @@ {# Run macro for the specific target DB #} {% if execute %} {{ return( - adapter.dispatch('get_uniqueness_test_suggestions', 'testgen')(table_relation, sample, limit, resource_type, exclude_types, exclude_cols, tags, composite_key_length, dbt_config, **kwargs) + adapter.dispatch('get_uniqueness_test_suggestions', 'testgen')(table_relation, sample, limit, resource_type, column_config, exclude_types, exclude_cols, tags, composite_key_length, dbt_config, **kwargs) ) }} {% endif %} {% endmacro %} @@ -26,6 +27,7 @@ sample = false, limit = None, resource_type = "models", + column_config = {}, exclude_types = ["float"], exclude_cols = [], tags = ["uniqueness"], From 8dacdf5e73651e1169dfdf7dbe7960b8cc970583 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 20:56:17 -0600 Subject: [PATCH 07/15] added tests for the generated tests --- .github/workflows/dbt_test.yml | 4 ++-- macros/test_aggregation/merge_dbt_configs.sql | 22 ++++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/.github/workflows/dbt_test.yml b/.github/workflows/dbt_test.yml index 258df86..a6b6851 100644 --- a/.github/workflows/dbt_test.yml +++ b/.github/workflows/dbt_test.yml @@ -39,7 +39,7 @@ jobs: run: dbt compile -q --inline "{{ testgen.get_test_suggestions(ref('users'), resource_type='seeds') }}" > seeds/users_test_suggestions.yml - name: Generate tests - run: dbt compile -q --inline "{{ testgen.get_test_suggestions(ref('colnames_with_spaces'), resource_type='seeds') }}" > seeds/colnames_with_spaces_test_suggestions.yml + run: "dbt compile -q --inline \"{{ testgen.get_test_suggestions(ref('colnames_with_spaces'), resource_type='seeds', column_config={'quote': true}) }}\" > seeds/colnames_with_spaces_test_suggestions.yml" - name: dbt test run: dbt test --target duckdb @@ -63,7 +63,7 @@ jobs: uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - + - name: pip install run: pip install dbt-core duckdb dbt-postgres diff --git a/macros/test_aggregation/merge_dbt_configs.sql b/macros/test_aggregation/merge_dbt_configs.sql index f11109e..c07def7 100644 --- a/macros/test_aggregation/merge_dbt_configs.sql +++ b/macros/test_aggregation/merge_dbt_configs.sql @@ -63,18 +63,30 @@ {% set new_columns = [] %} {% for col_name in col_names %} + {% set new_column = { + "name": col_name + } + %} {% if col_name not in config_1_col_lookup.keys() %} + {% for k, v in config_2_col_lookup[col_name].items() %} + {% do new_column.update({k: v}) %} + {% endfor %} {% set col_tests = config_2_col_lookup[col_name]["tests"] %} {% elif col_name not in config_2_col_lookup.keys() %} + {% for k, v in config_1_col_lookup[col_name].items() %} + {% do new_column.update({k: v}) %} + {% endfor %} {% set col_tests = config_1_col_lookup[col_name]["tests"] %} {% else %} + {% for k, v in config_1_col_lookup[col_name].items()|list + config_2_col_lookup[col_name].items()|list %} + {% do new_column.update({k: v}) %} + {% endfor %} {% set col_tests = config_1_col_lookup[col_name]["tests"] + config_2_col_lookup[col_name]["tests"] %} {% endif %} - {% do new_columns.append({ - "name": col_name, - "tests": col_tests - }) - %} + + {% do new_column.update({"tests": col_tests}) %} + + {% do new_columns.append(new_column) %} {% endfor %} {% set model_tests = [] %} From 110fd995ddcdf8122f507cecc4bb58608572cfbe Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 21:05:42 -0600 Subject: [PATCH 08/15] refactored tests --- .github/workflows/dbt_test.yml | 4 ++-- .../accepted_values_colnames_with_spaces.sql | 4 ++-- .../accepted_values_users.sql | 4 ++-- .../range_colnames_with_spaces.sql | 4 ++-- .../tests/generate_range_tests/range_users.sql | 4 ++-- .../uniqueness_colnames_with_spaces.sql | 10 +++++++--- .../generate_uniqueness_tests/uniqueness_users.sql | 4 ++-- .../tests/merge_dbt_configs/merge_dbt_configs_1.sql | 2 ++ .../tests/merge_dbt_configs/merge_dbt_configs_2.sql | 1 + .../tests/test_test_selection/test_selection_users.sql | 5 +++++ 10 files changed, 27 insertions(+), 15 deletions(-) diff --git a/.github/workflows/dbt_test.yml b/.github/workflows/dbt_test.yml index a6b6851..9bd4d4d 100644 --- a/.github/workflows/dbt_test.yml +++ b/.github/workflows/dbt_test.yml @@ -35,10 +35,10 @@ jobs: - name: load test data run: dbt seed --target duckdb - - name: Generate tests + - name: Create seed tests run: dbt compile -q --inline "{{ testgen.get_test_suggestions(ref('users'), resource_type='seeds') }}" > seeds/users_test_suggestions.yml - - name: Generate tests + - name: Create seed tests run: "dbt compile -q --inline \"{{ testgen.get_test_suggestions(ref('colnames_with_spaces'), resource_type='seeds', column_config={'quote': true}) }}\" > seeds/colnames_with_spaces_test_suggestions.yml" - name: dbt test diff --git a/integration_tests/tests/generate_accepted_values_tests/accepted_values_colnames_with_spaces.sql b/integration_tests/tests/generate_accepted_values_tests/accepted_values_colnames_with_spaces.sql index 3e803b9..ddf6481 100644 --- a/integration_tests/tests/generate_accepted_values_tests/accepted_values_colnames_with_spaces.sql +++ b/integration_tests/tests/generate_accepted_values_tests/accepted_values_colnames_with_spaces.sql @@ -1,10 +1,10 @@ -{% set actual_yaml = toyaml(fromjson(tojson( +{% set actual_yaml = testgen.to_yaml( testgen.get_accepted_values_test_suggestions( ref('colnames_with_spaces') ) - ))) + ) %} {% set expected_yaml %} diff --git a/integration_tests/tests/generate_accepted_values_tests/accepted_values_users.sql b/integration_tests/tests/generate_accepted_values_tests/accepted_values_users.sql index 6b36a34..9507f4c 100644 --- a/integration_tests/tests/generate_accepted_values_tests/accepted_values_users.sql +++ b/integration_tests/tests/generate_accepted_values_tests/accepted_values_users.sql @@ -1,10 +1,10 @@ -{% set actual_yaml = toyaml(fromjson(tojson( +{% set actual_yaml = testgen.to_yaml( testgen.get_accepted_values_test_suggestions( ref('users') ) - ))) + ) %} {% set expected_yaml %} diff --git a/integration_tests/tests/generate_range_tests/range_colnames_with_spaces.sql b/integration_tests/tests/generate_range_tests/range_colnames_with_spaces.sql index 26b269d..2045bb5 100644 --- a/integration_tests/tests/generate_range_tests/range_colnames_with_spaces.sql +++ b/integration_tests/tests/generate_range_tests/range_colnames_with_spaces.sql @@ -1,10 +1,10 @@ -{% set actual_yaml = toyaml(fromjson(tojson( +{% set actual_yaml = testgen.to_yaml( testgen.get_range_test_suggestions( ref('colnames_with_spaces') ) - ))) + ) %} {% set expected_yaml %} diff --git a/integration_tests/tests/generate_range_tests/range_users.sql b/integration_tests/tests/generate_range_tests/range_users.sql index 19f6561..c74c69e 100644 --- a/integration_tests/tests/generate_range_tests/range_users.sql +++ b/integration_tests/tests/generate_range_tests/range_users.sql @@ -1,10 +1,10 @@ -{% set actual_yaml = toyaml(fromjson(tojson( +{% set actual_yaml = testgen.to_yaml( testgen.get_range_test_suggestions( ref('users') ) - ))) + ) %} {% set expected_yaml %} diff --git a/integration_tests/tests/generate_uniqueness_tests/uniqueness_colnames_with_spaces.sql b/integration_tests/tests/generate_uniqueness_tests/uniqueness_colnames_with_spaces.sql index 101f5d6..45f3a86 100644 --- a/integration_tests/tests/generate_uniqueness_tests/uniqueness_colnames_with_spaces.sql +++ b/integration_tests/tests/generate_uniqueness_tests/uniqueness_colnames_with_spaces.sql @@ -1,11 +1,12 @@ -{% set actual_yaml = toyaml(fromjson(tojson( +{% set actual_yaml = testgen.to_yaml( testgen.get_uniqueness_test_suggestions( ref('colnames_with_spaces'), - composite_key_length = 1 + composite_key_length = 1, + column_config={'quote': true} ) - ))) + ) %} {% set expected_yaml %} @@ -17,16 +18,19 @@ models: tests: - unique - not_null + quote: true - name: Age (Years) description: Uniqueness test generated by dbt-testgen tests: - unique - not_null + quote: true - name: Current City description: Uniqueness test generated by dbt-testgen tests: - unique - not_null + quote: true {% endset %} {{ assert_equal (actual_yaml | trim, expected_yaml | trim) }} \ No newline at end of file diff --git a/integration_tests/tests/generate_uniqueness_tests/uniqueness_users.sql b/integration_tests/tests/generate_uniqueness_tests/uniqueness_users.sql index 263e193..24b8123 100644 --- a/integration_tests/tests/generate_uniqueness_tests/uniqueness_users.sql +++ b/integration_tests/tests/generate_uniqueness_tests/uniqueness_users.sql @@ -1,11 +1,11 @@ -{% set actual_yaml = toyaml(fromjson(tojson( +{% set actual_yaml = testgen.to_yaml( testgen.get_uniqueness_test_suggestions( ref('users'), composite_key_length = 1 ) - ))) + ) %} {% set expected_yaml %} diff --git a/integration_tests/tests/merge_dbt_configs/merge_dbt_configs_1.sql b/integration_tests/tests/merge_dbt_configs/merge_dbt_configs_1.sql index 27f72b7..e42d855 100644 --- a/integration_tests/tests/merge_dbt_configs/merge_dbt_configs_1.sql +++ b/integration_tests/tests/merge_dbt_configs/merge_dbt_configs_1.sql @@ -44,6 +44,7 @@ models: - name: users columns: - name: user_id + description: Uniqueness test generated by dbt-testgen tests: - unique: tags: @@ -52,6 +53,7 @@ models: tags: - uniqueness - name: email + description: Uniqueness test generated by dbt-testgen tests: - unique: tags: diff --git a/integration_tests/tests/merge_dbt_configs/merge_dbt_configs_2.sql b/integration_tests/tests/merge_dbt_configs/merge_dbt_configs_2.sql index 226c5c4..8c1cf4c 100644 --- a/integration_tests/tests/merge_dbt_configs/merge_dbt_configs_2.sql +++ b/integration_tests/tests/merge_dbt_configs/merge_dbt_configs_2.sql @@ -42,6 +42,7 @@ models: - name: users columns: - name: user_id + description: Uniqueness test generated by dbt-testgen tests: - unique: tags: diff --git a/integration_tests/tests/test_test_selection/test_selection_users.sql b/integration_tests/tests/test_test_selection/test_selection_users.sql index 0ae535f..eda1fd7 100644 --- a/integration_tests/tests/test_test_selection/test_selection_users.sql +++ b/integration_tests/tests/test_test_selection/test_selection_users.sql @@ -13,6 +13,7 @@ models: - name: users columns: - name: user_id + description: Numeric range test generated by dbt-testgen tests: - unique - not_null @@ -20,20 +21,24 @@ models: min_value: 1 max_value: 30 - name: username + description: Uniqueness test generated by dbt-testgen tests: - unique - not_null - name: email + description: Uniqueness test generated by dbt-testgen tests: - unique - not_null - name: user_status + description: Accepted values test generated by dbt-testgen tests: - accepted_values: values: - active - inactive - name: age + description: Numeric range test generated by dbt-testgen tests: - dbt_utils.accepted_range: min_value: 22 From dc6688c150707d41411be59ec3a59045b00b78e4 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 21:11:03 -0600 Subject: [PATCH 09/15] added dbt-utils --- integration_tests/packages.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/integration_tests/packages.yml b/integration_tests/packages.yml index c9c4e3c..da5cee5 100644 --- a/integration_tests/packages.yml +++ b/integration_tests/packages.yml @@ -1,2 +1,4 @@ packages: - - local: ../ \ No newline at end of file + - local: ../ + - package: dbt-labs/dbt_utils + version: 1.1.1 \ No newline at end of file From ac752bd308fe9963a1a9ed92289c0fe6c63bb4ee Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 21:13:31 -0600 Subject: [PATCH 10/15] added dbt-utils --- integration_tests/packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_tests/packages.yml b/integration_tests/packages.yml index da5cee5..3d6b503 100644 --- a/integration_tests/packages.yml +++ b/integration_tests/packages.yml @@ -1,4 +1,4 @@ packages: - local: ../ - package: dbt-labs/dbt_utils - version: 1.1.1 \ No newline at end of file + version: 1.1.1 \ No newline at end of file From e376345c737d75408bd846af2735bdb12f0ba4de Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 21:15:51 -0600 Subject: [PATCH 11/15] issues with actions postgres serice --- .github/workflows/dbt_test.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dbt_test.yml b/.github/workflows/dbt_test.yml index 9bd4d4d..3a48007 100644 --- a/.github/workflows/dbt_test.yml +++ b/.github/workflows/dbt_test.yml @@ -47,9 +47,8 @@ jobs: test-postgres: name: Test on Postgres runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] + container: + image: python:3.11 services: postgres: From b8095f28e0f4160adb1ede4b2fcc3e3d0192b7af Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 21:20:34 -0600 Subject: [PATCH 12/15] refactored tests --- .github/workflows/dbt_test.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/dbt_test.yml b/.github/workflows/dbt_test.yml index 3a48007..9cadb16 100644 --- a/.github/workflows/dbt_test.yml +++ b/.github/workflows/dbt_test.yml @@ -36,10 +36,7 @@ jobs: run: dbt seed --target duckdb - name: Create seed tests - run: dbt compile -q --inline "{{ testgen.get_test_suggestions(ref('users'), resource_type='seeds') }}" > seeds/users_test_suggestions.yml - - - name: Create seed tests - run: "dbt compile -q --inline \"{{ testgen.get_test_suggestions(ref('colnames_with_spaces'), resource_type='seeds', column_config={'quote': true}) }}\" > seeds/colnames_with_spaces_test_suggestions.yml" + run: bash tests/create_seeds_tests_yml.sh - name: dbt test run: dbt test --target duckdb @@ -72,5 +69,8 @@ jobs: - name: load test data run: dbt seed --target postgres + - name: Create seed tests + run: bash tests/create_seeds_tests_yml.sh + - name: dbt test run: dbt test --target postgres From 8a9d9526ed0c9cebbdcfdb9de211ff2912e794a0 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 21:20:50 -0600 Subject: [PATCH 13/15] refactored tests --- integration_tests/tests/create_seeds_tests_yml.sh | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 integration_tests/tests/create_seeds_tests_yml.sh diff --git a/integration_tests/tests/create_seeds_tests_yml.sh b/integration_tests/tests/create_seeds_tests_yml.sh new file mode 100644 index 0000000..7ae3ebb --- /dev/null +++ b/integration_tests/tests/create_seeds_tests_yml.sh @@ -0,0 +1,7 @@ +dbt compile -q \ + --inline "{{ testgen.get_test_suggestions(ref('users'), resource_type='seeds') }}" \ + > seeds/users_test_suggestions.yml + +dbt compile -q \ + --inline "{{ testgen.get_test_suggestions(ref('colnames_with_spaces'), resource_type='seeds', column_config={'quote': true}) }}" \ + > seeds/colnames_with_spaces_test_suggestions.yml From ddbb04fcb062a78ecf270cb329cfb73272dfed4d Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 21:21:15 -0600 Subject: [PATCH 14/15] removed python 3.12 --- .github/workflows/dbt_test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dbt_test.yml b/.github/workflows/dbt_test.yml index 9cadb16..10dc8d0 100644 --- a/.github/workflows/dbt_test.yml +++ b/.github/workflows/dbt_test.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11"] steps: - uses: actions/checkout@v4 From 2741c6de758c3884ce6599f7e92e430e577e29a1 Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 1 Jan 2024 21:23:25 -0600 Subject: [PATCH 15/15] removed python 3.12 --- .github/workflows/dbt_test.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/dbt_test.yml b/.github/workflows/dbt_test.yml index 10dc8d0..b03f796 100644 --- a/.github/workflows/dbt_test.yml +++ b/.github/workflows/dbt_test.yml @@ -69,8 +69,5 @@ jobs: - name: load test data run: dbt seed --target postgres - - name: Create seed tests - run: bash tests/create_seeds_tests_yml.sh - - name: dbt test run: dbt test --target postgres