Skip to content

Commit 0369824

Browse files
il-ngocanhil-dat
andauthored
Feature/add test description (#44)
* 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>
1 parent c52acee commit 0369824

File tree

11 files changed

+160
-2
lines changed

11 files changed

+160
-2
lines changed

dbt_project.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ vars:
2323
# >> for metricflow
2424
# dbt_dq_tool_start_date
2525
# dbt_dq_tool_end_date
26+
# dq_tools__auto_generate_test_description: 1 # Set 1 to automatically generate test description if not specified
2627

2728
models:
2829
dq_tools:

integration_tests/dbt_project.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ vars:
4343
by_database: ['dummy'] # dummy inputs
4444
by_schema: ['dq_tools_mart'] # exclude all dq_tools.03_mart
4545
by_table: ['dq_issue_log', 'dummy'] # dummy inputs
46+
dq_tools__auto_generate_test_description: "1"
4647

4748
seeds:
4849
dq_tools_integration_tests:

integration_tests/models/artifacts/test/utilities/_general/_general.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,9 @@ models:
2222
- name: test__get_where_subquery
2323
data_tests:
2424
- dq_tools.expression_is_true_db:
25-
expression: actual = expected
25+
expression: actual = expected
26+
- name: test__get_test_description
27+
data_tests:
28+
- dq_tools.expression_is_true_db:
29+
expression: actual = expected
30+
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
-- test not_null
2+
{% set result_node = {
3+
"test_metadata": {
4+
"name": "not_null",
5+
"kwargs": {
6+
"column_name": "indicator_category",
7+
"model": "{{ get_where_subquery(ref('bi_column_analysis')) }}"
8+
},
9+
}
10+
} %}
11+
12+
select '{{ dq_tools.__get_test_description(result_node) }}' as actual,
13+
'The indicator_category column in the bi_column_analysis model should not contain null values.' as expected
14+
15+
-- test unique
16+
{% set result_node = {
17+
"test_metadata": {
18+
"name": "unique",
19+
"kwargs": {
20+
"column_name": "invocation_id",
21+
"model": "{{ get_where_subquery(ref('test_coverage')) }}"
22+
}
23+
}
24+
} %}
25+
26+
union all
27+
select '{{ dq_tools.__get_test_description(result_node) }}' as actual,
28+
'The invocation_id column in the test_coverage model should be unique.' as expected
29+
30+
-- test relationships
31+
{% set result_node = {
32+
33+
"test_metadata": {
34+
"name": "relationships",
35+
"kwargs": {
36+
"to": "ref('data_test_relationships_a')",
37+
"field": "a_id",
38+
"column_name": "b_id",
39+
"model": "{{ get_where_subquery(ref('data_test_relationships_b')) }}"
40+
}
41+
}
42+
} %}
43+
44+
union all
45+
select '{{ dq_tools.__get_test_description((result_node)) }}' as actual,
46+
'Each b_id in the data_test_relationships_b model exists as an id in the data_test_relationships_a table.' as expected
47+
48+
-- test no test description
49+
{% set result_node = {
50+
"test_metadata": {
51+
"name": "not_null_where_db",
52+
"kwargs": {
53+
"column_name": "check_timestamp",
54+
"model": "{{ get_where_subquery(ref('dq_tools_test')) }}"
55+
}
56+
}
57+
} %}
58+
59+
union all
60+
select '{{ dq_tools.__get_test_description(result_node) }}' as actual,
61+
'' as expected
62+
63+
{% set result_node = {
64+
"test_metadata": {
65+
"name": "accepted_values",
66+
"kwargs": {
67+
"values": [
68+
"Simple Statistics"
69+
],
70+
"column_name": "indicator_category",
71+
"model": "{{ get_where_subquery(ref('bi_dq_metrics')) }}"
72+
},
73+
"namespace": null
74+
},
75+
"description": "The indicator_category column should only contain simple statistics value"
76+
} %}
77+
78+
union all
79+
select
80+
'{{ dq_tools.__get_test_description(result_node) }}' as actual,
81+
'The indicator_category column should only contain simple statistics value' as expected
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
models:
2+
- name: metricflow_time_spine
3+
time_spine:
4+
standard_granularity_column: date_day
5+
columns:
6+
- name: date_day
7+
granularity: day

macros/artifacts/test/store_test_results.sql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
,no_of_table_columns
4747
,no_of_tables
4848
,test_unique_id
49+
,test_description
4950
)
5051

5152
with logs as (
@@ -75,6 +76,7 @@
7576
,no_of_table_columns
7677
,{{ no_of_tables }} as no_of_tables
7778
,test_unique_id
79+
,test_description
7880

7981
from logs;
8082

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{% macro __get_test_description(test_node) %}
2+
3+
{{ return(adapter.dispatch('__get_test_description', 'dq_tools')(test_node)) }}
4+
5+
{% endmacro %}
6+
7+
{% macro default____get_test_description(test_node) %}
8+
9+
{% if test_node.description is defined and test_node.description %}
10+
11+
{{ return(test_node.description) }}
12+
13+
{% elif dq_tools.__get_test_type(test_node) != 'singular' and var("dq_tools__auto_generate_test_description", "0") == "1" %}
14+
15+
{%- set test_name = dq_tools.__get_test_name(test_node) -%}
16+
{%- set column_name = dq_tools.__get_column_name(test_node) -%}
17+
{%- set testing_model = dq_tools.__get_test_model(test_node) -%}
18+
{%- set model_name = dq_tools.__get_relation(testing_model).name | lower -%}
19+
20+
{%- set generated_description = '' -%}
21+
22+
{%- if test_name == 'unique' -%}
23+
{%- set generated_description = 'The ' ~ column_name ~ ' column in the ' ~ model_name ~ ' model should be unique.' -%}
24+
{%- elif test_name == 'not_null' -%}
25+
{%- set generated_description = 'The ' ~ column_name ~ ' column in the ' ~ model_name ~ ' model should not contain null values.' -%}
26+
{%- elif test_name == 'accepted_values' -%}
27+
{%- set accepted_values = test_node.test_metadata.kwargs['values'] | join(', ') -%}
28+
{%- set generated_description = 'The ' ~ column_name ~ ' column in the ' ~ model_name ~ ' should be one of ' ~ accepted_values ~ ' values.' -%}
29+
{%- elif test_name == 'relationships' -%}
30+
{%- set to_model = test_node.test_metadata.kwargs.to -%}
31+
{%- set related_model = to_model.split('\'')[1].strip() -%}
32+
{%- set generated_description = 'Each ' ~ column_name ~ ' in the ' ~ model_name ~ ' model exists as an id in the ' ~ related_model ~ ' table.' -%}
33+
{%- endif -%}
34+
35+
{{ return(generated_description) }}
36+
37+
{% endif %}
38+
39+
{% endmacro %}

macros/artifacts/test/utilities/general/__select_test_result.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
{%- set testing_model = dq_tools.__get_test_model(result.node) -%}
1010
{%- set testing_model_relation = dq_tools.__get_relation(testing_model) -%}
1111
{%- set materialization = dq_tools.__get_test_model_materialization(testing_model.name) -%}
12+
{%- set test_description = dq_tools.__get_test_description(result.node) -%}
13+
1214
/* {{ testing_model }} */
1315

1416
select '{{ result.node.unique_id }}' as test_unique_id
@@ -42,6 +44,7 @@
4244
){% else %}null{% endif %} as no_of_records_scanned
4345
,coalesce({{ result.failures or 'null' }}, 0) as no_of_records_failed
4446
,'{{ test_type }}' as test_type
47+
,'{{ test_description }}' as test_description
4548
,'{{ result.execution_time }}' as execution_time_seconds
4649
,'{{ result.node.original_file_path }}' as file_test_defined
4750
,'{{ target.name }}' as dbt_target_name

macros/artifacts/test/utilities/general/_general.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ macros:
5050
General type of the test which are singular or generic.
5151
See {{'{{'}} __get_test_type {{'}}'}}
5252
53+
- `test_description`:
54+
Description of a test.
55+
5356
- `execution_time_seconds`:
5457
Value generated by dbt which is `result.execution_time`
5558
@@ -114,3 +117,16 @@ macros:
114117
- name: __get_test_model_materialization
115118
description: |
116119
Return the materialization type of the model being tested (eg: table, view, ephemeral etc).
120+
121+
122+
- name: __get_test_description
123+
description: |
124+
This macro retrieves the description of a test from a test node object.
125+
If the description is not defined, it generates one based on the test type (e.g., unique, not_null, accepted_values, or relationships).
126+
Available for tests starting in dbt v1.9.
127+
Returns an empty string if no description is found or generated.
128+
arguments:
129+
- name: test_node
130+
type: string
131+
description: The unique identifier of the test node in the graph
132+
return_value: (string) The test description or an empty string if none is found.

models/01_lake/dq_issue_log.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ select cast(null as {{ dbt.type_timestamp() }}) as check_timestamp
3030
,cast(null as {{ dbt.type_int() }}) as no_of_table_columns
3131
,cast(null as {{ dbt.type_int() }}) as no_of_tables
3232
,cast(null as {{ dbt.type_string() }}) as test_unique_id
33+
,cast(null as {{ dbt.type_string() }}) as test_description
3334

3435
from dummy
3536

0 commit comments

Comments
 (0)