symtest-cli 1.3.0__tar.gz → 1.3.2__tar.gz
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.
- {symtest_cli-1.3.0/src/symtest_cli.egg-info → symtest_cli-1.3.2}/PKG-INFO +15 -12
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/README.md +10 -7
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/docs/design.md +54 -10
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/docs/design_en.md +52 -10
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/docs/tui_and_config_split_design.md +3 -3
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/docs/user_manual.md +137 -6
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/docs/user_manual_en.md +137 -6
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/setup.py +4 -4
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/__init__.py +1 -1
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/config/config_io.py +73 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/config/config_schema.py +38 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/core/assertions.py +1 -1
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/core/base_runner.py +90 -4
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/core/config_loader.py +73 -65
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/core/execution.py +7 -1
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/core/history_store.py +1 -1
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/core/last_run_store.py +2 -2
- symtest_cli-1.3.2/src/symtest/core/parallel_runner.py +465 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/core/process_worker.py +2 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/core/sequence_state.py +5 -3
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/core/test_case.py +48 -3
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/core/types.py +1 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/file_comparator/base_comparator.py +13 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/file_comparator/text_comparator.py +56 -32
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/runners/parallel_config_runner.py +69 -3
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/tui/app.py +1 -1
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/tui/screens/case_editor.py +38 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2/src/symtest_cli.egg-info}/PKG-INFO +15 -12
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest_cli.egg-info/SOURCES.txt +26 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/__pycache__/conftest.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/__pycache__/conftest.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/e2e/__pycache__/test_user_flows.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/e2e/__pycache__/test_user_flows.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/__pycache__/test_history_feature.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/__pycache__/test_history_feature.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/integration/__pycache__/test_new_cli_features.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/__pycache__/test_new_cli_features.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/__pycache__/test_real_command_execution.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/__pycache__/test_real_command_execution.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/__pycache__/test_sequence.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/__pycache__/test_sequence.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/integration/file_compare/__pycache__/test_text_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.2/tests/integration/file_compare/__pycache__/test_text_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/integration/file_compare/test_text_compare.py +124 -0
- symtest_cli-1.3.2/tests/integration/parallel/__pycache__/test_depends_on.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.2/tests/integration/parallel/__pycache__/test_depends_on.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/integration/parallel/test_depends_on.py +229 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/test_history_feature.py +5 -3
- symtest_cli-1.3.2/tests/unit/__pycache__/test_binary_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_binary_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/__pycache__/test_cli.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_cli.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/__pycache__/test_config_io.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_config_io.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_h5_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_h5_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_import_expander.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_import_expander.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/__pycache__/test_inheritance_expander.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_inheritance_expander.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/__pycache__/test_result.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_result.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/commands/__pycache__/test_compare_command.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/commands/__pycache__/test_compare_command.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/core/__pycache__/test_assertions.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_assertions.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/core/__pycache__/test_case_env.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/core/__pycache__/test_case_env.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/core/__pycache__/test_config_loader.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_config_loader.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/core/__pycache__/test_execution.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_execution.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/core/__pycache__/test_execution_new_features.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_execution_new_features.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_history_store.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_history_store.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/core/__pycache__/test_last_run_store.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_last_run_store.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_process_worker.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_process_worker.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/core/__pycache__/test_sequence_state.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_sequence_state.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_setup.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_setup.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/core/__pycache__/test_validation_error.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_validation_error.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/core/__pycache__/test_xfail.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_xfail.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/core/test_case_env.py +225 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/test_sequence_state.py +1 -1
- symtest_cli-1.3.2/tests/unit/file_comparator/__pycache__/test_error_analysis.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/__pycache__/test_error_analysis.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/file_comparator/__pycache__/test_hourglass_tangent_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/file_comparator/__pycache__/test_script_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/__pycache__/test_script_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/file_comparator/__pycache__/test_workspace_plugins.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/__pycache__/test_workspace_plugins.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/tui/__pycache__/conftest.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/conftest.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_app.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_app.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_case_controller.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_case_controller.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_search_functions.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_search_functions.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/tui/__pycache__/test_tui_run_test.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_tui_run_test.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_widgets_data.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_widgets_data.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.2/tests/unit/utils/__pycache__/test_report_generator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/utils/__pycache__/test_report_generator.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.0/src/symtest/core/parallel_runner.py +0 -251
- symtest_cli-1.3.0/tests/integration/file_compare/__pycache__/test_text_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.0/tests/integration/file_compare/__pycache__/test_text_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.0/tests/integration/file_compare/test_text_compare.py +0 -40
- symtest_cli-1.3.0/tests/unit/__pycache__/test_cli.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.0/tests/unit/core/__pycache__/test_assertions.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.0/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.0/tests/unit/utils/__pycache__/test_report_generator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/LICENSE +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/MANIFEST.in +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/pyproject.toml +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/setup.cfg +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/cli.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/commands/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/commands/compare.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/config/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/config/import_expander.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/config/inheritance_expander.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/core/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/core/setup.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/file_comparator/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/file_comparator/binary_comparator.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/file_comparator/csv_comparator.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/file_comparator/factory.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/file_comparator/h5_comparator.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/file_comparator/json_comparator.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/file_comparator/result.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/file_comparator/script_comparator.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/file_comparator/xml_comparator.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/logging_config.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/runners/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/runners/config_runner.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/runners/json_runner.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/runners/parallel_json_runner.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/runners/parallel_yaml_runner.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/runners/yaml_runner.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/tui/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/tui/controllers/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/tui/controllers/case_controller.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/tui/screens/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/tui/screens/case_list.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/tui/widgets/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/tui/widgets/case_table.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/tui/widgets/expected_editor.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/tui/widgets/search_bar.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/tui/widgets/steps_editor.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/utils/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/utils/junit_xml_writer.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/utils/path_resolver.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest/utils/report_generator.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest_cli.egg-info/dependency_links.txt +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest_cli.egg-info/entry_points.txt +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest_cli.egg-info/requires.txt +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/src/symtest_cli.egg-info/top_level.txt +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/README.md +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/__pycache__/__init__.cpython-313.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/__pycache__/__init__.cpython-39.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/__pycache__/conftest.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/__pycache__/run_all.cpython-312.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/__pycache__/run_all.cpython-313.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/__pycache__/run_all.cpython-39.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/__pycache__/test_setup_module.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/conftest.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/demos/h5_filter_demo.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/demos/manual_report_example.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/demos/perf_parallel.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/e2e/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/e2e/__pycache__/__init__.cpython-312.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/e2e/__pycache__/__init__.cpython-313.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/e2e/__pycache__/__init__.cpython-39.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/e2e/__pycache__/test_user_flows.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/e2e/__pycache__/test_user_flows.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/e2e/test_user_flows.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/circular_config_a.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/circular_config_b.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/hourglass_stdout_mismatch.txt +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/hourglass_stdout_sample.txt +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/inheritance_base.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/inheritance_chain.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/inheritance_circular.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/main_config.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/missing_fields.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/mock_fail_script.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/mock_pass_script.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/setup_main.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/setup_sub.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/sub_json_tests.yaml +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/sub_text_tests.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/test_cases.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/test_cases.yaml +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/test_cases1.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/test_with_setup.json +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/fixtures/test_with_setup.yaml +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/__pycache__/test_history_feature.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/__pycache__/test_new_cli_features.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/__pycache__/test_real_command_execution.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/__pycache__/test_sequence.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/test_binary_compare.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/test_csv_compare.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/test_h5_compare.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/test_json_compare.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/file_compare/test_xml_compare.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/parallel/test_parallel_runner.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/path_handling/test_spaces_in_paths.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/test_new_cli_features.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/test_real_command_execution.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/integration/test_sequence.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/run_all.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_binary_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_config_io.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_h5_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_import_expander.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_inheritance_expander.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_result.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_run_all.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_run_all.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/__pycache__/test_run_all.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/commands/__pycache__/test_compare_command.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/commands/test_compare_command.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_assertions.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_config_loader.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_execution.cpython-312.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_execution.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_execution_new_features.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_history_store.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_last_run_store.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_process_worker.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_setup.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_setup.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_validation_error.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/__pycache__/test_xfail.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/test_assertions.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/test_config_loader.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/test_config_loader_new_features.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/test_execution.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/test_execution_new_features.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/test_history_store.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/test_last_run_store.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/test_process_worker.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/test_setup.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/test_validation_error.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/core/test_xfail.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/__pycache__/__init__.cpython-312.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/__pycache__/test_error_analysis.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/__pycache__/test_hourglass_tangent_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/__pycache__/test_hourglass_tangent_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/__pycache__/test_script_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/__pycache__/test_workspace_plugins.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/test_error_analysis.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/test_hourglass_tangent_comparator.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/test_script_comparator.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/file_comparator/test_workspace_plugins.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/runners/test_json_yaml_runner.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/runners/test_test_case_filter.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/runners/test_test_case_tag_filter.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/test_binary_comparator.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/test_cli.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/test_config_io.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/test_h5_comparator.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/test_import_expander.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/test_inheritance_expander.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/test_result.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/test_run_all.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__init__.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/__init__.cpython-312.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/__init__.cpython-313.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_app.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_case_controller.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_search_functions.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_tui_run_test.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/__pycache__/test_widgets_data.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/conftest.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/test_app.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/test_case_controller.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/test_search_functions.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/test_tui_run_test.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/tui/test_widgets_data.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/utils/__pycache__/test_report_generator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/utils/test_junit_xml_writer.py +0 -0
- {symtest_cli-1.3.0 → symtest_cli-1.3.2}/tests/unit/utils/test_report_generator.py +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: symtest-cli
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.2
|
|
4
4
|
Summary: Regression testing for CLI applications, with multi-step workflows and numerical file comparison.
|
|
5
|
-
Home-page: https://github.com/ozil111/symtest
|
|
5
|
+
Home-page: https://github.com/ozil111/symtest-cli
|
|
6
6
|
Author: Xiaotong Wang
|
|
7
7
|
Author-email: xiaotongwang98@gmail.com
|
|
8
|
-
Project-URL: Documentation, https://github.com/ozil111/symtest/blob/main/docs/user_manual.md
|
|
9
|
-
Project-URL: Source, https://github.com/ozil111/symtest
|
|
10
|
-
Project-URL: Tracker, https://github.com/ozil111/symtest/issues
|
|
8
|
+
Project-URL: Documentation, https://github.com/ozil111/symtest-cli/blob/main/docs/user_manual.md
|
|
9
|
+
Project-URL: Source, https://github.com/ozil111/symtest-cli
|
|
10
|
+
Project-URL: Tracker, https://github.com/ozil111/symtest-cli/issues
|
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
|
12
12
|
Classifier: License :: OSI Approved :: MIT License
|
|
13
13
|
Classifier: Operating System :: OS Independent
|
|
@@ -53,11 +53,11 @@ Dynamic: summary
|
|
|
53
53
|
|
|
54
54
|
> **Note:** This project was formerly known as `cli-test-framework`.
|
|
55
55
|
> Since version 1.3.0 it is released as
|
|
56
|
-
> [`symtest`](https://pypi.org/project/symtest/); the old package name
|
|
57
|
-
> longer updated. Install with:
|
|
56
|
+
> [`symtest-cli`](https://pypi.org/project/symtest-cli/); the old package name
|
|
57
|
+
> is no longer updated. Install with:
|
|
58
58
|
>
|
|
59
59
|
> ```bash
|
|
60
|
-
> pip install symtest
|
|
60
|
+
> pip install symtest-cli
|
|
61
61
|
> ```
|
|
62
62
|
|
|
63
63
|
A feature-focused automated testing framework for command-line applications.
|
|
@@ -92,15 +92,15 @@ occur in real CLI and scientific-computing projects.
|
|
|
92
92
|
Python 3.9 or newer is required.
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
|
-
pip install symtest
|
|
95
|
+
pip install symtest-cli
|
|
96
96
|
```
|
|
97
97
|
|
|
98
98
|
YAML and the TUI are optional:
|
|
99
99
|
|
|
100
100
|
```bash
|
|
101
|
-
pip install "symtest[yaml]"
|
|
102
|
-
pip install "symtest[tui]"
|
|
103
|
-
pip install "symtest[all]"
|
|
101
|
+
pip install "symtest-cli[yaml]"
|
|
102
|
+
pip install "symtest-cli[tui]"
|
|
103
|
+
pip install "symtest-cli[all]"
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
The default installation includes HDF5 and numerical comparison support.
|
|
@@ -298,6 +298,9 @@ requirement for using the framework.
|
|
|
298
298
|
- [User manual](docs/user_manual_en.md)
|
|
299
299
|
- [Design document](docs/design_en.md)
|
|
300
300
|
- [Plugin examples](examples/plugins/README.md)
|
|
301
|
+
- [AI Skill template](examples/skill/) — import framework knowledge into AI coding
|
|
302
|
+
assistants so they can author test cases, acceptance criteria,
|
|
303
|
+
and TDD workflows directly
|
|
301
304
|
|
|
302
305
|
## Development
|
|
303
306
|
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
> **Note:** This project was formerly known as `cli-test-framework`.
|
|
6
6
|
> Since version 1.3.0 it is released as
|
|
7
|
-
> [`symtest`](https://pypi.org/project/symtest/); the old package name
|
|
8
|
-
> longer updated. Install with:
|
|
7
|
+
> [`symtest-cli`](https://pypi.org/project/symtest-cli/); the old package name
|
|
8
|
+
> is no longer updated. Install with:
|
|
9
9
|
>
|
|
10
10
|
> ```bash
|
|
11
|
-
> pip install symtest
|
|
11
|
+
> pip install symtest-cli
|
|
12
12
|
> ```
|
|
13
13
|
|
|
14
14
|
A feature-focused automated testing framework for command-line applications.
|
|
@@ -43,15 +43,15 @@ occur in real CLI and scientific-computing projects.
|
|
|
43
43
|
Python 3.9 or newer is required.
|
|
44
44
|
|
|
45
45
|
```bash
|
|
46
|
-
pip install symtest
|
|
46
|
+
pip install symtest-cli
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
YAML and the TUI are optional:
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
|
-
pip install "symtest[yaml]"
|
|
53
|
-
pip install "symtest[tui]"
|
|
54
|
-
pip install "symtest[all]"
|
|
52
|
+
pip install "symtest-cli[yaml]"
|
|
53
|
+
pip install "symtest-cli[tui]"
|
|
54
|
+
pip install "symtest-cli[all]"
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
The default installation includes HDF5 and numerical comparison support.
|
|
@@ -249,6 +249,9 @@ requirement for using the framework.
|
|
|
249
249
|
- [User manual](docs/user_manual_en.md)
|
|
250
250
|
- [Design document](docs/design_en.md)
|
|
251
251
|
- [Plugin examples](examples/plugins/README.md)
|
|
252
|
+
- [AI Skill template](examples/skill/) — import framework knowledge into AI coding
|
|
253
|
+
assistants so they can author test cases, acceptance criteria,
|
|
254
|
+
and TDD workflows directly
|
|
252
255
|
|
|
253
256
|
## Development
|
|
254
257
|
|
|
@@ -259,7 +259,7 @@ load_test_cases() → _apply_test_case_filter() → setup_manager.setup_all()
|
|
|
259
259
|
支持三种过滤方式(可组合):
|
|
260
260
|
- `test_case_filter`:按名称精确匹配
|
|
261
261
|
- `test_case_tag_filter`:按 tags 匹配(交集逻辑)
|
|
262
|
-
- `last_failed`:从 `.
|
|
262
|
+
- `last_failed`:从 `.symtest/last_run.json` 读取上次失败的用例名
|
|
263
263
|
|
|
264
264
|
**xfail 机制 `_apply_xfail_status()`**:
|
|
265
265
|
|
|
@@ -318,6 +318,8 @@ class TestCase:
|
|
|
318
318
|
expected_failure: bool = False
|
|
319
319
|
xfail_reason: str = ""
|
|
320
320
|
xfail_quiet: bool = False
|
|
321
|
+
depends_on: List[str] = field(default_factory=list)
|
|
322
|
+
env: Dict[str, str] = field(default_factory=dict)
|
|
321
323
|
```
|
|
322
324
|
|
|
323
325
|
两种模式:
|
|
@@ -328,6 +330,8 @@ class TestCase:
|
|
|
328
330
|
- `tags`:标签过滤
|
|
329
331
|
- `retry_count`:失败重试次数
|
|
330
332
|
- `expected_failure` / `xfail_reason` / `xfail_quiet`:预期失败标记
|
|
333
|
+
- `depends_on`:用例级依赖声明,支持 DAG 拓扑调度
|
|
334
|
+
- `env`:case 级环境变量,注入该 case(序列模式为所有 step)的子进程,优先级高于 `setup` 与调度器注入
|
|
331
335
|
|
|
332
336
|
### 4.3 Assertions
|
|
333
337
|
|
|
@@ -426,7 +430,7 @@ class PathResolver:
|
|
|
426
430
|
`--last-failed` 状态存储模块(`core/last_run_store.py`):
|
|
427
431
|
|
|
428
432
|
```python
|
|
429
|
-
# 存储位置: <workspace>/.
|
|
433
|
+
# 存储位置: <workspace>/.symtest/last_run.json
|
|
430
434
|
# {
|
|
431
435
|
# "case_name": {"status": "passed"},
|
|
432
436
|
# ...
|
|
@@ -448,8 +452,8 @@ class PathResolver:
|
|
|
448
452
|
`--resume` 断点续跑模块(`core/sequence_state.py`):
|
|
449
453
|
|
|
450
454
|
```python
|
|
451
|
-
# 状态文件: <workspace>/.
|
|
452
|
-
# 输出缓存: <workspace>/.
|
|
455
|
+
# 状态文件: <workspace>/.symtest/sequence_state/<case_name>.json
|
|
456
|
+
# 输出缓存: <workspace>/.symtest/sequence_state/cache/<case_name>.step<N>.log
|
|
453
457
|
```
|
|
454
458
|
|
|
455
459
|
核心接口:
|
|
@@ -684,7 +688,7 @@ CaseManagerApp (Textual App)
|
|
|
684
688
|
_update_history() # 回归检测 + 更新 .symtest
|
|
685
689
|
│
|
|
686
690
|
▼
|
|
687
|
-
_save_last_run() # 写入 .
|
|
691
|
+
_save_last_run() # 写入 .symtest/last_run.json
|
|
688
692
|
│
|
|
689
693
|
▼
|
|
690
694
|
setup_manager.teardown_all() # 逆序清理
|
|
@@ -699,14 +703,14 @@ CaseManagerApp (Textual App)
|
|
|
699
703
|
ParallelConfigRunner.run_tests()
|
|
700
704
|
│
|
|
701
705
|
▼
|
|
702
|
-
LPT 排序 (
|
|
706
|
+
拓扑 LPT 排序 (depends_on 约束 + 历史 avg_duration 降序)
|
|
703
707
|
│
|
|
704
708
|
▼
|
|
705
709
|
_assign_relative_cpu_cores() # 按权重比例分配 CPU 核心
|
|
706
710
|
│
|
|
707
711
|
▼
|
|
708
712
|
┌──────────────────────────────────────┐
|
|
709
|
-
│
|
|
713
|
+
│ DAG 调度 / 或直接并行 (无依赖时) │
|
|
710
714
|
│ AtomicSemaphore.acquire(cores) │
|
|
711
715
|
│ 注入 OMP/MKL/NPROC 环境变量 │
|
|
712
716
|
│ execute_single_test_case() │
|
|
@@ -715,7 +719,45 @@ ParallelConfigRunner.run_tests()
|
|
|
715
719
|
└──────────────────────────────────────┘
|
|
716
720
|
```
|
|
717
721
|
|
|
718
|
-
### 7.3
|
|
722
|
+
### 7.3 DAG 依赖调度流
|
|
723
|
+
|
|
724
|
+
当 `TestCase.depends_on` 非空时,并行 runner 自动切换为 DAG 拓扑调度:
|
|
725
|
+
|
|
726
|
+
```
|
|
727
|
+
ParallelRunner.run_tests()
|
|
728
|
+
│
|
|
729
|
+
▼
|
|
730
|
+
has_deps? ──No──► _run_tests_flat() (fast path)
|
|
731
|
+
│
|
|
732
|
+
Yes
|
|
733
|
+
▼
|
|
734
|
+
_run_dag()
|
|
735
|
+
│
|
|
736
|
+
├── 构建 dependents 邻接表 + in_degree 入度表
|
|
737
|
+
├── 入度=0 的用例 → 就绪队列 → executor.submit()
|
|
738
|
+
│
|
|
739
|
+
▼
|
|
740
|
+
┌────────────────────────────────────────┐
|
|
741
|
+
│ as_completed() 循环: │
|
|
742
|
+
│ 完成一个 future │
|
|
743
|
+
│ │ │
|
|
744
|
+
│ ├── passed/xfailed → 后继入度-1 │
|
|
745
|
+
│ │ └── 入度=0 → submit(后继) │
|
|
746
|
+
│ │ │
|
|
747
|
+
│ └── failed/xpassed → cascade_skip │
|
|
748
|
+
│ └── BFS 标记下游全部 skipped │
|
|
749
|
+
└────────────────────────────────────────┘
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
**调度语义**:
|
|
753
|
+
- 依赖"满足" = 状态为 `passed` 或 `xfailed`
|
|
754
|
+
- 依赖"不满足" = 状态为 `failed` 或 `xpassed` → 下游全部 skip
|
|
755
|
+
- `skipped` 不计入 `failed` 计数,报告中单独列出
|
|
756
|
+
- 级联 skip:若 B 被 skip,则依赖 B 的 C 也自动 skip
|
|
757
|
+
|
|
758
|
+
**顺序 runner**(`BaseRunner.run_tests()`)同样支持拓扑排序:`_topological_order()` 使用 Kahn 算法生成拓扑序列,按序执行,依赖失败时自动跳过下游。
|
|
759
|
+
|
|
760
|
+
### 7.4 文件比较流
|
|
719
761
|
|
|
720
762
|
```
|
|
721
763
|
symtest compare file1 file2 [options]
|
|
@@ -737,7 +779,7 @@ symtest compare file1 file2 [options]
|
|
|
737
779
|
format_result(result, --output-format) # text / json / html
|
|
738
780
|
```
|
|
739
781
|
|
|
740
|
-
### 7.
|
|
782
|
+
### 7.5 --resume 断点续跑流
|
|
741
783
|
|
|
742
784
|
```
|
|
743
785
|
序列测试用例执行
|
|
@@ -781,14 +823,16 @@ symtest compare file1 file2 [options]
|
|
|
781
823
|
| LPT 调度策略 | 长任务先启动,减少尾延迟;优先使用 `.symtest` 历史数据 |
|
|
782
824
|
| 累计平均更新历史 | 直觉简单,随运行次数增多单次异常自然稀释 |
|
|
783
825
|
| 回归检测在更新前执行 | 先与旧均值比较再更新,确保对比的是"历史基线" |
|
|
784
|
-
| `.symtest
|
|
826
|
+
| `.symtest/` 目录 | 不干扰用户目录视图,JSON 格式便于调试;状态文件统一管理 |
|
|
785
827
|
| 环境变量注入 | 科学计算求解器常忽略 Python 级线程控制 |
|
|
828
|
+
| case 级 env 通过 subprocess 注入 | 不改进程全局 `os.environ`,进程隔离、并行线程安全;优先级 `os.environ` < 调度器 < case env |
|
|
786
829
|
| Comparator 工厂 + 插件发现 | 按文件类型创建比较器,workspace `comparators/` 目录自动发现插件 |
|
|
787
830
|
| subprocess 隔离执行 | 每个 test case 独立子进程,保证测试间互不影响 |
|
|
788
831
|
| xfail 机制 | 支持预期失败的测试(CI 中不阻塞流水线),意外通过时告警 |
|
|
789
832
|
| --last-failed 覆写策略 | 只覆写本次执行的用例状态,避免子集运行时丢失未执行用例的状态 |
|
|
790
833
|
| --resume 纯信任模型 | 不验证 artifact,由用户保证 workspace 未被修改,简化实现 |
|
|
791
834
|
| retry_count 重试机制 | 应对偶发性网络抖动或竞态条件,首次失败后自动重试 |
|
|
835
|
+
| DAG 依赖调度 | 基于 Kahn 拓扑 + 就绪队列,依赖满足后立即提交;依赖失败级联 skip 下游;无依赖时走 fast path 零开销 |
|
|
792
836
|
| --update-baseline | 比较失败时自动将实际输出覆盖 baseline,适合批量更新基准 |
|
|
793
837
|
| next_action_hint 结构化建议 | 失败结果附带下一步操作建议(update_baseline / update_expected / increase_timeout / investigate),便于 AI 消费 |
|
|
794
838
|
| TUI 基于 Textual | 利用成熟的终端 UI 框架,提供交互式用例管理 |
|
|
@@ -259,7 +259,7 @@ load_test_cases() → _apply_test_case_filter() → setup_manager.setup_all()
|
|
|
259
259
|
Supports three filter modes (combinable):
|
|
260
260
|
- `test_case_filter`: exact name match
|
|
261
261
|
- `test_case_tag_filter`: tag-based match (intersection logic)
|
|
262
|
-
- `last_failed`: reads previously failed case names from `.
|
|
262
|
+
- `last_failed`: reads previously failed case names from `.symtest/last_run.json`
|
|
263
263
|
|
|
264
264
|
**xfail mechanism `_apply_xfail_status()`**:
|
|
265
265
|
|
|
@@ -318,6 +318,7 @@ class TestCase:
|
|
|
318
318
|
expected_failure: bool = False
|
|
319
319
|
xfail_reason: str = ""
|
|
320
320
|
xfail_quiet: bool = False
|
|
321
|
+
depends_on: List[str] = field(default_factory=list)
|
|
321
322
|
```
|
|
322
323
|
|
|
323
324
|
Two modes:
|
|
@@ -426,7 +427,7 @@ Core interfaces:
|
|
|
426
427
|
`--last-failed` state storage module (`core/last_run_store.py`):
|
|
427
428
|
|
|
428
429
|
```python
|
|
429
|
-
# Storage location: <workspace>/.
|
|
430
|
+
# Storage location: <workspace>/.symtest/last_run.json
|
|
430
431
|
# {
|
|
431
432
|
# "case_name": {"status": "passed"},
|
|
432
433
|
# ...
|
|
@@ -448,8 +449,8 @@ Each run **overwrites** the status of executed cases; unexecuted cases retain th
|
|
|
448
449
|
`--resume` step-level resume module (`core/sequence_state.py`):
|
|
449
450
|
|
|
450
451
|
```python
|
|
451
|
-
# State file: <workspace>/.
|
|
452
|
-
# Output cache: <workspace>/.
|
|
452
|
+
# State file: <workspace>/.symtest/sequence_state/<case_name>.json
|
|
453
|
+
# Output cache: <workspace>/.symtest/sequence_state/cache/<case_name>.step<N>.log
|
|
453
454
|
```
|
|
454
455
|
|
|
455
456
|
Core interfaces:
|
|
@@ -684,7 +685,7 @@ Config file (JSON/YAML)
|
|
|
684
685
|
_update_history() # Regression detection + update .symtest
|
|
685
686
|
│
|
|
686
687
|
▼
|
|
687
|
-
_save_last_run() # Write .
|
|
688
|
+
_save_last_run() # Write .symtest/last_run.json
|
|
688
689
|
│
|
|
689
690
|
▼
|
|
690
691
|
setup_manager.teardown_all() # Reverse cleanup
|
|
@@ -699,14 +700,14 @@ Config file (JSON/YAML)
|
|
|
699
700
|
ParallelConfigRunner.run_tests()
|
|
700
701
|
│
|
|
701
702
|
▼
|
|
702
|
-
LPT sort (historical avg_duration
|
|
703
|
+
Topology-constrained LPT sort (depends_on + historical avg_duration desc)
|
|
703
704
|
│
|
|
704
705
|
▼
|
|
705
706
|
_assign_relative_cpu_cores() # Proportional CPU core assignment by weight
|
|
706
707
|
│
|
|
707
708
|
▼
|
|
708
709
|
┌──────────────────────────────────────┐
|
|
709
|
-
│
|
|
710
|
+
│ DAG scheduling / flat (no deps) │
|
|
710
711
|
│ AtomicSemaphore.acquire(cores) │
|
|
711
712
|
│ Inject OMP/MKL/NPROC env vars │
|
|
712
713
|
│ execute_single_test_case() │
|
|
@@ -715,7 +716,47 @@ ParallelConfigRunner.run_tests()
|
|
|
715
716
|
└──────────────────────────────────────┘
|
|
716
717
|
```
|
|
717
718
|
|
|
718
|
-
### 7.3
|
|
719
|
+
### 7.3 DAG Dependency Scheduling Flow
|
|
720
|
+
|
|
721
|
+
When `TestCase.depends_on` is non-empty, the parallel runner switches to DAG topology scheduling:
|
|
722
|
+
|
|
723
|
+
```
|
|
724
|
+
ParallelRunner.run_tests()
|
|
725
|
+
│
|
|
726
|
+
▼
|
|
727
|
+
has_deps? ──No──► _run_tests_flat() (fast path)
|
|
728
|
+
│
|
|
729
|
+
Yes
|
|
730
|
+
▼
|
|
731
|
+
_run_dag()
|
|
732
|
+
│
|
|
733
|
+
├── Build dependents adjacency + in_degree table
|
|
734
|
+
├── in_degree=0 cases → ready queue → executor.submit()
|
|
735
|
+
│
|
|
736
|
+
▼
|
|
737
|
+
┌────────────────────────────────────────┐
|
|
738
|
+
│ as_completed() loop: │
|
|
739
|
+
│ Complete one future │
|
|
740
|
+
│ │ │
|
|
741
|
+
│ ├── passed/xfailed → decrement │
|
|
742
|
+
│ │ successor in-degree │
|
|
743
|
+
│ │ └── in_degree=0 → submit() │
|
|
744
|
+
│ │ │
|
|
745
|
+
│ └── failed/xpassed → cascade_skip │
|
|
746
|
+
│ └── BFS mark all downstream │
|
|
747
|
+
│ as skipped │
|
|
748
|
+
└────────────────────────────────────────┘
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
**Scheduling semantics**:
|
|
752
|
+
- Dependency "satisfied" = status is `passed` or `xfailed`
|
|
753
|
+
- Dependency "unsatisfied" = status is `failed` or `xpassed` → all downstream skipped
|
|
754
|
+
- `skipped` is NOT counted as `failed`; listed separately in reports
|
|
755
|
+
- Cascade skip: if B is skipped, C (which depends on B) is also skipped
|
|
756
|
+
|
|
757
|
+
**Sequential runner** (`BaseRunner.run_tests()`) also supports topological ordering: `_topological_order()` uses Kahn's algorithm to generate a topological sequence, runs in order, and auto-skips downstream on dependency failure.
|
|
758
|
+
|
|
759
|
+
### 7.4 File Comparison Flow
|
|
719
760
|
|
|
720
761
|
```
|
|
721
762
|
symtest compare file1 file2 [options]
|
|
@@ -737,7 +778,7 @@ symtest compare file1 file2 [options]
|
|
|
737
778
|
format_result(result, --output-format) # text / json / html
|
|
738
779
|
```
|
|
739
780
|
|
|
740
|
-
### 7.
|
|
781
|
+
### 7.5 --resume Checkpoint Flow
|
|
741
782
|
|
|
742
783
|
```
|
|
743
784
|
Sequence test case execution
|
|
@@ -781,7 +822,7 @@ Sequence test case execution
|
|
|
781
822
|
| LPT scheduling strategy | Long tasks start first, reducing tail latency; prioritizes `.symtest` historical data |
|
|
782
823
|
| Cumulative average history update | Simple and intuitive; single anomalies are naturally diluted over many runs |
|
|
783
824
|
| Regression check before update | Compare against old average first, then update; ensures comparison is against the "historical baseline" |
|
|
784
|
-
| `.symtest
|
|
825
|
+
| `.symtest/` directory | Non-intrusive to the user's directory view; JSON format for easy debugging; state files centrally managed |
|
|
785
826
|
| Environment variable injection | Scientific computing solvers often ignore Python-level thread control |
|
|
786
827
|
| Comparator factory + plugin discovery | Creates comparators by file type; workspace `comparators/` directory for auto-discovered plugins |
|
|
787
828
|
| subprocess isolated execution | Each test case runs in an independent subprocess, ensuring tests don't affect each other |
|
|
@@ -789,6 +830,7 @@ Sequence test case execution
|
|
|
789
830
|
| --last-failed overwrite strategy | Only overwrites status of executed cases; avoids losing state of unexecuted cases during subset runs |
|
|
790
831
|
| --resume pure trust model | No artifact validation; user guarantees workspace is unchanged, simplifying implementation |
|
|
791
832
|
| retry_count retry mechanism | Handles transient network glitches or race conditions; auto-retries on first failure |
|
|
833
|
+
| DAG dependency scheduling | Kahn topology + ready queue; submits dependents immediately once deps are satisfied; cascade-skips downstream on dep failure; zero-overhead fast path when no deps declared |
|
|
792
834
|
| --update-baseline | Automatically overwrites baseline files with actual output on comparison failure; ideal for batch baseline updates |
|
|
793
835
|
| next_action_hint structured suggestions | Failed results include actionable suggestions (update_baseline / update_expected / increase_timeout / investigate), convenient for AI consumption |
|
|
794
836
|
| TUI based on Textual | Leverages a mature terminal UI framework for interactive case management |
|
|
@@ -683,8 +683,8 @@ tui = ["textual>=0.40.0"]
|
|
|
683
683
|
```
|
|
684
684
|
|
|
685
685
|
```bash
|
|
686
|
-
pip install symtest[tui] # 安装 TUI 依赖
|
|
687
|
-
pip install symtest # 核心包,不含 TUI
|
|
686
|
+
pip install symtest-cli[tui] # 安装 TUI 依赖
|
|
687
|
+
pip install symtest-cli # 核心包,不含 TUI
|
|
688
688
|
```
|
|
689
689
|
|
|
690
690
|
### 9.2 优雅降级
|
|
@@ -698,7 +698,7 @@ def run_tui(config_file, workspace):
|
|
|
698
698
|
except ImportError:
|
|
699
699
|
print(
|
|
700
700
|
"TUI 功能需要安装 textual。请运行:\n"
|
|
701
|
-
" pip install symtest[tui]\n"
|
|
701
|
+
" pip install symtest-cli[tui]\n"
|
|
702
702
|
"或:\n"
|
|
703
703
|
" pip install textual"
|
|
704
704
|
)
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
- [安装](#安装)
|
|
6
6
|
- [测试用例定义](#测试用例定义)
|
|
7
|
+
- [Case 级环境变量](#case-级环境变量env)
|
|
7
8
|
- [配置拆分机制](#配置拆分机制)
|
|
8
9
|
- [配置继承](#配置继承)
|
|
9
10
|
- [配置校验](#配置校验)
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
## 安装
|
|
27
28
|
|
|
28
29
|
```bash
|
|
29
|
-
pip install symtest
|
|
30
|
+
pip install symtest-cli
|
|
30
31
|
```
|
|
31
32
|
|
|
32
33
|
要求:Python >= 3.9
|
|
@@ -34,13 +35,13 @@ pip install symtest
|
|
|
34
35
|
YAML 支持需安装可选依赖:
|
|
35
36
|
|
|
36
37
|
```bash
|
|
37
|
-
pip install "symtest[yaml]"
|
|
38
|
+
pip install "symtest-cli[yaml]"
|
|
38
39
|
```
|
|
39
40
|
|
|
40
41
|
一次安装 YAML 和 TUI 等全部可选功能:
|
|
41
42
|
|
|
42
43
|
```bash
|
|
43
|
-
pip install "symtest[all]"
|
|
44
|
+
pip install "symtest-cli[all]"
|
|
44
45
|
```
|
|
45
46
|
|
|
46
47
|
HDF5 文件比较依赖 `h5py`(已随框架安装)。如需在无 HDF5 环境下使用其他比较功能,可单独卸载,但 HDF5 比较将不可用。
|
|
@@ -159,6 +160,78 @@ test_cases:
|
|
|
159
160
|
}
|
|
160
161
|
```
|
|
161
162
|
|
|
163
|
+
### 测试依赖(depends_on)
|
|
164
|
+
|
|
165
|
+
当测试用例之间存在先后依赖时(例如 D 需要 A、B、C 先生成数据),通过 `depends_on` 声明依赖关系,框架会自动按 DAG 拓扑顺序调度:
|
|
166
|
+
|
|
167
|
+
**并行模式**:A、B、C 并行执行,全部通过后 D 才被提交。依赖失败的用例会自动 skip 其下游(级联 skip)。
|
|
168
|
+
|
|
169
|
+
**顺序模式**:框架按拓扑序重排用例,保证依赖在前的先执行,依赖失败时同样跳过下游。
|
|
170
|
+
|
|
171
|
+
**JSON 示例**:
|
|
172
|
+
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"test_cases": [
|
|
176
|
+
{ "name": "A", "command": "python", "args": ["gen_a.py"], "expected": {"return_code": 0} },
|
|
177
|
+
{ "name": "B", "command": "python", "args": ["gen_b.py"], "expected": {"return_code": 0} },
|
|
178
|
+
{ "name": "C", "command": "python", "args": ["gen_c.py"], "expected": {"return_code": 0} },
|
|
179
|
+
{
|
|
180
|
+
"name": "D", "command": "python", "args": ["merge.py"],
|
|
181
|
+
"depends_on": ["A", "B", "C"],
|
|
182
|
+
"expected": {"return_code": 0, "compare_files": [{"file": "output.h5", "type": "hdf5"}]}
|
|
183
|
+
}
|
|
184
|
+
]
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**YAML 示例**:
|
|
189
|
+
|
|
190
|
+
```yaml
|
|
191
|
+
test_cases:
|
|
192
|
+
- name: A
|
|
193
|
+
command: python
|
|
194
|
+
args: ["gen_a.py"]
|
|
195
|
+
expected: { return_code: 0 }
|
|
196
|
+
|
|
197
|
+
- name: B
|
|
198
|
+
command: python
|
|
199
|
+
args: ["gen_b.py"]
|
|
200
|
+
expected: { return_code: 0 }
|
|
201
|
+
|
|
202
|
+
- name: C
|
|
203
|
+
command: python
|
|
204
|
+
args: ["gen_c.py"]
|
|
205
|
+
expected: { return_code: 0 }
|
|
206
|
+
|
|
207
|
+
- name: D
|
|
208
|
+
command: python
|
|
209
|
+
args: ["merge.py"]
|
|
210
|
+
depends_on: [A, B, C]
|
|
211
|
+
expected:
|
|
212
|
+
return_code: 0
|
|
213
|
+
compare_files:
|
|
214
|
+
- file: output.h5
|
|
215
|
+
type: hdf5
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**调度语义**:
|
|
219
|
+
|
|
220
|
+
| 依赖状态 | 下游行为 |
|
|
221
|
+
|---|---|
|
|
222
|
+
| `passed` 或 `xfailed` | 依赖"满足",下游正常执行 |
|
|
223
|
+
| `failed` 或 `xpassed` | 依赖"不满足",下游标记为 `skipped`,并级联 skip |
|
|
224
|
+
| 存在循环依赖 | 配置校验阶段报错,禁止运行 |
|
|
225
|
+
|
|
226
|
+
`skipped` 不计入 `failed` 计数,在报告摘要中单独显示 `Skipped: N`。
|
|
227
|
+
|
|
228
|
+
**约束**:
|
|
229
|
+
- 依赖名称必须在同配置文件的 `test_cases` 中存在
|
|
230
|
+
- 不允许自依赖(`depends_on: ["self"]`)
|
|
231
|
+
- 不允许循环依赖(A → B → A)
|
|
232
|
+
- 与 `steps` 模式互不影响——`depends_on` 是用例级概念,`steps` 是用例内步骤级概念
|
|
233
|
+
- 无依赖时走 fast path,调度开销为零
|
|
234
|
+
|
|
162
235
|
### 字段说明
|
|
163
236
|
|
|
164
237
|
| 字段 | 必填 | 说明 |
|
|
@@ -174,11 +247,69 @@ test_cases:
|
|
|
174
247
|
| `expected_failure` | 否 | 标记为预期失败(xfail)。设为 `true` 时,失败计为 XFailed(不影响退出码),意外通过计为 XPassed(视作失败) |
|
|
175
248
|
| `xfail_reason` | 否 | xfail 的原因说明,报告中将展示此文本(如 "Bug #42 尚未修复") |
|
|
176
249
|
| `xfail_quiet` | 否 | 设为 `true` 时,xfailed 状态下报告中不输出 Command Output(stdout/stderr 大段输出),仅保留命令、返回码、失败原因等元信息 |
|
|
250
|
+
| `depends_on` | 否 | 依赖的测试用例名称列表(如 `["A", "B"]`)。当前用例必须等待所有依赖用例通过后才执行。依赖失败时自动 skip 当前用例及下游。支持并行和顺序两种 runner |
|
|
251
|
+
| `env` | 否 | case 级环境变量字典(如 `{"UEL_SYSID_SCALE": "1.0"}`),仅在执行该 case(序列模式为所有 step)时注入子进程,见 [Case 级环境变量](#case-级环境变量env) |
|
|
177
252
|
| `expected.return_code` | 否 | 期望返回码 |
|
|
178
253
|
| `expected.output_contains` | 否 | 输出需包含的字符串列表 |
|
|
179
254
|
| `expected.output_matches` | 否 | 输出需匹配的正则表达式(单个字符串) |
|
|
180
255
|
| `expected.compare_files` | 否 | 文件比较断言列表,见下文 |
|
|
181
256
|
|
|
257
|
+
## Case 级环境变量(env)
|
|
258
|
+
|
|
259
|
+
通过 case 下与 `name` 同级的 `env` 字段,可为单个用例注入环境变量,仅在该用例(序列模式为所有 step)的子进程内生效,不影响其他用例。
|
|
260
|
+
|
|
261
|
+
### JSON
|
|
262
|
+
|
|
263
|
+
```json
|
|
264
|
+
{
|
|
265
|
+
"name": "UEL 缩放测试",
|
|
266
|
+
"command": "solver",
|
|
267
|
+
"args": ["-i", "input.dat"],
|
|
268
|
+
"env": {
|
|
269
|
+
"UEL_SYSID_SCALE": "1.0",
|
|
270
|
+
"OMP_NUM_THREADS": "8"
|
|
271
|
+
},
|
|
272
|
+
"expected": { "return_code": 0 }
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### YAML
|
|
277
|
+
|
|
278
|
+
```yaml
|
|
279
|
+
- name: UEL 缩放测试
|
|
280
|
+
command: solver
|
|
281
|
+
args: ["-i", "input.dat"]
|
|
282
|
+
env:
|
|
283
|
+
UEL_SYSID_SCALE: "1.0"
|
|
284
|
+
expected: { return_code: 0 }
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### 序列模式
|
|
288
|
+
|
|
289
|
+
`env` 定义在 case 级(与 `steps` 同级),对该 case 的**所有 step** 生效:
|
|
290
|
+
|
|
291
|
+
```json
|
|
292
|
+
{
|
|
293
|
+
"name": "多步骤+环境变量",
|
|
294
|
+
"env": { "UEL_SYSID_SCALE": "1.0" },
|
|
295
|
+
"steps": [
|
|
296
|
+
{ "command": "python", "args": ["./step1.py"], "expected": { "return_code": 0 } },
|
|
297
|
+
{ "command": "python", "args": ["./step2.py"], "expected": { "return_code": 0 } }
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### 语义
|
|
303
|
+
|
|
304
|
+
| 决策点 | 行为 |
|
|
305
|
+
|---|---|
|
|
306
|
+
| 生效方式 | 通过子进程 `env` 注入,不修改进程全局 `os.environ`,天然进程隔离、线程安全 |
|
|
307
|
+
| 优先级 | `os.environ`(含 `setup.environment_variables`)< 调度器注入(`OMP/MKL/NPROC`)< **case `env`(最高)**,即 case env 可覆盖调度器的 `OMP_NUM_THREADS` |
|
|
308
|
+
| 作用范围 | 仅当前 case,不污染其他 case(区别于全局 `setup.environment_variables`) |
|
|
309
|
+
| 占位符 | 自动支持,`"env": {"SCALE": "{scale}"}` 会被 `variables`/`--var` 替换 |
|
|
310
|
+
| 继承(extends) | 自动支持,`env` 为 dict,深合并、子类覆盖父类同名 key |
|
|
311
|
+
| 值类型 | 字符串;数字/布尔在解析时自动 `str()` 化 |
|
|
312
|
+
|
|
182
313
|
### 文件比较断言(compare_files)
|
|
183
314
|
|
|
184
315
|
在 `expected` 中通过 `compare_files` 可声明一条或多条文件比较规则,框架会在命令执行后自动用对应的比较器对比实际产出文件与基线文件。所有比较通过才算用例通过,可与 `return_code`、`output_contains` 等断言共存。
|
|
@@ -515,7 +646,7 @@ TUI 依赖 `textual` 库,并作为按需安装的可选依赖提供:
|
|
|
515
646
|
|
|
516
647
|
```bash
|
|
517
648
|
# 安装时附带 TUI 支持
|
|
518
|
-
pip install "symtest[tui]"
|
|
649
|
+
pip install "symtest-cli[tui]"
|
|
519
650
|
|
|
520
651
|
# 或者在已有框架上单独安装 textual
|
|
521
652
|
pip install textual
|
|
@@ -702,7 +833,7 @@ symtest run test_cases.json --error-analysis
|
|
|
702
833
|
**xfail 语义**:标记为 `expected_failure` 的用例如果失败(`xfailed`),是预期行为,**不会**被 `--last-failed` 选中重跑。但如果 xfail 标记的用例意外通过(`xpassed`),则被视为真正失败,**会**被选中。
|
|
703
834
|
|
|
704
835
|
**工作原理**:
|
|
705
|
-
- 每次运行结束后,框架在 `<workspace>/.
|
|
836
|
+
- 每次运行结束后,框架在 `<workspace>/.symtest/last_run.json` 中记录每个用例的状态
|
|
706
837
|
- 记录采用**覆盖式更新**:本次跑到的用例用新结果覆盖旧结果,没跑到的保留原状态
|
|
707
838
|
- 这意味着修好的 case 在下一次显示中不再是"failed"
|
|
708
839
|
- 如果文件不存在(首次运行),`--last-failed` 会提示并正常运行全部用例
|
|
@@ -725,7 +856,7 @@ symtest run config.json
|
|
|
725
856
|
`--resume` 针对**顺序步骤测试(sequence)**,跳过上次运行中已通过的步骤,直接从失败步骤继续执行。适合耗时长的多步骤用例——例如有限元分析中 step 1-3 通过了(各耗时几十秒甚至分钟),只有 step 4 的断言失败,`--resume` 可以跳过 1-3、只重跑 step 4。
|
|
726
857
|
|
|
727
858
|
**工作原理**:
|
|
728
|
-
- 每个步骤通过后,框架在 `<workspace>/.
|
|
859
|
+
- 每个步骤通过后,框架在 `<workspace>/.symtest/sequence_state/<case_name>.json` 中记录步骤状态,并将输出缓存到 `cache/` 子目录
|
|
729
860
|
- 下次 `--resume` 时,计算配置哈希(所有步骤的 command/args/expected/timeout/retry_count 及 case 级 expected 的 SHA256)与已保存状态比对
|
|
730
861
|
- 哈希匹配 → 跳过已通过的步骤,从缓存重建 `combined_output`(确保 case 级 `expected` 断言能正常执行)
|
|
731
862
|
- 用例全部通过 → 自动删除状态文件和缓存,避免残留影响后续运行
|