33
44import pytest
55
6+ from pyatlan .client .asset import IndexSearchResults
67from pyatlan .errors import ErrorCode , InvalidRequestError
78from pyatlan .model .assets import Column , DataQualityRule , Table
89from pyatlan .model .dq_rule_conditions import DQRuleConditionsBuilder
910from pyatlan .model .enums import (
1011 DataQualityDimension ,
1112 DataQualityRuleAlertPriority ,
13+ DataQualityRuleCustomSQLReturnType ,
1214 DataQualityRuleStatus ,
1315 DataQualityRuleTemplateConfigRuleConditions ,
1416 DataQualityRuleThresholdCompareOperator ,
@@ -287,7 +289,6 @@ def test_column_level_rule_creator_with_missing_parameters_raise_value_error(
287289 )
288290
289291
290- ## Change below
291292def test_table_level_rule_creator (mock_client ):
292293 asset = Table .ref_by_qualified_name (qualified_name = DQ_TABLE_QUALIFIED_NAME )
293294
@@ -305,6 +306,23 @@ def test_table_level_rule_creator(mock_client):
305306 assert dq_rule .qualified_name .startswith (f"{ DQ_TABLE_QUALIFIED_NAME } /rule/" )
306307
307308
309+ def test_table_level_rule_creator_with_threshold_unit (mock_client ):
310+ asset = Table .ref_by_qualified_name (qualified_name = DQ_TABLE_QUALIFIED_NAME )
311+
312+ dq_rule = DataQualityRule .table_level_rule_creator (
313+ client = mock_client ,
314+ rule_type = DQ_RULE_TYPE_TABLE ,
315+ asset = asset ,
316+ threshold_compare_operator = DataQualityRuleThresholdCompareOperator .LESS_THAN_EQUAL ,
317+ threshold_value = DQ_RULE_THRESHOLD_VALUE ,
318+ alert_priority = DataQualityRuleAlertPriority .NORMAL ,
319+ threshold_unit = DataQualityRuleThresholdUnit .ABSOLUTE ,
320+ )
321+
322+ assert dq_rule .dq_rule_alert_priority == DataQualityRuleAlertPriority .NORMAL
323+ assert dq_rule .dq_rule_status == DataQualityRuleStatus .ACTIVE
324+
325+
308326def test_custom_sql_creator (mock_client ):
309327 asset = Table .ref_by_qualified_name (qualified_name = DQ_TABLE_QUALIFIED_NAME )
310328
@@ -347,6 +365,27 @@ def test_custom_sql_creator_with_optional_parameters(mock_client):
347365 assert dq_rule .user_description == DQ_RULE_DESCRIPTION
348366
349367
368+ def test_custom_sql_creator_with_custom_sql_return_type (mock_client ):
369+ asset = Table .ref_by_qualified_name (qualified_name = DQ_TABLE_QUALIFIED_NAME )
370+
371+ dq_rule = DataQualityRule .custom_sql_creator (
372+ client = mock_client ,
373+ rule_name = DQ_RULE_NAME ,
374+ asset = asset ,
375+ custom_sql = DQ_RULE_CUSTOM_SQL ,
376+ threshold_compare_operator = DataQualityRuleThresholdCompareOperator .LESS_THAN_EQUAL ,
377+ threshold_value = DQ_RULE_THRESHOLD_VALUE ,
378+ alert_priority = DataQualityRuleAlertPriority .NORMAL ,
379+ dimension = DataQualityDimension .COMPLETENESS ,
380+ custom_sql_return_type = DataQualityRuleCustomSQLReturnType .ROW_COUNT ,
381+ )
382+
383+ assert (
384+ dq_rule .dq_rule_custom_s_q_l_return_type
385+ == DataQualityRuleCustomSQLReturnType .ROW_COUNT
386+ )
387+
388+
350389def test_column_level_rule_creator (mock_client ):
351390 asset = Table .ref_by_qualified_name (qualified_name = DQ_TABLE_QUALIFIED_NAME )
352391 column = Column .ref_by_qualified_name (qualified_name = DQ_COLUMN_QUALIFIED_NAME )
@@ -391,6 +430,10 @@ def test_column_level_rule_creator_with_row_scope_filtering(mock_client):
391430 asset .asset_d_q_row_scope_filter_column_qualified_name = DQ_COLUMN_QUALIFIED_NAME
392431 column = Column .ref_by_qualified_name (qualified_name = DQ_COLUMN_QUALIFIED_NAME )
393432
433+ search_results = Mock (spec = IndexSearchResults )
434+ search_results .current_page .return_value = [asset ]
435+ mock_client .asset .search .return_value = search_results
436+
394437 dq_rule = DataQualityRule .column_level_rule_creator (
395438 client = mock_client ,
396439 rule_type = DQ_RULE_TYPE_COLUMN ,
@@ -593,3 +636,111 @@ def test_validate_template_features_row_scope_filter_column_missing(mock_client)
593636 threshold_compare_operator = DataQualityRuleThresholdCompareOperator .EQUAL ,
594637 asset = table_asset ,
595638 )
639+
640+
641+ def test_fetch_assets_for_row_scope_validation_disabled (mock_client ):
642+ asset = Table .ref_by_qualified_name (qualified_name = DQ_TABLE_QUALIFIED_NAME )
643+
644+ asset_for_validation , target_table_asset = (
645+ DataQualityRule .Attributes ._fetch_assets_for_row_scope_validation (
646+ client = mock_client ,
647+ base_asset = asset ,
648+ rule_conditions = None ,
649+ row_scope_filtering_enabled = False ,
650+ )
651+ )
652+
653+ assert asset_for_validation == asset
654+ assert target_table_asset is None
655+
656+
657+ def test_fetch_assets_for_row_scope_validation_with_target_table (mock_client ):
658+ asset = Table .ref_by_qualified_name (qualified_name = DQ_TABLE_QUALIFIED_NAME )
659+ asset .asset_d_q_row_scope_filter_column_qualified_name = DQ_COLUMN_QUALIFIED_NAME
660+ target_table = Table .ref_by_qualified_name (
661+ qualified_name = "target/table/qualified_name"
662+ )
663+ target_table .asset_d_q_row_scope_filter_column_qualified_name = (
664+ DQ_COLUMN_QUALIFIED_NAME
665+ )
666+
667+ search_results = Mock (spec = IndexSearchResults )
668+ search_results .current_page .return_value = [asset , target_table ]
669+ mock_client .asset .search .return_value = search_results
670+
671+ rule_conditions = (
672+ DQRuleConditionsBuilder ()
673+ .add_condition (
674+ type = DataQualityRuleTemplateConfigRuleConditions .ROW_COUNT_RECON ,
675+ target_table = "target/table/qualified_name" ,
676+ )
677+ .build ()
678+ )
679+
680+ asset_for_validation , target_table_asset = (
681+ DataQualityRule .Attributes ._fetch_assets_for_row_scope_validation (
682+ client = mock_client ,
683+ base_asset = asset ,
684+ rule_conditions = rule_conditions ,
685+ row_scope_filtering_enabled = True ,
686+ )
687+ )
688+
689+ assert asset_for_validation == asset
690+ assert target_table_asset == target_table
691+
692+
693+ def test_dq_condition_in_list_reference ():
694+ rule_conditions = (
695+ DQRuleConditionsBuilder ()
696+ .add_condition (
697+ type = DataQualityRuleTemplateConfigRuleConditions .IN_LIST_REFERENCE ,
698+ reference_table = "reference/table/qualified_name" ,
699+ reference_column = "reference/column/qualified_name" ,
700+ )
701+ .build ()
702+ )
703+
704+ condition = json .loads (rule_conditions )["conditions" ][0 ]
705+ assert condition ["type" ] == "IN_LIST_REFERENCE"
706+ assert condition ["value" ]["reference_table" ] == "reference/table/qualified_name"
707+ assert condition ["value" ]["reference_column" ] == "reference/column/qualified_name"
708+
709+
710+ def test_dq_condition_recon_with_target_table_and_column ():
711+ rule_conditions = (
712+ DQRuleConditionsBuilder ()
713+ .add_condition (
714+ type = DataQualityRuleTemplateConfigRuleConditions .AVERAGE_RECON ,
715+ target_table = "target/table/qualified_name" ,
716+ target_column = "target/column/qualified_name" ,
717+ )
718+ .build ()
719+ )
720+
721+ condition = json .loads (rule_conditions )["conditions" ][0 ]
722+ assert condition ["type" ] == "AVERAGE_RECON"
723+ assert condition ["value" ]["target_table" ] == "target/table/qualified_name"
724+ assert condition ["value" ]["target_column" ] == "target/column/qualified_name"
725+
726+
727+ def test_dq_condition_missing_required_fields ():
728+ with pytest .raises (ValueError , match = "reference_table is required" ):
729+ DQRuleConditionsBuilder ().add_condition (
730+ type = DataQualityRuleTemplateConfigRuleConditions .IN_LIST_REFERENCE ,
731+ reference_table = None ,
732+ reference_column = "reference/column/qualified_name" ,
733+ ).build ()
734+
735+ with pytest .raises (ValueError , match = "target_table is required" ):
736+ DQRuleConditionsBuilder ().add_condition (
737+ type = DataQualityRuleTemplateConfigRuleConditions .ROW_COUNT_RECON ,
738+ target_table = None ,
739+ ).build ()
740+
741+ with pytest .raises (ValueError , match = "target_column is required" ):
742+ DQRuleConditionsBuilder ().add_condition (
743+ type = DataQualityRuleTemplateConfigRuleConditions .AVERAGE_RECON ,
744+ target_table = "target/table/qualified_name" ,
745+ target_column = None ,
746+ ).build ()
0 commit comments