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,545 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import typing
|
|
3
|
+
|
|
4
|
+
import streamlit as st
|
|
5
|
+
|
|
6
|
+
import testgen.ui.services.authentication_service as authentication_service
|
|
7
|
+
import testgen.ui.services.form_service as fm
|
|
8
|
+
import testgen.ui.services.test_suite_service as test_suite_service
|
|
9
|
+
import testgen.ui.services.toolbar_service as tb
|
|
10
|
+
from testgen.commands.run_execute_tests import run_execution_steps_in_background
|
|
11
|
+
from testgen.commands.run_generate_tests import run_test_gen_queries
|
|
12
|
+
from testgen.commands.run_observability_exporter import export_test_results
|
|
13
|
+
from testgen.ui.components import widgets as testgen
|
|
14
|
+
from testgen.ui.navigation.page import Page
|
|
15
|
+
from testgen.ui.services import connection_service, table_group_service
|
|
16
|
+
from testgen.ui.services.string_service import empty_if_null
|
|
17
|
+
from testgen.ui.session import session
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TestSuitesPage(Page):
|
|
21
|
+
path = "connections/table-groups/test-suites"
|
|
22
|
+
can_activate: typing.ClassVar = [
|
|
23
|
+
lambda: authentication_service.current_user_has_admin_role() or "overview",
|
|
24
|
+
lambda: session.authentication_status or "login",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
def render(self, connection_id: str | None = None, table_group_id: str | None = None) -> None:
|
|
28
|
+
fm.render_page_header(
|
|
29
|
+
"Test Suites",
|
|
30
|
+
"https://docs.datakitchen.io/article/dataops-testgen-help/create-a-test-suite",
|
|
31
|
+
lst_breadcrumbs=[
|
|
32
|
+
{"label": "Overview", "path": "overview"},
|
|
33
|
+
{"label": "Connections", "path": "connections"},
|
|
34
|
+
{"label": "Table Groups", "path": "connections/table-groups"},
|
|
35
|
+
{"label": "Test Suites", "path": None},
|
|
36
|
+
],
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
# Get page parameters from session
|
|
40
|
+
project_code = st.session_state["project"]
|
|
41
|
+
connection = connection_service.get_by_id(connection_id) if connection_id else st.session_state["connection"]
|
|
42
|
+
|
|
43
|
+
table_group = st.session_state.get("table_group")
|
|
44
|
+
if table_group_id:
|
|
45
|
+
table_group = table_group_service.get_by_id(table_group_id)
|
|
46
|
+
table_group = table_group.iloc[0]
|
|
47
|
+
|
|
48
|
+
connection_id = connection["connection_id"]
|
|
49
|
+
table_group_id = table_group["id"]
|
|
50
|
+
|
|
51
|
+
tool_bar = tb.ToolBar(2, 5, 0, None)
|
|
52
|
+
|
|
53
|
+
with tool_bar.long_slots[0]:
|
|
54
|
+
st.selectbox("Connection", [connection["connection_name"]], disabled=True)
|
|
55
|
+
|
|
56
|
+
with tool_bar.long_slots[1]:
|
|
57
|
+
st.selectbox("Table Group", [table_group["table_groups_name"]], disabled=True)
|
|
58
|
+
|
|
59
|
+
df = test_suite_service.get_by_table_group(project_code, table_group_id)
|
|
60
|
+
|
|
61
|
+
show_columns = [
|
|
62
|
+
"test_suite",
|
|
63
|
+
"test_suite_description",
|
|
64
|
+
"severity",
|
|
65
|
+
"export_to_observability",
|
|
66
|
+
"component_key",
|
|
67
|
+
"component_type",
|
|
68
|
+
"component_name",
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
selected = fm.render_grid_select(df, show_columns)
|
|
72
|
+
|
|
73
|
+
add_modal = testgen.Modal(title=None, key="dk-add-test_suite-modal", max_width=1100)
|
|
74
|
+
edit_modal = testgen.Modal(title=None, key="dk-edit-test_suite-modal", max_width=1100)
|
|
75
|
+
delete_modal = testgen.Modal(title=None, key="dk-delete-test_suite-modal", max_width=1100)
|
|
76
|
+
run_tests_command_modal = testgen.Modal(title=None, key="dk-run-tests-command-modal", max_width=1100)
|
|
77
|
+
|
|
78
|
+
show_test_run_command_modal = testgen.Modal(
|
|
79
|
+
title=None, key="dk-show-test-run-command-modal", max_width=1100
|
|
80
|
+
)
|
|
81
|
+
run_test_generation_modal = testgen.Modal(title=None, key="dk-run-test-generation-modal", max_width=1100)
|
|
82
|
+
show_run_test_generation_modal = testgen.Modal(
|
|
83
|
+
title=None, key="dk-show-test-generation-modal", max_width=1100
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
run_export_command_modal = testgen.Modal(title=None, key="dk-run-export-modal", max_width=1100)
|
|
87
|
+
show_export_command_modal = testgen.Modal(
|
|
88
|
+
title=None, key="dk-show-export-modal", max_width=1100
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
if tool_bar.short_slots[1].button("➕ Add", help="Add a new Test Run", use_container_width=True): # NOQA RUF001
|
|
92
|
+
add_modal.open()
|
|
93
|
+
|
|
94
|
+
disable_buttons = selected is None
|
|
95
|
+
if tool_bar.short_slots[2].button(
|
|
96
|
+
"🖊️ Edit", help="Edit the selected Test Run", disabled=disable_buttons, use_container_width=True
|
|
97
|
+
):
|
|
98
|
+
edit_modal.open()
|
|
99
|
+
if tool_bar.short_slots[3].button(
|
|
100
|
+
"❌ Delete", help="Delete the selected Test Run", disabled=disable_buttons, use_container_width=True
|
|
101
|
+
):
|
|
102
|
+
delete_modal.open()
|
|
103
|
+
|
|
104
|
+
if tool_bar.short_slots[4].button(
|
|
105
|
+
f":{'gray' if disable_buttons else 'green'}[Tests →]",
|
|
106
|
+
help="View and edit Test Definitions for selected Test Suite",
|
|
107
|
+
disabled=disable_buttons,
|
|
108
|
+
use_container_width=True,
|
|
109
|
+
):
|
|
110
|
+
st.session_state["test_suite"] = selected[0]
|
|
111
|
+
|
|
112
|
+
session.current_page = "connections/table-groups/test-suites/test-definitions"
|
|
113
|
+
session.current_page_args = {
|
|
114
|
+
"connection_id": connection,
|
|
115
|
+
"table_group_id": table_group_id,
|
|
116
|
+
"test_suite_id": selected[0]["id"],
|
|
117
|
+
}
|
|
118
|
+
st.experimental_rerun()
|
|
119
|
+
|
|
120
|
+
if add_modal.is_open():
|
|
121
|
+
show_add_or_edit_modal(add_modal, "add", project_code, connection, table_group)
|
|
122
|
+
|
|
123
|
+
if edit_modal.is_open():
|
|
124
|
+
show_add_or_edit_modal(edit_modal, "edit", project_code, connection, table_group, selected)
|
|
125
|
+
|
|
126
|
+
if delete_modal.is_open():
|
|
127
|
+
show_delete_modal(delete_modal, selected)
|
|
128
|
+
|
|
129
|
+
if run_tests_command_modal.is_open():
|
|
130
|
+
run_tests(run_tests_command_modal, project_code, selected)
|
|
131
|
+
|
|
132
|
+
if show_test_run_command_modal.is_open():
|
|
133
|
+
show_test_run_command(show_test_run_command_modal, project_code, selected)
|
|
134
|
+
|
|
135
|
+
if run_test_generation_modal.is_open():
|
|
136
|
+
show_run_test_generation(run_test_generation_modal, selected)
|
|
137
|
+
|
|
138
|
+
if show_run_test_generation_modal.is_open():
|
|
139
|
+
show_test_generation_command(show_run_test_generation_modal, selected)
|
|
140
|
+
|
|
141
|
+
if show_export_command_modal.is_open():
|
|
142
|
+
show_export_command(show_export_command_modal, selected)
|
|
143
|
+
|
|
144
|
+
if run_export_command_modal.is_open():
|
|
145
|
+
run_export_command(run_export_command_modal, selected)
|
|
146
|
+
|
|
147
|
+
if not selected:
|
|
148
|
+
st.markdown(":orange[Select a row to see Test Suite details.]")
|
|
149
|
+
else:
|
|
150
|
+
show_record_detail(
|
|
151
|
+
selected[0],
|
|
152
|
+
show_test_run_command_modal,
|
|
153
|
+
run_test_generation_modal,
|
|
154
|
+
show_run_test_generation_modal,
|
|
155
|
+
run_tests_command_modal,
|
|
156
|
+
show_export_command_modal,
|
|
157
|
+
run_export_command_modal,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def show_record_detail(
|
|
162
|
+
selected,
|
|
163
|
+
show_test_run_command_modal,
|
|
164
|
+
run_test_generation_modal,
|
|
165
|
+
show_run_test_generation_modal,
|
|
166
|
+
run_tests_command_modal,
|
|
167
|
+
show_export_command_modal,
|
|
168
|
+
run_export_command_modal,
|
|
169
|
+
):
|
|
170
|
+
left_column, right_column = st.columns([0.5, 0.5])
|
|
171
|
+
|
|
172
|
+
with left_column:
|
|
173
|
+
fm.render_html_list(
|
|
174
|
+
selected,
|
|
175
|
+
[
|
|
176
|
+
"id",
|
|
177
|
+
"project_code",
|
|
178
|
+
"test_suite",
|
|
179
|
+
"connection_id",
|
|
180
|
+
"table_groups_id",
|
|
181
|
+
"test_suite_description",
|
|
182
|
+
"severity",
|
|
183
|
+
"export_to_observability",
|
|
184
|
+
"component_key",
|
|
185
|
+
"component_name",
|
|
186
|
+
"component_type",
|
|
187
|
+
],
|
|
188
|
+
"Test Suite Information",
|
|
189
|
+
int_data_width=700,
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
with right_column:
|
|
193
|
+
# st.write("<br/><br/>", unsafe_allow_html=True)
|
|
194
|
+
_, button_column = st.columns([0.2, 0.8])
|
|
195
|
+
with button_column:
|
|
196
|
+
run_now_commands_tab, cli_commands_tab = st.tabs(["Test Suite Actions", "View CLI Commands"])
|
|
197
|
+
|
|
198
|
+
with cli_commands_tab:
|
|
199
|
+
if st.button(
|
|
200
|
+
"Test Generation Command",
|
|
201
|
+
help="Shows the run-test-generation CLI command",
|
|
202
|
+
use_container_width=True,
|
|
203
|
+
):
|
|
204
|
+
show_run_test_generation_modal.open()
|
|
205
|
+
|
|
206
|
+
if st.button(
|
|
207
|
+
"Test Execution Command",
|
|
208
|
+
help="Shows the run-tests CLI command",
|
|
209
|
+
use_container_width=True,
|
|
210
|
+
):
|
|
211
|
+
show_test_run_command_modal.open()
|
|
212
|
+
|
|
213
|
+
if st.button(
|
|
214
|
+
"Observability Export Command",
|
|
215
|
+
help="Shows the export-observability CLI command",
|
|
216
|
+
use_container_width=True,
|
|
217
|
+
):
|
|
218
|
+
show_export_command_modal.open()
|
|
219
|
+
|
|
220
|
+
with run_now_commands_tab:
|
|
221
|
+
if st.button("Run Test Generation", help="Run Test Generation", use_container_width=True):
|
|
222
|
+
run_test_generation_modal.open()
|
|
223
|
+
|
|
224
|
+
if st.button("Run Test Execution", help="Run the tests", use_container_width=True):
|
|
225
|
+
run_tests_command_modal.open()
|
|
226
|
+
|
|
227
|
+
if st.button(
|
|
228
|
+
"Run Observability Export",
|
|
229
|
+
help="Exports test results to Observability for the current Test Suite",
|
|
230
|
+
use_container_width=True,
|
|
231
|
+
):
|
|
232
|
+
run_export_command_modal.open()
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def show_run_test_generation(modal, selected):
|
|
236
|
+
selected_test_suite = selected[0]
|
|
237
|
+
|
|
238
|
+
with modal.container():
|
|
239
|
+
fm.render_modal_header("Run Test Generation", None)
|
|
240
|
+
container = st.empty()
|
|
241
|
+
with container:
|
|
242
|
+
st.markdown(":green[**Execute Test Generation for the Test Suite**]")
|
|
243
|
+
|
|
244
|
+
warning_container = st.container()
|
|
245
|
+
options_container = st.container()
|
|
246
|
+
button_container = st.empty()
|
|
247
|
+
status_container = st.empty()
|
|
248
|
+
|
|
249
|
+
test_ct, unlocked_test_ct, unlocked_edits_ct = test_suite_service.get_test_suite_refresh_warning(
|
|
250
|
+
selected_test_suite["table_groups_id"], selected_test_suite["test_suite"]
|
|
251
|
+
)
|
|
252
|
+
if test_ct:
|
|
253
|
+
warning_msg = ""
|
|
254
|
+
counts_msg = f"\n\nAuto-Generated Tests: {test_ct}, Unlocked: {unlocked_test_ct}, Edited Unlocked: {unlocked_edits_ct}"
|
|
255
|
+
if unlocked_edits_ct > 0:
|
|
256
|
+
if unlocked_edits_ct > 1:
|
|
257
|
+
|
|
258
|
+
warning_msg = "Manual changes have been made to auto-generated tests in this Test Suite that have not been locked. "
|
|
259
|
+
else:
|
|
260
|
+
warning_msg = "A manual change has been made to an auto-generated test in this Test Suite that has not been locked. "
|
|
261
|
+
elif unlocked_test_ct > 0:
|
|
262
|
+
warning_msg = "Auto-generated tests are present in this Test Suite that have not been locked. "
|
|
263
|
+
warning_msg = f"{warning_msg}Generating tests now will overwrite unlocked tests subject to auto-generation based on the latest profiling.{counts_msg}"
|
|
264
|
+
with warning_container:
|
|
265
|
+
st.warning(warning_msg)
|
|
266
|
+
if unlocked_edits_ct > 0:
|
|
267
|
+
lock_edits_button = st.button("Lock Edited Tests")
|
|
268
|
+
if lock_edits_button:
|
|
269
|
+
edits_locked = test_suite_service.lock_edited_tests(selected_test_suite["test_suite"])
|
|
270
|
+
if edits_locked:
|
|
271
|
+
st.info("Edited tests have been successfully locked.")
|
|
272
|
+
|
|
273
|
+
with options_container:
|
|
274
|
+
lst_generation_sets = test_suite_service.get_generation_set_choices()
|
|
275
|
+
if lst_generation_sets:
|
|
276
|
+
lst_generation_sets.insert(0, "(All Test Types)")
|
|
277
|
+
str_generation_set = st.selectbox("Generation Set", lst_generation_sets)
|
|
278
|
+
if str_generation_set == "(All Test Types)":
|
|
279
|
+
str_generation_set = ""
|
|
280
|
+
else:
|
|
281
|
+
str_generation_set = ""
|
|
282
|
+
|
|
283
|
+
with button_container:
|
|
284
|
+
start_process_button_message = "Start"
|
|
285
|
+
test_generation_button = st.button(start_process_button_message)
|
|
286
|
+
|
|
287
|
+
if test_generation_button:
|
|
288
|
+
button_container.empty()
|
|
289
|
+
|
|
290
|
+
table_group_id = selected_test_suite["table_groups_id"]
|
|
291
|
+
test_suite_key = selected_test_suite["test_suite"]
|
|
292
|
+
status_container.info("Executing Test Generation...")
|
|
293
|
+
|
|
294
|
+
try:
|
|
295
|
+
run_test_gen_queries(table_group_id, test_suite_key, str_generation_set)
|
|
296
|
+
except Exception as e:
|
|
297
|
+
status_container.empty()
|
|
298
|
+
status_container.error(f"Process had errors: {e!s}.")
|
|
299
|
+
|
|
300
|
+
status_container.empty()
|
|
301
|
+
status_container.success("Process has successfully finished.")
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def show_delete_modal(modal, selected=None):
|
|
305
|
+
selected_test_suite = selected[0]
|
|
306
|
+
|
|
307
|
+
with modal.container():
|
|
308
|
+
fm.render_modal_header("Delete Test Suite", None)
|
|
309
|
+
test_suite_name = selected_test_suite["test_suite"]
|
|
310
|
+
|
|
311
|
+
can_be_deleted = test_suite_service.cascade_delete([test_suite_name], dry_run=True)
|
|
312
|
+
|
|
313
|
+
fm.render_html_list(
|
|
314
|
+
selected_test_suite,
|
|
315
|
+
[
|
|
316
|
+
"id",
|
|
317
|
+
"test_suite",
|
|
318
|
+
"test_suite_description",
|
|
319
|
+
],
|
|
320
|
+
"Test Suite Information",
|
|
321
|
+
int_data_width=700,
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
if not can_be_deleted:
|
|
325
|
+
st.markdown(
|
|
326
|
+
":orange[This Test Suite has related data, which includes test definitions and may include test results. If you proceed, all related data will be permanently deleted.<br/>Are you sure you want to proceed?]",
|
|
327
|
+
unsafe_allow_html=True,
|
|
328
|
+
)
|
|
329
|
+
accept_cascade_delete = st.toggle("I accept deletion of this Test Suite and all related TestGen data.")
|
|
330
|
+
|
|
331
|
+
with st.form("Delete Test Suite", clear_on_submit=True):
|
|
332
|
+
disable_delete_button = authentication_service.current_user_has_read_role() or (
|
|
333
|
+
not can_be_deleted and not accept_cascade_delete
|
|
334
|
+
)
|
|
335
|
+
delete = st.form_submit_button("Delete", disabled=disable_delete_button)
|
|
336
|
+
|
|
337
|
+
if delete:
|
|
338
|
+
if test_suite_service.are_test_suites_in_use([test_suite_name]):
|
|
339
|
+
st.error("This Test Suite is in use by a running process and cannot be deleted.")
|
|
340
|
+
else:
|
|
341
|
+
test_suite_service.cascade_delete([test_suite_name])
|
|
342
|
+
success_message = f"Test Suite {test_suite_name} has been deleted. "
|
|
343
|
+
st.success(success_message)
|
|
344
|
+
time.sleep(1)
|
|
345
|
+
modal.close()
|
|
346
|
+
st.experimental_rerun()
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
def show_add_or_edit_modal(modal, mode, project_code, connection, table_group, selected=None):
|
|
350
|
+
connection_id = connection["connection_id"]
|
|
351
|
+
table_group_id = table_group["id"]
|
|
352
|
+
with modal.container():
|
|
353
|
+
fm.render_modal_header("Edit Test Suite" if mode == "edit" else "Add Test Suite", None)
|
|
354
|
+
severity_options = ["Inherit", "Failed", "Warning"]
|
|
355
|
+
|
|
356
|
+
selected_test_suite = selected[0] if mode == "edit" else None
|
|
357
|
+
|
|
358
|
+
if mode == "edit" and not selected_test_suite["severity"]:
|
|
359
|
+
selected_test_suite["severity"] = severity_options[0]
|
|
360
|
+
|
|
361
|
+
# establish default values
|
|
362
|
+
test_suite_id = selected_test_suite["id"] if mode == "edit" else None
|
|
363
|
+
test_suite = empty_if_null(selected_test_suite["test_suite"]) if mode == "edit" else ""
|
|
364
|
+
connection_id = selected_test_suite["connection_id"] if mode == "edit" else connection_id
|
|
365
|
+
table_groups_id = selected_test_suite["table_groups_id"] if mode == "edit" else table_group_id
|
|
366
|
+
test_suite_description = empty_if_null(selected_test_suite["test_suite_description"]) if mode == "edit" else ""
|
|
367
|
+
test_action = empty_if_null(selected_test_suite["test_action"]) if mode == "edit" else ""
|
|
368
|
+
severity_index = severity_options.index(selected_test_suite["severity"]) if mode == "edit" else 0
|
|
369
|
+
export_to_observability = selected_test_suite["export_to_observability"] == "Y" if mode == "edit" else False
|
|
370
|
+
test_suite_schema = empty_if_null(selected_test_suite["test_suite_schema"]) if mode == "edit" else ""
|
|
371
|
+
component_key = empty_if_null(selected_test_suite["component_key"]) if mode == "edit" else ""
|
|
372
|
+
component_type = empty_if_null(selected_test_suite["component_type"]) if mode == "edit" else "dataset"
|
|
373
|
+
component_name = empty_if_null(selected_test_suite["component_name"]) if mode == "edit" else ""
|
|
374
|
+
|
|
375
|
+
left_column, right_column = st.columns([0.50, 0.50])
|
|
376
|
+
expander = st.expander("", expanded=True)
|
|
377
|
+
with expander:
|
|
378
|
+
expander_left_column, expander_right_column = st.columns([0.50, 0.50])
|
|
379
|
+
|
|
380
|
+
with st.form("Test Suite Add / Edit", clear_on_submit=True):
|
|
381
|
+
entity = {
|
|
382
|
+
"id": test_suite_id,
|
|
383
|
+
"project_code": project_code,
|
|
384
|
+
"test_suite": left_column.text_input(
|
|
385
|
+
label="Test Suite Name", max_chars=40, value=test_suite, disabled=(mode != "add")
|
|
386
|
+
),
|
|
387
|
+
"connection_id": connection_id,
|
|
388
|
+
"table_groups_id": table_groups_id,
|
|
389
|
+
"test_suite_description": left_column.text_input(
|
|
390
|
+
label="Test Suite Description", max_chars=40, value=test_suite_description
|
|
391
|
+
),
|
|
392
|
+
"test_action": test_action,
|
|
393
|
+
"severity": right_column.selectbox(
|
|
394
|
+
label="Severity",
|
|
395
|
+
options=severity_options,
|
|
396
|
+
index=severity_index,
|
|
397
|
+
help="Overrides the default severity in 'Test Definition' and/or 'Test Run'.",
|
|
398
|
+
),
|
|
399
|
+
"test_suite_schema": test_suite_schema,
|
|
400
|
+
"export_to_observability": left_column.toggle(
|
|
401
|
+
"Export to Observability",
|
|
402
|
+
value=export_to_observability,
|
|
403
|
+
help="Fields below are only required when overriding the Table Group defaults.",
|
|
404
|
+
),
|
|
405
|
+
"component_key": expander_left_column.text_input(
|
|
406
|
+
label="Component Key",
|
|
407
|
+
max_chars=40,
|
|
408
|
+
value=component_key,
|
|
409
|
+
placeholder="Optional Field",
|
|
410
|
+
help="Overrides the default component key mapping, which is set at Table Group level.",
|
|
411
|
+
),
|
|
412
|
+
"component_type": expander_right_column.text_input(
|
|
413
|
+
label="Component Type", max_chars=40, value=component_type, disabled=True
|
|
414
|
+
),
|
|
415
|
+
"component_name": expander_left_column.text_input(
|
|
416
|
+
label="Component Name",
|
|
417
|
+
max_chars=40,
|
|
418
|
+
value=component_name,
|
|
419
|
+
placeholder="Optional Field",
|
|
420
|
+
help="Overrides the default component name mapping, which is set at the Table Group level.",
|
|
421
|
+
),
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
submit_button_text = "Save" if mode == "edit" else "Add"
|
|
425
|
+
submit = st.form_submit_button(
|
|
426
|
+
submit_button_text, disabled=authentication_service.current_user_has_read_role()
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
if submit:
|
|
430
|
+
if " " in entity["test_suite"]:
|
|
431
|
+
proposed_test_suite = entity["test_suite"].replace(" ", "-")
|
|
432
|
+
st.error(
|
|
433
|
+
f"Blank spaces not allowed in field 'Test Suite Name'. Use dash or underscore instead. i.e.: {proposed_test_suite}"
|
|
434
|
+
)
|
|
435
|
+
else:
|
|
436
|
+
if mode == "edit":
|
|
437
|
+
test_suite_service.edit(entity)
|
|
438
|
+
else:
|
|
439
|
+
test_suite_service.add(entity)
|
|
440
|
+
success_message = (
|
|
441
|
+
"Changes have been saved successfully. "
|
|
442
|
+
if mode == "edit"
|
|
443
|
+
else "New TestSuite added successfully. "
|
|
444
|
+
)
|
|
445
|
+
st.success(success_message)
|
|
446
|
+
time.sleep(1)
|
|
447
|
+
modal.close()
|
|
448
|
+
st.experimental_rerun()
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
def run_tests(modal, project_code, selected):
|
|
452
|
+
selected_test_suite = selected[0]
|
|
453
|
+
|
|
454
|
+
with modal.container():
|
|
455
|
+
fm.render_modal_header("Run Test Execution", None)
|
|
456
|
+
container = st.empty()
|
|
457
|
+
with container:
|
|
458
|
+
st.markdown(":green[**Run Tests for the Test Suite**]")
|
|
459
|
+
|
|
460
|
+
button_container = st.empty()
|
|
461
|
+
status_container = st.empty()
|
|
462
|
+
|
|
463
|
+
with button_container:
|
|
464
|
+
start_process_button_message = "Start"
|
|
465
|
+
run_test_button = st.button(start_process_button_message)
|
|
466
|
+
|
|
467
|
+
if run_test_button:
|
|
468
|
+
button_container.empty()
|
|
469
|
+
|
|
470
|
+
test_suite_key = selected_test_suite["test_suite"]
|
|
471
|
+
status_container.info(f"Running tests for test suite {test_suite_key}")
|
|
472
|
+
|
|
473
|
+
try:
|
|
474
|
+
run_execution_steps_in_background(project_code, test_suite_key)
|
|
475
|
+
except Exception as e:
|
|
476
|
+
status_container.empty()
|
|
477
|
+
status_container.error(f"Process started with errors: {e!s}.")
|
|
478
|
+
|
|
479
|
+
status_container.empty()
|
|
480
|
+
status_container.success(
|
|
481
|
+
"Process has successfully started. Check details in menu item 'Data Quality Testing'."
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
def show_test_run_command(modal, project_code, selected):
|
|
486
|
+
with modal.container():
|
|
487
|
+
fm.render_modal_header("Test Execution Command for CLI", None)
|
|
488
|
+
selected_test_suite = selected[0]
|
|
489
|
+
test_suite_name = selected_test_suite["test_suite"]
|
|
490
|
+
command = f"testgen run-tests --project-key {project_code} --test-suite-key {test_suite_name}"
|
|
491
|
+
st.code(command, language="shellSession")
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def show_test_generation_command(modal, selected):
|
|
495
|
+
with modal.container():
|
|
496
|
+
fm.render_modal_header("Test Generation Command for CLI", None)
|
|
497
|
+
selected_test_suite = selected[0]
|
|
498
|
+
test_suite_key = selected_test_suite["test_suite"]
|
|
499
|
+
table_group_id = selected_test_suite["table_groups_id"]
|
|
500
|
+
command = f"testgen run-test-generation --table-group-id {table_group_id} --test-suite-key {test_suite_key}"
|
|
501
|
+
st.code(command, language="shellSession")
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def show_export_command(modal, selected):
|
|
505
|
+
with modal.container():
|
|
506
|
+
fm.render_modal_header("Observability Export Command for CLI", None)
|
|
507
|
+
selected_test_suite = selected[0]
|
|
508
|
+
test_suite_key = selected_test_suite["test_suite"]
|
|
509
|
+
project_key = selected_test_suite["project_code"]
|
|
510
|
+
command = f"testgen export-observability --project-key {project_key} --test-suite-key {test_suite_key}"
|
|
511
|
+
st.code(command, language="shellSession")
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
def run_export_command(modal, selected):
|
|
515
|
+
selected_test_suite = selected[0]
|
|
516
|
+
|
|
517
|
+
with modal.container():
|
|
518
|
+
fm.render_modal_header("Run Observability Export", None)
|
|
519
|
+
container = st.empty()
|
|
520
|
+
with container:
|
|
521
|
+
st.markdown(":green[**Execute the test export for the current Test Suite**]")
|
|
522
|
+
|
|
523
|
+
button_container = st.empty()
|
|
524
|
+
status_container = st.empty()
|
|
525
|
+
|
|
526
|
+
with button_container:
|
|
527
|
+
start_process_button_message = "Start"
|
|
528
|
+
test_generation_button = st.button(start_process_button_message)
|
|
529
|
+
|
|
530
|
+
if test_generation_button:
|
|
531
|
+
button_container.empty()
|
|
532
|
+
|
|
533
|
+
test_suite_key = selected_test_suite["test_suite"]
|
|
534
|
+
project_key = selected_test_suite["project_code"]
|
|
535
|
+
status_container.info("Executing Export ...")
|
|
536
|
+
|
|
537
|
+
try:
|
|
538
|
+
qty_of_exported_events = export_test_results(project_key, test_suite_key)
|
|
539
|
+
status_container.empty()
|
|
540
|
+
status_container.success(
|
|
541
|
+
f"Process has successfully finished, {qty_of_exported_events} events have been exported."
|
|
542
|
+
)
|
|
543
|
+
except Exception as e:
|
|
544
|
+
status_container.empty()
|
|
545
|
+
status_container.error(f"Process has finished with errors: {e!s}.")
|
|
File without changes
|
testgen/utils/plugins.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
import importlib.metadata
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
PLUGIN_PREFIX = "testgen_"
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def discover() -> typing.Generator["Plugin", None, None]:
|
|
9
|
+
for package_path, distribution_names in importlib.metadata.packages_distributions().items():
|
|
10
|
+
if package_path.startswith(PLUGIN_PREFIX):
|
|
11
|
+
yield Plugin(package=package_path, version=importlib.metadata.version(distribution_names[0]))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclasses.dataclass
|
|
15
|
+
class Plugin:
|
|
16
|
+
package: str
|
|
17
|
+
version: str
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SingletonType(type):
|
|
5
|
+
_instances: typing.ClassVar[dict[type, object]] = {}
|
|
6
|
+
|
|
7
|
+
def __call__(cls, *args, **kwargs) -> typing.Any:
|
|
8
|
+
if cls not in cls._instances:
|
|
9
|
+
cls._instances[cls] = super().__call__(*args, **kwargs)
|
|
10
|
+
return cls._instances[cls]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Singleton(metaclass=SingletonType):
|
|
14
|
+
pass
|