Skip to content

Commit

Permalink
Feature/add test description (#44)
Browse files Browse the repository at this point in the history
* Added macro __get_test_description and test_description to dq_log

* Remove redundant macro

* Added macro __get_test_description and test_description to dq_log

* Added integration tests for __get_test_description

* Added missing underscore

* feat: adj auto_generate_test_description

* fix: dq_tools__auto_generate_test_description: "1"

---------

Co-authored-by: Dat <dat@infinitelambda.com>
  • Loading branch information
il-ngocanh and il-dat authored Dec 3, 2024
1 parent c52acee commit 0369824
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 2 deletions.
1 change: 1 addition & 0 deletions dbt_project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ vars:
# >> for metricflow
# dbt_dq_tool_start_date
# dbt_dq_tool_end_date
# dq_tools__auto_generate_test_description: 1 # Set 1 to automatically generate test description if not specified

models:
dq_tools:
Expand Down
1 change: 1 addition & 0 deletions integration_tests/dbt_project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ vars:
by_database: ['dummy'] # dummy inputs
by_schema: ['dq_tools_mart'] # exclude all dq_tools.03_mart
by_table: ['dq_issue_log', 'dummy'] # dummy inputs
dq_tools__auto_generate_test_description: "1"

seeds:
dq_tools_integration_tests:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ models:
- name: test__get_where_subquery
data_tests:
- dq_tools.expression_is_true_db:
expression: actual = expected
expression: actual = expected
- name: test__get_test_description
data_tests:
- dq_tools.expression_is_true_db:
expression: actual = expected

Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
-- test not_null
{% set result_node = {
"test_metadata": {
"name": "not_null",
"kwargs": {
"column_name": "indicator_category",
"model": "{{ get_where_subquery(ref('bi_column_analysis')) }}"
},
}
} %}

select '{{ dq_tools.__get_test_description(result_node) }}' as actual,
'The indicator_category column in the bi_column_analysis model should not contain null values.' as expected

-- test unique
{% set result_node = {
"test_metadata": {
"name": "unique",
"kwargs": {
"column_name": "invocation_id",
"model": "{{ get_where_subquery(ref('test_coverage')) }}"
}
}
} %}

union all
select '{{ dq_tools.__get_test_description(result_node) }}' as actual,
'The invocation_id column in the test_coverage model should be unique.' as expected

-- test relationships
{% set result_node = {

"test_metadata": {
"name": "relationships",
"kwargs": {
"to": "ref('data_test_relationships_a')",
"field": "a_id",
"column_name": "b_id",
"model": "{{ get_where_subquery(ref('data_test_relationships_b')) }}"
}
}
} %}

union all
select '{{ dq_tools.__get_test_description((result_node)) }}' as actual,
'Each b_id in the data_test_relationships_b model exists as an id in the data_test_relationships_a table.' as expected

-- test no test description
{% set result_node = {
"test_metadata": {
"name": "not_null_where_db",
"kwargs": {
"column_name": "check_timestamp",
"model": "{{ get_where_subquery(ref('dq_tools_test')) }}"
}
}
} %}

union all
select '{{ dq_tools.__get_test_description(result_node) }}' as actual,
'' as expected

{% set result_node = {
"test_metadata": {
"name": "accepted_values",
"kwargs": {
"values": [
"Simple Statistics"
],
"column_name": "indicator_category",
"model": "{{ get_where_subquery(ref('bi_dq_metrics')) }}"
},
"namespace": null
},
"description": "The indicator_category column should only contain simple statistics value"
} %}

union all
select
'{{ dq_tools.__get_test_description(result_node) }}' as actual,
'The indicator_category column should only contain simple statistics value' as expected
7 changes: 7 additions & 0 deletions integration_tests/models/time_spine.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
models:
- name: metricflow_time_spine
time_spine:
standard_granularity_column: date_day
columns:
- name: date_day
granularity: day
2 changes: 2 additions & 0 deletions macros/artifacts/test/store_test_results.sql
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
,no_of_table_columns
,no_of_tables
,test_unique_id
,test_description
)

with logs as (
Expand Down Expand Up @@ -75,6 +76,7 @@
,no_of_table_columns
,{{ no_of_tables }} as no_of_tables
,test_unique_id
,test_description

from logs;

Expand Down
39 changes: 39 additions & 0 deletions macros/artifacts/test/utilities/general/__get_test_description.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{% macro __get_test_description(test_node) %}

{{ return(adapter.dispatch('__get_test_description', 'dq_tools')(test_node)) }}

{% endmacro %}

{% macro default____get_test_description(test_node) %}

{% if test_node.description is defined and test_node.description %}

{{ return(test_node.description) }}

{% elif dq_tools.__get_test_type(test_node) != 'singular' and var("dq_tools__auto_generate_test_description", "0") == "1" %}

{%- set test_name = dq_tools.__get_test_name(test_node) -%}
{%- set column_name = dq_tools.__get_column_name(test_node) -%}
{%- set testing_model = dq_tools.__get_test_model(test_node) -%}
{%- set model_name = dq_tools.__get_relation(testing_model).name | lower -%}

{%- set generated_description = '' -%}

{%- if test_name == 'unique' -%}
{%- set generated_description = 'The ' ~ column_name ~ ' column in the ' ~ model_name ~ ' model should be unique.' -%}
{%- elif test_name == 'not_null' -%}
{%- set generated_description = 'The ' ~ column_name ~ ' column in the ' ~ model_name ~ ' model should not contain null values.' -%}
{%- elif test_name == 'accepted_values' -%}
{%- set accepted_values = test_node.test_metadata.kwargs['values'] | join(', ') -%}
{%- set generated_description = 'The ' ~ column_name ~ ' column in the ' ~ model_name ~ ' should be one of ' ~ accepted_values ~ ' values.' -%}
{%- elif test_name == 'relationships' -%}
{%- set to_model = test_node.test_metadata.kwargs.to -%}
{%- set related_model = to_model.split('\'')[1].strip() -%}
{%- set generated_description = 'Each ' ~ column_name ~ ' in the ' ~ model_name ~ ' model exists as an id in the ' ~ related_model ~ ' table.' -%}
{%- endif -%}

{{ return(generated_description) }}

{% endif %}

{% endmacro %}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
{%- set testing_model = dq_tools.__get_test_model(result.node) -%}
{%- set testing_model_relation = dq_tools.__get_relation(testing_model) -%}
{%- set materialization = dq_tools.__get_test_model_materialization(testing_model.name) -%}
{%- set test_description = dq_tools.__get_test_description(result.node) -%}

/* {{ testing_model }} */

select '{{ result.node.unique_id }}' as test_unique_id
Expand Down Expand Up @@ -42,6 +44,7 @@
){% else %}null{% endif %} as no_of_records_scanned
,coalesce({{ result.failures or 'null' }}, 0) as no_of_records_failed
,'{{ test_type }}' as test_type
,'{{ test_description }}' as test_description
,'{{ result.execution_time }}' as execution_time_seconds
,'{{ result.node.original_file_path }}' as file_test_defined
,'{{ target.name }}' as dbt_target_name
Expand Down
16 changes: 16 additions & 0 deletions macros/artifacts/test/utilities/general/_general.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ macros:
General type of the test which are singular or generic.
See {{'{{'}} __get_test_type {{'}}'}}
- `test_description`:
Description of a test.
- `execution_time_seconds`:
Value generated by dbt which is `result.execution_time`
Expand Down Expand Up @@ -114,3 +117,16 @@ macros:
- name: __get_test_model_materialization
description: |
Return the materialization type of the model being tested (eg: table, view, ephemeral etc).

- name: __get_test_description
description: |
This macro retrieves the description of a test from a test node object.
If the description is not defined, it generates one based on the test type (e.g., unique, not_null, accepted_values, or relationships).
Available for tests starting in dbt v1.9.
Returns an empty string if no description is found or generated.
arguments:
- name: test_node
type: string
description: The unique identifier of the test node in the graph
return_value: (string) The test description or an empty string if none is found.
1 change: 1 addition & 0 deletions models/01_lake/dq_issue_log.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ select cast(null as {{ dbt.type_timestamp() }}) as check_timestamp
,cast(null as {{ dbt.type_int() }}) as no_of_table_columns
,cast(null as {{ dbt.type_int() }}) as no_of_tables
,cast(null as {{ dbt.type_string() }}) as test_unique_id
,cast(null as {{ dbt.type_string() }}) as test_description

from dummy

Expand Down
4 changes: 3 additions & 1 deletion models/01_lake/dq_issue_log.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,6 @@ models:
- name: no_of_tables
description: number of models of the tested project
- name: test_unique_id
description: unique id of a test generated by dbt
description: unique id of a test generated by dbt
- name: test_description
description: description of a test

0 comments on commit 0369824

Please sign in to comment.