dataops-testgen 2.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dataops_testgen-2.2.0.dist-info/LICENSE +203 -0
- dataops_testgen-2.2.0.dist-info/METADATA +287 -0
- dataops_testgen-2.2.0.dist-info/NOTICE +5 -0
- dataops_testgen-2.2.0.dist-info/RECORD +270 -0
- dataops_testgen-2.2.0.dist-info/WHEEL +5 -0
- dataops_testgen-2.2.0.dist-info/entry_points.txt +2 -0
- dataops_testgen-2.2.0.dist-info/top_level.txt +1 -0
- testgen/__init__.py +0 -0
- testgen/__main__.py +770 -0
- testgen/commands/__init__.py +0 -0
- testgen/commands/queries/__init__.py +0 -0
- testgen/commands/queries/execute_cat_tests_query.py +95 -0
- testgen/commands/queries/execute_tests_query.py +160 -0
- testgen/commands/queries/generate_tests_query.py +94 -0
- testgen/commands/queries/profiling_query.py +366 -0
- testgen/commands/queries/test_parameter_validation_query.py +88 -0
- testgen/commands/run_execute_cat_tests.py +162 -0
- testgen/commands/run_execute_tests.py +168 -0
- testgen/commands/run_generate_tests.py +107 -0
- testgen/commands/run_get_entities.py +122 -0
- testgen/commands/run_launch_db_config.py +84 -0
- testgen/commands/run_observability_exporter.py +330 -0
- testgen/commands/run_profiling_bridge.py +495 -0
- testgen/commands/run_quick_start.py +168 -0
- testgen/commands/run_setup_profiling_tools.py +96 -0
- testgen/commands/run_test_definition.py +146 -0
- testgen/commands/run_test_parameter_validation.py +135 -0
- testgen/commands/run_upgrade_db_config.py +156 -0
- testgen/common/__init__.py +8 -0
- testgen/common/clean_sql.py +53 -0
- testgen/common/credentials.py +25 -0
- testgen/common/database/__init__.py +0 -0
- testgen/common/database/database_service.py +629 -0
- testgen/common/database/flavor/__init__.py +0 -0
- testgen/common/database/flavor/flavor_service.py +75 -0
- testgen/common/database/flavor/mssql_flavor_service.py +34 -0
- testgen/common/database/flavor/postgresql_flavor_service.py +5 -0
- testgen/common/database/flavor/redshift_flavor_service.py +22 -0
- testgen/common/database/flavor/snowflake_flavor_service.py +69 -0
- testgen/common/database/flavor/trino_flavor_service.py +21 -0
- testgen/common/date_service.py +68 -0
- testgen/common/display_service.py +85 -0
- testgen/common/docker_service.py +76 -0
- testgen/common/encrypt.py +55 -0
- testgen/common/get_pipeline_parms.py +57 -0
- testgen/common/logs.py +79 -0
- testgen/common/process_service.py +62 -0
- testgen/common/read_file.py +69 -0
- testgen/settings.py +440 -0
- testgen/template/dbsetup/010_create_base_schema.sql +2 -0
- testgen/template/dbsetup/020_create_standard_functions_sprocs.sql +179 -0
- testgen/template/dbsetup/030_initialize_new_schema_structure.sql +735 -0
- testgen/template/dbsetup/040_populate_new_schema_project.sql +59 -0
- testgen/template/dbsetup/050_populate_new_schema_metadata.sql +1517 -0
- testgen/template/dbsetup/060_create_standard_views.sql +248 -0
- testgen/template/dbsetup/070_create_default_users.sql +17 -0
- testgen/template/dbsetup/075_grant_role_rights.sql +43 -0
- testgen/template/dbsetup/080_set_current_revision.sql +5 -0
- testgen/template/dbupgrade/0100_incremental_upgrade.sql +5 -0
- testgen/template/dbupgrade/0101_incremental_upgrade.sql +15 -0
- testgen/template/dbupgrade/0102_incremental_upgrade.sql +4 -0
- testgen/template/dbupgrade/0103_incremental_upgrade.sql +22 -0
- testgen/template/dbupgrade/0104_incremental_upgrade.sql +44 -0
- testgen/template/dbupgrade/0105_incremental_upgrade.sql +1 -0
- testgen/template/dbupgrade/0106_incremental_upgrade.sql +5 -0
- testgen/template/dbupgrade/0107_incremental_upgrade.sql +3 -0
- testgen/template/dbupgrade_helpers/get_tg_revision.sql +2 -0
- testgen/template/exec_cat_tests/ex_cat_build_agg_table_tests.sql +116 -0
- testgen/template/exec_cat_tests/ex_cat_get_distinct_tables.sql +11 -0
- testgen/template/exec_cat_tests/ex_cat_results_parse.sql +69 -0
- testgen/template/exec_cat_tests/ex_cat_retrieve_agg_test_parms.sql +6 -0
- testgen/template/exec_cat_tests/ex_cat_test_query.sql +8 -0
- testgen/template/execution/ex_finalize_test_run_results.sql +37 -0
- testgen/template/execution/ex_get_tests_non_cat.sql +47 -0
- testgen/template/execution/ex_update_test_record_in_testrun_table.sql +27 -0
- testgen/template/execution/ex_write_test_record_to_testrun_table.sql +6 -0
- testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_no_drops_generic.sql +48 -0
- testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_num_incr_generic.sql +34 -0
- testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_percent_above_generic.sql +49 -0
- testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_percent_within_generic.sql +49 -0
- testgen/template/flavors/generic/exec_query_tests/ex_aggregate_match_same_generic.sql +49 -0
- testgen/template/flavors/generic/exec_query_tests/ex_custom_query_generic.sql +39 -0
- testgen/template/flavors/generic/exec_query_tests/ex_data_match_2way_generic.sql +58 -0
- testgen/template/flavors/generic/exec_query_tests/ex_data_match_generic.sql +44 -0
- testgen/template/flavors/generic/exec_query_tests/ex_prior_match_generic.sql +37 -0
- testgen/template/flavors/generic/exec_query_tests/ex_relative_entropy_generic.sql +53 -0
- testgen/template/flavors/generic/exec_query_tests/ex_window_match_no_drops_generic.sql +46 -0
- testgen/template/flavors/generic/exec_query_tests/ex_window_match_same_generic.sql +59 -0
- testgen/template/flavors/generic/profiling/contingency_counts.sql +3 -0
- testgen/template/flavors/generic/validate_tests/ex_get_project_column_list_generic.sql +3 -0
- testgen/template/flavors/mssql/exec_query_tests/ex_relative_entropy_mssql.sql +53 -0
- testgen/template/flavors/mssql/profiling/project_ddf_query_mssql.sql +35 -0
- testgen/template/flavors/mssql/profiling/project_profiling_query_mssql.yaml +246 -0
- testgen/template/flavors/mssql/profiling/project_secondary_profiling_query_mssql.sql +36 -0
- testgen/template/flavors/mssql/setup_profiling_tools/00_drop_existing_functions_mssql.sql +8 -0
- testgen/template/flavors/mssql/setup_profiling_tools/01_create_functions_mssql.sql +12 -0
- testgen/template/flavors/mssql/setup_profiling_tools/02_create_functions_mssql.sql +54 -0
- testgen/template/flavors/mssql/setup_profiling_tools/create_qc_schema_mssql.sql +4 -0
- testgen/template/flavors/mssql/setup_profiling_tools/grant_execute_privileges_mssql.sql +1 -0
- testgen/template/flavors/postgresql/exec_query_tests/ex_window_match_no_drops_postgresql.sql +46 -0
- testgen/template/flavors/postgresql/exec_query_tests/ex_window_match_same_postgresql.sql +59 -0
- testgen/template/flavors/postgresql/profiling/project_ddf_query_postgresql.sql +42 -0
- testgen/template/flavors/postgresql/profiling/project_profiling_query_postgresql.yaml +225 -0
- testgen/template/flavors/postgresql/profiling/project_secondary_profiling_query_postgresql.sql +28 -0
- testgen/template/flavors/postgresql/setup_profiling_tools/create_functions_postgresql.sql +157 -0
- testgen/template/flavors/postgresql/setup_profiling_tools/create_qc_schema_postgresql.sql +1 -0
- testgen/template/flavors/postgresql/setup_profiling_tools/grant_execute_privileges_postgresql.sql +2 -0
- testgen/template/flavors/redshift/profiling/project_ddf_query_redshift.sql +38 -0
- testgen/template/flavors/redshift/profiling/project_profiling_query_redshift.yaml +221 -0
- testgen/template/flavors/redshift/profiling/project_secondary_profiling_query_redshift.sql +29 -0
- testgen/template/flavors/redshift/setup_profiling_tools/create_functions_redshift.sql +115 -0
- testgen/template/flavors/redshift/setup_profiling_tools/create_qc_schema_redshift.sql +1 -0
- testgen/template/flavors/redshift/setup_profiling_tools/grant_execute_privileges_redshift.sql +2 -0
- testgen/template/flavors/snowflake/profiling/project_ddf_query_snowflake.sql +38 -0
- testgen/template/flavors/snowflake/profiling/project_profiling_query_snowflake.yaml +220 -0
- testgen/template/flavors/snowflake/profiling/project_secondary_profiling_query_snowflake.sql +29 -0
- testgen/template/flavors/snowflake/setup_profiling_tools/create_functions_snowflake.sql +69 -0
- testgen/template/flavors/snowflake/setup_profiling_tools/create_qc_schema_snowflake.sql +1 -0
- testgen/template/flavors/snowflake/setup_profiling_tools/grant_execute_privileges_snowflake.sql +6 -0
- testgen/template/flavors/trino/profiling/project_profiling_query_trino.yaml +219 -0
- testgen/template/flavors/trino/setup_profiling_tools/create_functions_trino.sql +92 -0
- testgen/template/flavors/trino/setup_profiling_tools/create_qc_schema_trino.sql +1 -0
- testgen/template/gen_funny_cat_tests/gen_test_constant.sql +104 -0
- testgen/template/gen_funny_cat_tests/gen_test_distinct_value_ct.sql +98 -0
- testgen/template/gen_funny_cat_tests/gen_test_row_ct.sql +57 -0
- testgen/template/gen_funny_cat_tests/gen_test_row_ct_pct.sql +59 -0
- testgen/template/generation/gen_delete_old_tests.sql +5 -0
- testgen/template/generation/gen_insert_test_suite.sql +5 -0
- testgen/template/generation/gen_retrieve_or_insert_test_suite.sql +58 -0
- testgen/template/generation/gen_standard_test_type_list.sql +13 -0
- testgen/template/generation/gen_standard_tests.sql +48 -0
- testgen/template/get_entities/get_connection.sql +21 -0
- testgen/template/get_entities/get_connections_list.sql +9 -0
- testgen/template/get_entities/get_latest.sql +4 -0
- testgen/template/get_entities/get_profile.sql +12 -0
- testgen/template/get_entities/get_profile_info.sql +17 -0
- testgen/template/get_entities/get_profile_list.sql +17 -0
- testgen/template/get_entities/get_profile_screen.sql +275 -0
- testgen/template/get_entities/get_project_list.sql +6 -0
- testgen/template/get_entities/get_table_group_list.sql +10 -0
- testgen/template/get_entities/get_test_generation_list.sql +18 -0
- testgen/template/get_entities/get_test_info.sql +41 -0
- testgen/template/get_entities/get_test_results_for_run_cli.sql +16 -0
- testgen/template/get_entities/get_test_run_list.sql +24 -0
- testgen/template/get_entities/get_test_suite.sql +13 -0
- testgen/template/get_entities/get_test_suite_list.sql +18 -0
- testgen/template/get_entities/list_test_types.sql +4 -0
- testgen/template/observability/get_event_data.sql +23 -0
- testgen/template/observability/get_test_results.sql +41 -0
- testgen/template/observability/update_test_results_exported_to_observability.sql +12 -0
- testgen/template/parms/parms_profiling.sql +34 -0
- testgen/template/parms/parms_test_execution.sql +13 -0
- testgen/template/parms/parms_test_gen.sql +23 -0
- testgen/template/profiling/contingency_columns.sql +7 -0
- testgen/template/profiling/datatype_suggestions.sql +56 -0
- testgen/template/profiling/functional_datatype.sql +523 -0
- testgen/template/profiling/functional_tabletype_stage.sql +48 -0
- testgen/template/profiling/functional_tabletype_update.sql +8 -0
- testgen/template/profiling/pii_flag.sql +133 -0
- testgen/template/profiling/profile_anomalies_screen_column.sql +22 -0
- testgen/template/profiling/profile_anomalies_screen_multi_column.sql +58 -0
- testgen/template/profiling/profile_anomalies_screen_table.sql +22 -0
- testgen/template/profiling/profile_anomalies_screen_table_dates.sql +30 -0
- testgen/template/profiling/profile_anomalies_screen_variants.sql +40 -0
- testgen/template/profiling/profile_anomaly_types_get.sql +3 -0
- testgen/template/profiling/project_get_table_sample_count.sql +22 -0
- testgen/template/profiling/project_profile_run_record_insert.sql +8 -0
- testgen/template/profiling/project_profile_run_record_update.sql +5 -0
- testgen/template/profiling/project_profile_run_record_update_status.sql +5 -0
- testgen/template/profiling/project_update_profile_results_to_estimates.sql +32 -0
- testgen/template/profiling/refresh_anomalies.sql +33 -0
- testgen/template/profiling/refresh_data_chars_from_profiling.sql +156 -0
- testgen/template/profiling/secondary_profiling_columns.sql +12 -0
- testgen/template/profiling/secondary_profiling_delete.sql +4 -0
- testgen/template/profiling/secondary_profiling_update.sql +18 -0
- testgen/template/quick_start/populate_target_data.sql +1077 -0
- testgen/template/quick_start/recreate_target_data_schema.sql +167 -0
- testgen/template/quick_start/update_target_data.sql +100 -0
- testgen/template/updates/create_tmp_test_definition.sql +19 -0
- testgen/template/updates/get_test_def_parms.sql +38 -0
- testgen/template/updates/populate_stg_test_definitions.sql +184 -0
- testgen/template/validate_tests/ex_disable_tests_test_definitions.sql +5 -0
- testgen/template/validate_tests/ex_flag_tests_test_definitions.sql +64 -0
- testgen/template/validate_tests/ex_get_project_column_list_generic.sql +3 -0
- testgen/template/validate_tests/ex_get_test_column_list_tg.sql +65 -0
- testgen/template/validate_tests/ex_write_test_val_errors.sql +22 -0
- testgen/ui/__init__.py +0 -0
- testgen/ui/app.py +98 -0
- testgen/ui/assets/dk_logo.svg +46 -0
- testgen/ui/assets/question_mark.png +0 -0
- testgen/ui/assets/scripts.js +68 -0
- testgen/ui/assets/style.css +140 -0
- testgen/ui/bootstrap.py +109 -0
- testgen/ui/components/__init__.py +0 -0
- testgen/ui/components/frontend/css/KFOlCnqEu92Fr1MmEU9fBBc4.woff2 +0 -0
- testgen/ui/components/frontend/css/KFOlCnqEu92Fr1MmEU9fChc4EsA.woff2 +0 -0
- testgen/ui/components/frontend/css/KFOmCnqEu92Fr1Mu4mxK.woff2 +0 -0
- testgen/ui/components/frontend/css/KFOmCnqEu92Fr1Mu7GxKOzY.woff2 +0 -0
- testgen/ui/components/frontend/css/material-symbols-rounded.css +24 -0
- testgen/ui/components/frontend/css/material-symbols-rounded.woff2 +0 -0
- testgen/ui/components/frontend/css/roboto-font-faces.css +35 -0
- testgen/ui/components/frontend/css/shared.css +36 -0
- testgen/ui/components/frontend/img/dk_logo.svg +46 -0
- testgen/ui/components/frontend/index.html +17 -0
- testgen/ui/components/frontend/js/components/breadcrumbs.js +86 -0
- testgen/ui/components/frontend/js/components/button.js +66 -0
- testgen/ui/components/frontend/js/components/location.js +62 -0
- testgen/ui/components/frontend/js/components/select.js +75 -0
- testgen/ui/components/frontend/js/components/sidebar.js +358 -0
- testgen/ui/components/frontend/js/main.js +99 -0
- testgen/ui/components/frontend/js/streamlit.js +19 -0
- testgen/ui/components/frontend/js/van.min.js +1 -0
- testgen/ui/components/utils/__init__.py +0 -0
- testgen/ui/components/utils/callbacks.py +51 -0
- testgen/ui/components/utils/component.py +13 -0
- testgen/ui/components/widgets/__init__.py +6 -0
- testgen/ui/components/widgets/breadcrumbs.py +32 -0
- testgen/ui/components/widgets/location.py +65 -0
- testgen/ui/components/widgets/modal.py +97 -0
- testgen/ui/components/widgets/sidebar.py +69 -0
- testgen/ui/navigation/__init__.py +0 -0
- testgen/ui/navigation/menu.py +42 -0
- testgen/ui/navigation/page.py +20 -0
- testgen/ui/navigation/router.py +63 -0
- testgen/ui/queries/__init__.py +0 -0
- testgen/ui/queries/authentication_queries.py +47 -0
- testgen/ui/queries/connection_queries.py +121 -0
- testgen/ui/queries/profiling_queries.py +148 -0
- testgen/ui/queries/project_queries.py +9 -0
- testgen/ui/queries/table_group_queries.py +186 -0
- testgen/ui/queries/test_definition_queries.py +270 -0
- testgen/ui/queries/test_run_queries.py +32 -0
- testgen/ui/queries/test_suite_queries.py +145 -0
- testgen/ui/scripts/__init__.py +0 -0
- testgen/ui/scripts/patch_streamlit.py +111 -0
- testgen/ui/services/__init__.py +0 -0
- testgen/ui/services/authentication_service.py +119 -0
- testgen/ui/services/connection_service.py +220 -0
- testgen/ui/services/database_service.py +282 -0
- testgen/ui/services/form_service.py +1008 -0
- testgen/ui/services/javascript_service.py +44 -0
- testgen/ui/services/query_service.py +316 -0
- testgen/ui/services/string_service.py +12 -0
- testgen/ui/services/table_group_service.py +130 -0
- testgen/ui/services/test_definition_service.py +117 -0
- testgen/ui/services/test_run_service.py +13 -0
- testgen/ui/services/test_suite_service.py +76 -0
- testgen/ui/services/toolbar_service.py +77 -0
- testgen/ui/session.py +46 -0
- testgen/ui/views/__init__.py +0 -0
- testgen/ui/views/app_log_modal.py +92 -0
- testgen/ui/views/connections.py +72 -0
- testgen/ui/views/connections_base.py +367 -0
- testgen/ui/views/login.py +40 -0
- testgen/ui/views/not_found.py +16 -0
- testgen/ui/views/overview.py +34 -0
- testgen/ui/views/profiling_anomalies.py +501 -0
- testgen/ui/views/profiling_details.py +335 -0
- testgen/ui/views/profiling_modal.py +40 -0
- testgen/ui/views/profiling_results.py +206 -0
- testgen/ui/views/profiling_summary.py +177 -0
- testgen/ui/views/project_settings.py +74 -0
- testgen/ui/views/table_groups.py +530 -0
- testgen/ui/views/test_definitions.py +1020 -0
- testgen/ui/views/test_results.py +908 -0
- testgen/ui/views/test_runs.py +195 -0
- testgen/ui/views/test_suites.py +545 -0
- testgen/utils/__init__.py +0 -0
- testgen/utils/plugins.py +17 -0
- testgen/utils/singleton.py +14 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from streamlit_javascript import st_javascript
|
|
4
|
+
|
|
5
|
+
from testgen.ui.services.authentication_service import AUTH_TOKEN_COOKIE_NAME
|
|
6
|
+
|
|
7
|
+
LOG = logging.getLogger("testgen")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def copy_to_clipboard(text):
|
|
11
|
+
script = f"""await (async function () {{
|
|
12
|
+
window.parent.postMessage({{ type: 'TestgenCopyToClipboard', text: '{text}' }}, '*');
|
|
13
|
+
return 0;
|
|
14
|
+
}})()
|
|
15
|
+
"""
|
|
16
|
+
execute_javascript(script)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def clear_component_states():
|
|
20
|
+
execute_javascript(
|
|
21
|
+
f"""await (async function () {{
|
|
22
|
+
window.parent.postMessage({{ type: 'TestgenLogout', cookie: '{AUTH_TOKEN_COOKIE_NAME}' }}, '*');
|
|
23
|
+
return 0;
|
|
24
|
+
}})()
|
|
25
|
+
"""
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def execute_javascript(script):
|
|
30
|
+
return_value = st_javascript(script)
|
|
31
|
+
if return_value != 0:
|
|
32
|
+
LOG.warning(f"execute_javascript returned with non zero value: {return_value}, script: {script}")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_browser_locale_timezone():
|
|
36
|
+
from streamlit_javascript import st_javascript
|
|
37
|
+
|
|
38
|
+
return st_javascript(
|
|
39
|
+
"""await (async () => {
|
|
40
|
+
const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
41
|
+
console.log(userTimezone)
|
|
42
|
+
return userTimezone
|
|
43
|
+
})().then(returnValue => returnValue)"""
|
|
44
|
+
)
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import testgen.ui.services.database_service as db
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
Shared queries for standard lookups
|
|
5
|
+
- should be called by cached functions within page
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def run_project_lookup_query(str_schema):
|
|
10
|
+
str_sql = f"""
|
|
11
|
+
SELECT
|
|
12
|
+
id::VARCHAR(50),
|
|
13
|
+
project_code,
|
|
14
|
+
project_name,
|
|
15
|
+
effective_from_date,
|
|
16
|
+
observability_api_url,
|
|
17
|
+
observability_api_key
|
|
18
|
+
FROM {str_schema}.projects
|
|
19
|
+
ORDER BY project_name
|
|
20
|
+
"""
|
|
21
|
+
return db.retrieve_data(str_sql)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_project_by_code(schema: str, project_code: str):
|
|
25
|
+
str_sql = f"""
|
|
26
|
+
SELECT
|
|
27
|
+
id::VARCHAR(50),
|
|
28
|
+
project_code,
|
|
29
|
+
project_name,
|
|
30
|
+
effective_from_date,
|
|
31
|
+
observability_api_url,
|
|
32
|
+
observability_api_key
|
|
33
|
+
FROM {schema}.projects
|
|
34
|
+
WHERE project_code = {db.make_value_db_friendly(project_code)};
|
|
35
|
+
"""
|
|
36
|
+
results = db.retrieve_data(str_sql)
|
|
37
|
+
if results.size <= 0:
|
|
38
|
+
return None
|
|
39
|
+
return results.iloc[0]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def run_test_type_lookup_query(str_schema, str_test_type=None, boo_show_referential=True, boo_show_table=True,
|
|
43
|
+
boo_show_column=True, boo_show_custom=True):
|
|
44
|
+
if str_test_type:
|
|
45
|
+
str_criteria = f" AND tt.test_type = '{str_test_type}'"
|
|
46
|
+
else:
|
|
47
|
+
str_criteria = ""
|
|
48
|
+
|
|
49
|
+
if (boo_show_referential and boo_show_table and boo_show_column and boo_show_custom) == False:
|
|
50
|
+
str_scopes = ""
|
|
51
|
+
str_scopes += "'referential'," if boo_show_referential else ""
|
|
52
|
+
str_scopes += "'table'," if boo_show_table else ""
|
|
53
|
+
str_scopes += "'column'," if boo_show_column else ""
|
|
54
|
+
str_scopes += "'custom'," if boo_show_custom else ""
|
|
55
|
+
if str_scopes > "":
|
|
56
|
+
str_criteria += f"AND tt.test_scope in ({str_scopes[:-1]})"
|
|
57
|
+
|
|
58
|
+
str_sql = f"""
|
|
59
|
+
SELECT tt.id, tt.test_type, tt.id as cat_test_id,
|
|
60
|
+
tt.test_name_short, tt.test_name_long, tt.test_description,
|
|
61
|
+
tt.measure_uom, COALESCE(tt.measure_uom_description, '') as measure_uom_description,
|
|
62
|
+
tt.default_parm_columns, tt.default_severity,
|
|
63
|
+
tt.run_type, tt.test_scope, tt.dq_dimension, tt.threshold_description,
|
|
64
|
+
tt.column_name_prompt, tt.column_name_help,
|
|
65
|
+
tt.default_parm_prompts, tt.default_parm_help, tt.usage_notes,
|
|
66
|
+
CASE tt.test_scope WHEN 'referential' THEN '⧉ ' WHEN 'custom' THEN '⛭ ' WHEN 'table' THEN '⊞ ' WHEN 'column' THEN '≣ ' ELSE '? ' END
|
|
67
|
+
|| tt.test_name_short || ': ' || lower(tt.test_name_long)
|
|
68
|
+
|| CASE WHEN tt.selection_criteria > '' THEN ' [auto-generated]' ELSE '' END as select_name
|
|
69
|
+
FROM {str_schema}.test_types tt
|
|
70
|
+
WHERE tt.active = 'Y' {str_criteria}
|
|
71
|
+
ORDER BY CASE tt.test_scope WHEN 'referential' THEN 1 WHEN 'custom' THEN 2 WHEN 'table' THEN 3 WHEN 'column' THEN 4 ELSE 5 END,
|
|
72
|
+
tt.test_name_short;
|
|
73
|
+
"""
|
|
74
|
+
return db.retrieve_data(str_sql)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def run_connections_lookup_query(str_schema, str_project_code):
|
|
78
|
+
str_sql = f"""
|
|
79
|
+
SELECT c.id::VARCHAR(50), c.connection_id, c.connection_name
|
|
80
|
+
FROM {str_schema}.connections c
|
|
81
|
+
WHERE c.project_code = '{str_project_code}'
|
|
82
|
+
ORDER BY connection_name
|
|
83
|
+
"""
|
|
84
|
+
return db.retrieve_data(str_sql)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def run_table_groups_lookup_query(str_schema, str_project_code, connection_id=None, table_group_id=None):
|
|
88
|
+
str_sql = f"""
|
|
89
|
+
SELECT tg.id::VARCHAR(50), tg.table_groups_name, tg.connection_id, tg.table_group_schema
|
|
90
|
+
FROM {str_schema}.table_groups tg
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
if connection_id:
|
|
94
|
+
str_sql += f"""
|
|
95
|
+
inner join {str_schema}.connections c on c.connection_id = tg.connection_id
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
str_sql += f"""
|
|
99
|
+
WHERE tg.project_code = '{str_project_code}'
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
if table_group_id:
|
|
103
|
+
str_sql += f"""
|
|
104
|
+
AND tg.id = '{table_group_id}'::UUID
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
if connection_id:
|
|
108
|
+
str_sql += f"""
|
|
109
|
+
AND c.id = '{connection_id}'::UUID
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
str_sql += """
|
|
113
|
+
ORDER BY table_groups_name
|
|
114
|
+
"""
|
|
115
|
+
return db.retrieve_data(str_sql)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def run_table_lookup_query(str_schema, str_table_groups_id):
|
|
119
|
+
str_sql = f"""
|
|
120
|
+
SELECT table_name
|
|
121
|
+
FROM {str_schema}.data_table_chars
|
|
122
|
+
WHERE table_groups_id = '{str_table_groups_id}'::UUID
|
|
123
|
+
AND drop_date IS NULL
|
|
124
|
+
ORDER BY table_name
|
|
125
|
+
"""
|
|
126
|
+
return db.retrieve_data(str_sql)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def run_column_lookup_query(str_schema, str_table_groups_id, str_table_name):
|
|
130
|
+
str_sql = f"""
|
|
131
|
+
SELECT column_name
|
|
132
|
+
FROM {str_schema}.data_column_chars
|
|
133
|
+
WHERE table_groups_id = '{str_table_groups_id}'::UUID
|
|
134
|
+
AND table_name = '{str_table_name}'
|
|
135
|
+
AND drop_date IS NULL
|
|
136
|
+
ORDER BY column_name
|
|
137
|
+
"""
|
|
138
|
+
return db.retrieve_data(str_sql)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def run_test_suite_lookup_by_tgroup_query(str_schema, str_table_groups_id, test_suite_name=None):
|
|
142
|
+
str_sql = f"""
|
|
143
|
+
SELECT id::VARCHAR(50), test_suite, test_suite_schema, severity, export_to_observability
|
|
144
|
+
FROM {str_schema}.test_suites
|
|
145
|
+
WHERE table_groups_id = '{str_table_groups_id}'
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
if test_suite_name:
|
|
149
|
+
str_sql += f"""
|
|
150
|
+
AND test_suite = '{test_suite_name}'
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
str_sql += """
|
|
154
|
+
ORDER BY test_suite
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
return db.retrieve_data(str_sql)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def run_test_suite_lookup_by_project_query(str_schema, str_project):
|
|
161
|
+
str_sql = f"""
|
|
162
|
+
SELECT s.id::VARCHAR(50), s.test_suite, s.test_suite_schema,
|
|
163
|
+
s.test_suite
|
|
164
|
+
|| CASE
|
|
165
|
+
WHEN tg.table_groups_name IS NULL THEN ''
|
|
166
|
+
ELSE '(' || tg.table_groups_name || ')'
|
|
167
|
+
END as test_suite_with_tg,
|
|
168
|
+
s.test_suite_description
|
|
169
|
+
FROM {str_schema}.test_suites s
|
|
170
|
+
LEFT JOIN {str_schema}.table_groups tg
|
|
171
|
+
ON (s.table_groups_id = tg.id)
|
|
172
|
+
WHERE s.project_code = '{str_project}'
|
|
173
|
+
ORDER BY s.test_suite
|
|
174
|
+
"""
|
|
175
|
+
return db.retrieve_data(str_sql)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def run_last_test_run(str_schema, str_project_code):
|
|
179
|
+
str_sql = f"""
|
|
180
|
+
SELECT MIN(EXTRACT(DAY FROM (CURRENT_DATE - r.test_starttime))) as days_back
|
|
181
|
+
FROM {str_schema}.test_runs r
|
|
182
|
+
WHERE r.project_code = '{str_project_code}'
|
|
183
|
+
AND r.status = 'Complete';
|
|
184
|
+
"""
|
|
185
|
+
return db.retrieve_data(str_sql)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def run_test_run_lookup_by_date(str_schema, str_project_code, str_run_date):
|
|
189
|
+
str_sql = f"""
|
|
190
|
+
SELECT r.id::VARCHAR(50),
|
|
191
|
+
r.test_starttime::VARCHAR || ' - ' || s.test_suite as test_run_desc
|
|
192
|
+
FROM {str_schema}.test_runs r
|
|
193
|
+
LEFT JOIN {str_schema}.test_suites s
|
|
194
|
+
ON (r.project_code = s.project_code
|
|
195
|
+
AND r.test_suite = s.test_suite)
|
|
196
|
+
WHERE r.project_code = '{str_project_code}'
|
|
197
|
+
AND r.test_starttime::DATE = '{str_run_date}'
|
|
198
|
+
ORDER BY r.test_starttime DESC
|
|
199
|
+
"""
|
|
200
|
+
return db.retrieve_data(str_sql)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def update_anomaly_disposition_old(selected, str_schema, str_new_status):
|
|
204
|
+
int_batch_size = 50
|
|
205
|
+
|
|
206
|
+
def finalize_query(status, ids):
|
|
207
|
+
return f"""UPDATE {str_schema}.profile_anomaly_results
|
|
208
|
+
SET disposition = NULLIF('{status}', 'No Decision')
|
|
209
|
+
WHERE id IN ({ids.rstrip(',')});"""
|
|
210
|
+
|
|
211
|
+
lst_ids = [row["id"] for row in selected if "id" in row]
|
|
212
|
+
lst_updates = []
|
|
213
|
+
i = 0
|
|
214
|
+
str_ids = ""
|
|
215
|
+
|
|
216
|
+
for my_id in lst_ids:
|
|
217
|
+
i += 1
|
|
218
|
+
str_ids += f" '{my_id}'::UUID,"
|
|
219
|
+
if i >= int_batch_size:
|
|
220
|
+
lst_updates.append(finalize_query(str_new_status, str_ids))
|
|
221
|
+
# reset for next batch
|
|
222
|
+
i = 0
|
|
223
|
+
if i > 0:
|
|
224
|
+
lst_updates.append(finalize_query(str_new_status, str_ids))
|
|
225
|
+
for upd in lst_updates:
|
|
226
|
+
db.execute_sql(upd)
|
|
227
|
+
|
|
228
|
+
return True
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def update_anomaly_disposition(selected, str_schema, str_new_status):
|
|
232
|
+
def finalize_small_update(status, ids):
|
|
233
|
+
return f"""UPDATE {str_schema}.profile_anomaly_results
|
|
234
|
+
SET disposition = NULLIF('{status}', 'No Decision')
|
|
235
|
+
WHERE id IN ({ids});"""
|
|
236
|
+
|
|
237
|
+
def finalize_big_update(status, ids):
|
|
238
|
+
return f"""WITH selects
|
|
239
|
+
as ( SELECT UNNEST(ARRAY [{ids}]) AS selected_id )
|
|
240
|
+
UPDATE {str_schema}.profile_anomaly_results
|
|
241
|
+
SET disposition = NULLIF('{status}', 'No Decision')
|
|
242
|
+
FROM {str_schema}.profile_anomaly_results r
|
|
243
|
+
INNER JOIN selects s
|
|
244
|
+
ON (r.id = s.selected_id)
|
|
245
|
+
WHERE r.id = profile_anomaly_results.id;"""
|
|
246
|
+
|
|
247
|
+
lst_ids = [row["id"] for row in selected if "id" in row]
|
|
248
|
+
lst_updates = []
|
|
249
|
+
str_ids = ""
|
|
250
|
+
|
|
251
|
+
if len(lst_ids) > 0:
|
|
252
|
+
for my_id in lst_ids:
|
|
253
|
+
str_ids += f" '{my_id}'::UUID,"
|
|
254
|
+
str_ids = str_ids.rstrip(",")
|
|
255
|
+
if len(lst_ids) > 4:
|
|
256
|
+
lst_updates.append(finalize_big_update(str_new_status, str_ids))
|
|
257
|
+
else:
|
|
258
|
+
lst_updates.append(finalize_small_update(str_new_status, str_ids))
|
|
259
|
+
|
|
260
|
+
for q in lst_updates:
|
|
261
|
+
db.execute_sql_raw(q)
|
|
262
|
+
|
|
263
|
+
return True
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def update_result_disposition(selected, str_schema, str_new_status):
|
|
267
|
+
active_yn = "N" if str_new_status == "Inactive" else "Y"
|
|
268
|
+
|
|
269
|
+
def finalize_small_update(status, ids):
|
|
270
|
+
return f"""UPDATE {str_schema}.test_results
|
|
271
|
+
SET disposition = NULLIF('{status}', 'No Decision')
|
|
272
|
+
WHERE id IN ({ids});"""
|
|
273
|
+
|
|
274
|
+
def finalize_big_update(status, ids):
|
|
275
|
+
return f"""WITH selects
|
|
276
|
+
as ( SELECT UNNEST(ARRAY [{ids}]) AS selected_id )
|
|
277
|
+
UPDATE {str_schema}.test_results
|
|
278
|
+
SET disposition = NULLIF('{status}', 'No Decision')
|
|
279
|
+
FROM {str_schema}.test_results r
|
|
280
|
+
INNER JOIN selects s
|
|
281
|
+
ON (r.id = s.selected_id)
|
|
282
|
+
WHERE r.id = test_results.id;"""
|
|
283
|
+
|
|
284
|
+
def finalize_test_update(ids):
|
|
285
|
+
str_lock_test = ", lock_refresh = 'N'" if active_yn == "Y" else ", lock_refresh = 'Y'"
|
|
286
|
+
return f"""WITH selects
|
|
287
|
+
as ( SELECT UNNEST(ARRAY [{ids}]) AS selected_id )
|
|
288
|
+
UPDATE {str_schema}.test_definitions
|
|
289
|
+
SET test_active = '{active_yn}',
|
|
290
|
+
last_manual_update = CURRENT_TIMESTAMP AT TIME ZONE 'UTC' {str_lock_test}
|
|
291
|
+
FROM {str_schema}.test_definitions d
|
|
292
|
+
INNER JOIN {str_schema}.test_results r
|
|
293
|
+
ON (d.id = r.test_definition_id)
|
|
294
|
+
INNER JOIN selects s
|
|
295
|
+
ON (r.id = s.selected_id)
|
|
296
|
+
WHERE d.id = test_definitions.id"""
|
|
297
|
+
|
|
298
|
+
lst_ids = [row["test_result_id"] for row in selected if "test_result_id" in row]
|
|
299
|
+
lst_updates = []
|
|
300
|
+
str_ids = ""
|
|
301
|
+
|
|
302
|
+
for my_id in lst_ids:
|
|
303
|
+
str_ids += f" '{my_id}'::UUID,"
|
|
304
|
+
str_ids = str_ids.rstrip(",")
|
|
305
|
+
|
|
306
|
+
if len(lst_ids) > 0:
|
|
307
|
+
if len(lst_ids) > 4:
|
|
308
|
+
lst_updates.append(finalize_big_update(str_new_status, str_ids))
|
|
309
|
+
else:
|
|
310
|
+
lst_updates.append(finalize_small_update(str_new_status, str_ids))
|
|
311
|
+
lst_updates.append(finalize_test_update(str_ids))
|
|
312
|
+
|
|
313
|
+
for q in lst_updates:
|
|
314
|
+
db.execute_sql_raw(q)
|
|
315
|
+
|
|
316
|
+
return True
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
def empty_if_null(item):
|
|
2
|
+
if item is None:
|
|
3
|
+
return ""
|
|
4
|
+
else:
|
|
5
|
+
return item
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def snake_case_to_title_case(snake_case):
|
|
9
|
+
words = snake_case.split("_")
|
|
10
|
+
title_case_words = [word.capitalize() for word in words]
|
|
11
|
+
title_case = " ".join(title_case_words)
|
|
12
|
+
return title_case
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import streamlit as st
|
|
2
|
+
|
|
3
|
+
import testgen.ui.queries.table_group_queries as table_group_queries
|
|
4
|
+
import testgen.ui.services.connection_service as connection_service
|
|
5
|
+
import testgen.ui.services.test_suite_service as test_suite_service
|
|
6
|
+
from testgen.common.database.database_service import RetrieveDBResultsToDictList
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_by_id(table_group_id: str):
|
|
10
|
+
schema = st.session_state["dbschema"]
|
|
11
|
+
return table_group_queries.get_by_id(schema, table_group_id)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_by_connection(project_code, connection_id):
|
|
15
|
+
schema = st.session_state["dbschema"]
|
|
16
|
+
return table_group_queries.get_by_connection(schema, project_code, connection_id)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def edit(table_group):
|
|
20
|
+
schema = st.session_state["dbschema"]
|
|
21
|
+
table_group_queries.edit(schema, table_group)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def add(table_group):
|
|
25
|
+
schema = st.session_state["dbschema"]
|
|
26
|
+
table_group_queries.add(schema, table_group)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def cascade_delete(table_group_names, dry_run=False):
|
|
30
|
+
schema = st.session_state["dbschema"]
|
|
31
|
+
test_suite_names = get_test_suite_names_by_table_group_names(table_group_names)
|
|
32
|
+
can_be_deleted = not table_group_has_dependencies(schema, table_group_names, test_suite_names)
|
|
33
|
+
if not dry_run:
|
|
34
|
+
test_suite_service.cascade_delete(test_suite_names)
|
|
35
|
+
table_group_queries.cascade_delete(schema, table_group_names)
|
|
36
|
+
return can_be_deleted
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def table_group_has_dependencies(schema, table_group_names, test_suite_names):
|
|
40
|
+
test_suite_usage_result = test_suite_service.has_test_suite_dependencies(schema, test_suite_names)
|
|
41
|
+
if not table_group_names:
|
|
42
|
+
table_group_usage_result = False
|
|
43
|
+
else:
|
|
44
|
+
table_group_usage_result = not table_group_queries.get_table_group_dependencies(schema, table_group_names).empty
|
|
45
|
+
return test_suite_usage_result or table_group_usage_result
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def are_table_groups_in_use(table_group_names):
|
|
49
|
+
if not table_group_names:
|
|
50
|
+
return False
|
|
51
|
+
|
|
52
|
+
schema = st.session_state["dbschema"]
|
|
53
|
+
|
|
54
|
+
test_suite_names = get_test_suite_names_by_table_group_names(table_group_names)
|
|
55
|
+
test_suites_in_use = test_suite_service.are_test_suites_in_use(test_suite_names)
|
|
56
|
+
|
|
57
|
+
table_groups_in_use_result = table_group_queries.get_table_group_usage(schema, table_group_names)
|
|
58
|
+
table_groups_in_use = not table_groups_in_use_result.empty
|
|
59
|
+
|
|
60
|
+
return test_suites_in_use or table_groups_in_use
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_test_suite_names_by_table_group_names(table_group_names):
|
|
64
|
+
if not table_group_names:
|
|
65
|
+
return []
|
|
66
|
+
schema = st.session_state["dbschema"]
|
|
67
|
+
test_suite_names = table_group_queries.get_test_suite_names_by_table_group_names(schema, table_group_names)
|
|
68
|
+
return test_suite_names.to_dict()["test_suite"].values()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def test_table_group(table_group, connection_id, project_code):
|
|
72
|
+
# get connection data
|
|
73
|
+
connection = connection_service.get_by_id(connection_id, hide_passwords=False)
|
|
74
|
+
connection_id = str(connection["connection_id"])
|
|
75
|
+
|
|
76
|
+
# get table group data
|
|
77
|
+
table_group_schema = table_group["table_group_schema"]
|
|
78
|
+
table_group_id = table_group["id"]
|
|
79
|
+
project_qc_schema = connection["project_qc_schema"]
|
|
80
|
+
profiling_table_set = table_group["profiling_table_set"]
|
|
81
|
+
profiling_include_mask = table_group["profiling_include_mask"]
|
|
82
|
+
profiling_exclude_mask = table_group["profiling_exclude_mask"]
|
|
83
|
+
profile_id_column_mask = table_group["profile_id_column_mask"]
|
|
84
|
+
profile_sk_column_mask = table_group["profile_sk_column_mask"]
|
|
85
|
+
profile_use_sampling = "Y" if table_group["profile_use_sampling"] else "N"
|
|
86
|
+
profile_sample_percent = table_group["profile_sample_percent"]
|
|
87
|
+
profile_sample_min_count = table_group["profile_sample_min_count"]
|
|
88
|
+
|
|
89
|
+
clsProfiling = connection_service.init_profiling_sql(project_code, connection, table_group_schema)
|
|
90
|
+
|
|
91
|
+
# Set General Parms
|
|
92
|
+
clsProfiling.table_groups_id = table_group_id
|
|
93
|
+
clsProfiling.connection_id = connection_id
|
|
94
|
+
clsProfiling.parm_do_sample = "N"
|
|
95
|
+
clsProfiling.parm_sample_size = 0
|
|
96
|
+
clsProfiling.parm_vldb_flag = "N"
|
|
97
|
+
clsProfiling.parm_do_freqs = "Y"
|
|
98
|
+
clsProfiling.parm_max_freq_length = 25
|
|
99
|
+
clsProfiling.parm_do_patterns = "Y"
|
|
100
|
+
clsProfiling.parm_max_pattern_length = 25
|
|
101
|
+
clsProfiling.profile_run_id = ""
|
|
102
|
+
clsProfiling.data_qc_schema = project_qc_schema
|
|
103
|
+
clsProfiling.data_schema = table_group_schema
|
|
104
|
+
clsProfiling.parm_table_set = get_profiling_table_set_with_quotes(profiling_table_set)
|
|
105
|
+
clsProfiling.parm_table_include_mask = profiling_include_mask
|
|
106
|
+
clsProfiling.parm_table_exclude_mask = profiling_exclude_mask
|
|
107
|
+
clsProfiling.profile_id_column_mask = profile_id_column_mask
|
|
108
|
+
clsProfiling.profile_sk_column_mask = profile_sk_column_mask
|
|
109
|
+
clsProfiling.profile_use_sampling = profile_use_sampling
|
|
110
|
+
clsProfiling.profile_sample_percent = profile_sample_percent
|
|
111
|
+
clsProfiling.profile_sample_min_count = profile_sample_min_count
|
|
112
|
+
|
|
113
|
+
query = clsProfiling.GetDDFQuery()
|
|
114
|
+
table_group_results = RetrieveDBResultsToDictList("PROJECT", query)
|
|
115
|
+
|
|
116
|
+
qc_results = connection_service.test_qc_connection(project_code, connection, init_profiling=False)
|
|
117
|
+
|
|
118
|
+
return table_group_results, qc_results
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def get_profiling_table_set_with_quotes(profiling_table_set):
|
|
122
|
+
if not profiling_table_set:
|
|
123
|
+
return profiling_table_set
|
|
124
|
+
|
|
125
|
+
aux_list = []
|
|
126
|
+
split = profiling_table_set.split(",")
|
|
127
|
+
for item in split:
|
|
128
|
+
aux_list.append(f"'{item}'")
|
|
129
|
+
profiling_table_set = ",".join(aux_list)
|
|
130
|
+
return profiling_table_set
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import streamlit as st
|
|
2
|
+
|
|
3
|
+
import testgen.ui.queries.test_definition_queries as test_definition_queries
|
|
4
|
+
import testgen.ui.services.connection_service as connection_service
|
|
5
|
+
import testgen.ui.services.database_service as database_service
|
|
6
|
+
import testgen.ui.services.table_group_service as table_group_service
|
|
7
|
+
import testgen.ui.services.test_run_service as test_run_service
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def update_attribute(test_definition_ids, attribute, value):
|
|
11
|
+
schema = st.session_state["dbschema"]
|
|
12
|
+
raw_value = "Y" if value else "N"
|
|
13
|
+
test_definition_queries.update_attribute(schema, test_definition_ids, attribute, raw_value)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_test_definitions(
|
|
17
|
+
project_code=None, test_suite=None, table_name=None, column_name=None, test_definition_ids=None
|
|
18
|
+
):
|
|
19
|
+
schema = st.session_state["dbschema"]
|
|
20
|
+
return test_definition_queries.get_test_definitions(
|
|
21
|
+
schema, project_code, test_suite, table_name, column_name, test_definition_ids
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def delete(test_definition_ids, dry_run=False):
|
|
26
|
+
schema = st.session_state["dbschema"]
|
|
27
|
+
usage_result = test_definition_queries.get_test_definition_usage(schema, test_definition_ids)
|
|
28
|
+
can_be_deleted = usage_result.empty
|
|
29
|
+
if not dry_run and can_be_deleted:
|
|
30
|
+
test_definition_queries.delete(schema, test_definition_ids)
|
|
31
|
+
return can_be_deleted
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def cascade_delete(test_suite_names):
|
|
35
|
+
schema = st.session_state["dbschema"]
|
|
36
|
+
test_run_service.cascade_delete(test_suite_names)
|
|
37
|
+
test_definition_queries.cascade_delete(schema, test_suite_names)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def add(test_definition):
|
|
41
|
+
schema = st.session_state["dbschema"]
|
|
42
|
+
prepare_to_persist(test_definition)
|
|
43
|
+
test_definition_queries.add(schema, test_definition)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def update(test_definition):
|
|
47
|
+
schema = st.session_state["dbschema"]
|
|
48
|
+
prepare_to_persist(test_definition)
|
|
49
|
+
return test_definition_queries.update(schema, test_definition)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def prepare_to_persist(test_definition):
|
|
53
|
+
# severity
|
|
54
|
+
if test_definition["severity"] and test_definition["severity"].startswith("Inherited"):
|
|
55
|
+
test_definition["severity"] = None
|
|
56
|
+
|
|
57
|
+
test_definition["export_to_observability"] = prepare_boolean_for_update(
|
|
58
|
+
test_definition["export_to_observability_raw"]
|
|
59
|
+
)
|
|
60
|
+
test_definition["lock_refresh"] = prepare_boolean_for_update(test_definition["lock_refresh"])
|
|
61
|
+
test_definition["test_active"] = prepare_boolean_for_update(test_definition["test_active"])
|
|
62
|
+
|
|
63
|
+
if test_definition["custom_query"] is not None:
|
|
64
|
+
test_definition["custom_query"] = test_definition["custom_query"].strip()
|
|
65
|
+
if test_definition["custom_query"].endswith(";"):
|
|
66
|
+
test_definition["custom_query"] = test_definition["custom_query"][:-1]
|
|
67
|
+
|
|
68
|
+
empty_if_null(test_definition)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def empty_if_null(test_definition):
|
|
72
|
+
for k, v in test_definition.items():
|
|
73
|
+
if v is None:
|
|
74
|
+
test_definition[k] = ""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def prepare_boolean_for_update(value):
|
|
78
|
+
if "Yes" == value or "Y" == value or value is True:
|
|
79
|
+
return "Y"
|
|
80
|
+
elif "No" == value or "N" == value or value is False:
|
|
81
|
+
return "N"
|
|
82
|
+
else:
|
|
83
|
+
return None
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def validate_test(test_definition):
|
|
87
|
+
schema = test_definition["schema_name"]
|
|
88
|
+
table_name = test_definition["table_name"]
|
|
89
|
+
|
|
90
|
+
if test_definition["test_type"] == "Condition_Flag":
|
|
91
|
+
condition = test_definition["custom_query"]
|
|
92
|
+
sql_query = f"""SELECT COALESCE(CAST(SUM(CASE WHEN {condition} THEN 1 ELSE 0 END) AS VARCHAR(1000) ) || '|' ,'<NULL>|') FROM {schema}.{table_name}"""
|
|
93
|
+
else:
|
|
94
|
+
sql_query = test_definition["custom_query"]
|
|
95
|
+
sql_query = sql_query.replace("{DATA_SCHEMA}", schema)
|
|
96
|
+
|
|
97
|
+
table_group_id = test_definition["table_groups_id"]
|
|
98
|
+
table_group_df = table_group_service.get_by_id(table_group_id)
|
|
99
|
+
|
|
100
|
+
connection_id = table_group_df.iloc[0]["connection_id"]
|
|
101
|
+
|
|
102
|
+
connection = connection_service.get_by_id(connection_id, hide_passwords=False)
|
|
103
|
+
|
|
104
|
+
database_service.retrieve_target_db_data(
|
|
105
|
+
connection["sql_flavor"],
|
|
106
|
+
connection["project_host"],
|
|
107
|
+
connection["project_port"],
|
|
108
|
+
connection["project_db"],
|
|
109
|
+
connection["project_user"],
|
|
110
|
+
connection["password"],
|
|
111
|
+
connection["url"],
|
|
112
|
+
connection["connect_by_url"],
|
|
113
|
+
connection["connect_by_key"],
|
|
114
|
+
connection["private_key"],
|
|
115
|
+
connection["private_key_passphrase"],
|
|
116
|
+
sql_query,
|
|
117
|
+
)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import streamlit as st
|
|
2
|
+
|
|
3
|
+
import testgen.ui.queries.test_run_queries as test_run_queries
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def cascade_delete(test_suite_names):
|
|
7
|
+
schema = st.session_state["dbschema"]
|
|
8
|
+
test_run_queries.cascade_delete(schema, test_suite_names)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def update_status(test_run_id, status):
|
|
12
|
+
schema = st.session_state["dbschema"]
|
|
13
|
+
test_run_queries.update_status(schema, test_run_id, status)
|