@@ -45,121 +45,15 @@ def _normalize_empty(val):
4545 return val if val not in (None , "" ) else None
4646
4747
48- @pytest .mark .parametrize (
49- "group_config, expected_groups, test_name" ,
50- [
51- # Single group with owner name and email
52- (
53- GROUP_CONFIG ,
54- [(GROUP_NAME , OWNER_NAME , OWNER_EMAIL )],
55- "single_group" ,
56- ),
57- # Single group with name only, no email
58- (
59- {"groups" : [{"name" : GROUP_NAME , "owner" : {"name" : OWNER_NAME }}]},
60- [(GROUP_NAME , OWNER_NAME , None )],
61- "single_group_without_email" ,
62- ),
63- # Single group with email only, no name
64- (
65- {"groups" : [{"name" : GROUP_NAME , "owner" : {"email" : OWNER_EMAIL }}]},
66- [(GROUP_NAME , None , OWNER_EMAIL )],
67- "single_group_without_name" ,
68- ),
69- # Single group with owner additional fields
70- (
71- {
72- "groups" : [
73- {
74- "name" : GROUP_NAME ,
75- "owner" : {"email" : OWNER_EMAIL , "slack" : "slack_channel" },
76- }
77- ]
78- },
79- [(GROUP_NAME , None , OWNER_EMAIL )],
80- "single_group_with_additional_fields" ,
81- ),
82- # Two groups, each with owner
83- (
84- {
85- "groups" : [
86- {
87- "name" : "test_group_1" ,
88- "owner" : {"name" : "Owner One" , "email" : "[email protected] " }, 89- },
90- {
91- "name" : "test_group_2" ,
92- "owner" : {"name" : "Owner Two" , "email" : "[email protected] " }, 93- },
94- ]
95- },
96- [
97- ("test_group_1" , "Owner One" , "[email protected] " ), 98- ("test_group_2" , "Owner Two" , "[email protected] " ), 99- ],
100- "two_groups" ,
101- ),
102- ],
103- ids = [
104- "single_group" ,
105- "single_group_without_email" ,
106- "single_group_without_name" ,
107- "single_group_with_additional_fields" ,
108- "two_groups" ,
109- ],
110- )
111- def test_dbt_groups_artifact_parametrized (
112- dbt_project : DbtProject , group_config , expected_groups , test_name , tmp_path
113- ):
114- """
115- Parametrized test for group artifact scenarios:
116- - Single group with owner (name and email)
117- - Single group with owner (name only, no email)
118- - Two groups, each with owner
119- Asserts that the group(s) and owner details are present and correct in the dbt_groups artifact table.
120- """
121- unique_id = str (uuid .uuid4 ()).replace ("-" , "_" )
122- # Patch group and owner names to be unique
123- patched_group_config = {"groups" : []}
124- patched_expected_groups = []
125- for i , group in enumerate (group_config ["groups" ]):
126- group_name = f"{ group ['name' ]} _{ unique_id } _{ i } "
127- owner = group .get ("owner" , {})
128- patched_owner = dict (owner )
129- patched_group = dict (group )
130- patched_group ["name" ] = group_name
131- patched_group ["owner" ] = patched_owner
132- patched_group_config ["groups" ].append (patched_group )
133- for i , (group_name , owner_name , owner_email ) in enumerate (expected_groups ):
134- patched_expected_groups .append (
135- (f"{ group_name } _{ unique_id } _{ i } " , owner_name , owner_email )
136- )
137- with _write_group_config (
138- dbt_project ,
139- patched_group_config ,
140- name = f"groups_test_{ test_name } _{ unique_id } .yml" ,
141- ):
142- dbt_project .dbt_runner .vars ["disable_dbt_artifacts_autoupload" ] = False
143- dbt_project .dbt_runner .run ()
144- dbt_project .assert_table_exists ("dbt_groups" )
145- for group_name , owner_name , owner_email in patched_expected_groups :
146- group = _get_group_from_table (dbt_project , group_name )
147- assert (
148- group is not None
149- ), f"Group { group_name } not found in dbt_groups artifact table."
150- assert _normalize_empty (group .get ("owner_name" )) == _normalize_empty (
151- owner_name
152- ), f"Expected owner name '{ owner_name } ', got '{ group .get ('owner_name' )} '"
153- assert _normalize_empty (group .get ("owner_email" )) == _normalize_empty (
154- owner_email
155- ), f"Expected owner email: '{ owner_email } ', got '{ group .get ('owner_email' )} '"
156-
157-
158- def test_model_group_attribute (dbt_project : DbtProject , tmp_path ):
48+ def test_model_and_groups (dbt_project : DbtProject , tmp_path ):
15949 """
16050 Test that a model assigned to a group inherits the group attribute in the dbt_models artifact table.
16151 Asserts that the model row has the correct group_name.
52+ Asserts that the group exists in the dbt_groups artifact table.
53+ This test tests both things although it is not a best practice. We decided to do it
54+ to save running time since these tests are very slow.
16255 """
56+
16357 unique_id = str (uuid .uuid4 ()).replace ("-" , "_" )
16458 model_name = f"model_with_group_{ unique_id } "
16559 group_name = f"test_group_{ unique_id } "
@@ -201,6 +95,7 @@ def test_model_group_attribute(dbt_project: DbtProject, tmp_path):
20195 dbt_project .dbt_runner .vars ["disable_dbt_artifacts_autoupload" ] = False
20296 dbt_project .dbt_runner .run (select = model_name )
20397 dbt_project .assert_table_exists ("dbt_models" )
98+
20499 models = dbt_project .read_table (
205100 "dbt_models" , where = f"name = '{ model_name } '" , raise_if_empty = True
206101 )
@@ -209,11 +104,132 @@ def test_model_group_attribute(dbt_project: DbtProject, tmp_path):
209104 assert (
210105 model_row ["group_name" ] == group_name
211106 ), f"Expected group_name { group_name } , got { model_row ['group_name' ]} "
107+
108+ # Assert group exists in dbt_groups table
109+ group_row = _get_group_from_table (dbt_project , group_name )
110+ assert (
111+ group_row is not None
112+ ), f"Group { group_name } not found in dbt_groups artifact table."
113+ assert _normalize_empty (group_row .get ("owner_name" )) == _normalize_empty (
114+ OWNER_NAME
115+ ), f"Expected owner name '{ OWNER_NAME } ', got '{ group_row .get ('owner_name' )} '"
116+ assert _normalize_empty (group_row .get ("owner_email" )) == _normalize_empty (
117+ OWNER_EMAIL
118+ ), f"Expected owner email '{ OWNER_EMAIL } ', got '{ group_row .get ('owner_email' )} '"
119+
212120 finally :
213121 if dbt_model_path .exists ():
214122 dbt_model_path .unlink ()
215123
216124
125+ def test_two_groups (dbt_project : DbtProject , tmp_path ):
126+ """
127+ Test that two models assigned to two different groups inherit the correct group attribute in the dbt_models artifact table.
128+ Asserts that both model rows have the correct group_name, and both groups exist in dbt_groups.
129+ This test also tests that dbt_groups is filled with the correct owner info when name or email are not provided.
130+ """
131+ unique_id = str (uuid .uuid4 ()).replace ("-" , "_" )
132+ model_name_1 = f"model_1_with_group_{ unique_id } "
133+ model_name_2 = f"model_2_with_group_{ unique_id } "
134+ group_name_1 = f"test_group_1_{ unique_id } "
135+ group_name_2 = f"test_group_2_{ unique_id } "
136+ owner_email_1 = OWNER_EMAIL
137+ owner_name_2 = "Other Owner"
138+ model_sql = """
139+ select 1 as col
140+ """
141+ schema_yaml = {
142+ "version" : 2 ,
143+ "models" : [
144+ {
145+ "name" : model_name_1 ,
146+ "group" : group_name_1 ,
147+ "description" : "A model assigned to group 1 for testing" ,
148+ },
149+ {
150+ "name" : model_name_2 ,
151+ "group" : group_name_2 ,
152+ "description" : "A model assigned to group 2 for testing" ,
153+ },
154+ ],
155+ }
156+ group_config = {
157+ "groups" : [
158+ {
159+ "name" : group_name_1 ,
160+ "owner" : {
161+ "email" : owner_email_1 ,
162+ "slack" : "slack_channel_1" ,
163+ },
164+ },
165+ {
166+ "name" : group_name_2 ,
167+ "owner" : {
168+ "name" : owner_name_2 ,
169+ },
170+ },
171+ ]
172+ }
173+ with _write_group_config (
174+ dbt_project , group_config , name = f"groups_test_two_groups_{ unique_id } .yml"
175+ ), dbt_project .write_yaml (
176+ schema_yaml , name = f"schema_model_with_two_groups_{ unique_id } .yml"
177+ ):
178+ # Write both model files
179+ model_path_1 = tmp_path / f"{ model_name_1 } .sql"
180+ model_path_2 = tmp_path / f"{ model_name_2 } .sql"
181+ model_path_1 .write_text (model_sql )
182+ model_path_2 .write_text (model_sql )
183+ dbt_model_path_1 = dbt_project .models_dir_path / "tmp" / f"{ model_name_1 } .sql"
184+ dbt_model_path_2 = dbt_project .models_dir_path / "tmp" / f"{ model_name_2 } .sql"
185+ dbt_model_path_1 .parent .mkdir (parents = True , exist_ok = True )
186+ dbt_model_path_1 .write_text (model_sql )
187+ dbt_model_path_2 .parent .mkdir (parents = True , exist_ok = True )
188+ dbt_model_path_2 .write_text (model_sql )
189+ try :
190+ dbt_project .dbt_runner .vars ["disable_dbt_artifacts_autoupload" ] = False
191+ dbt_project .dbt_runner .run (select = f"{ model_name_1 } { model_name_2 } " )
192+ dbt_project .assert_table_exists ("dbt_models" )
193+
194+ # Check both models and their groups/owners
195+ for model_name , group_name , owner_name , owner_email in [
196+ (model_name_1 , group_name_1 , None , owner_email_1 ),
197+ (model_name_2 , group_name_2 , owner_name_2 , None ),
198+ ]:
199+ models = dbt_project .read_table (
200+ "dbt_models" , where = f"name = '{ model_name } '" , raise_if_empty = True
201+ )
202+ assert (
203+ len (models ) == 1
204+ ), f"Expected 1 model for { model_name } , got { len (models )} "
205+ model_row = models [0 ]
206+ assert (
207+ model_row ["group_name" ] == group_name
208+ ), f"Expected group_name { group_name } , got { model_row ['group_name' ]} for model { model_name } "
209+
210+ # Assert group exists in dbt_groups table and owner info is correct
211+ group_row = _get_group_from_table (dbt_project , group_name )
212+ assert (
213+ group_row is not None
214+ ), f"Group { group_name } not found in dbt_groups artifact table."
215+ assert _normalize_empty (
216+ group_row .get ("owner_name" )
217+ ) == _normalize_empty (
218+ owner_name
219+ ), f"Expected owner name '{ owner_name } ', got '{ group_row .get ('owner_name' )} '"
220+ assert _normalize_empty (
221+ group_row .get ("owner_email" )
222+ ) == _normalize_empty (
223+ owner_email
224+ ), f"Expected owner email '{ owner_email } ', got '{ group_row .get ('owner_email' )} '"
225+
226+ finally :
227+ if dbt_model_path_1 .exists ():
228+ dbt_model_path_1 .unlink ()
229+ if dbt_model_path_2 .exists ():
230+ dbt_model_path_2 .unlink ()
231+
232+
217233def test_test_group_attribute (dbt_project : DbtProject , tmp_path ):
218234 """
219235 Test that a test on a model assigned to a group inherits the group attribute in the dbt_tests artifact table.
@@ -462,7 +478,7 @@ def test_snapshot_group_attribute(dbt_project: DbtProject, tmp_path):
462478 dbt_snapshot_path .write_text (snapshot_sql )
463479 # Run dbt snapshot (runs all snapshots, as selecting is not supported by the runner)
464480 dbt_project .dbt_runner .vars ["disable_dbt_artifacts_autoupload" ] = False
465- dbt_project .dbt_runner .run ()
481+ dbt_project .dbt_runner .snapshot ()
466482 dbt_project .assert_table_exists ("dbt_snapshots" )
467483 snapshots = dbt_project .read_table (
468484 "dbt_snapshots" , where = f"name = '{ snapshot_name } '" , raise_if_empty = False
0 commit comments