symtest-cli 1.3.2__tar.gz → 1.3.3__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.2/src/symtest_cli.egg-info → symtest_cli-1.3.3}/PKG-INFO +1 -1
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/docs/user_manual.md +27 -15
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/docs/user_manual_en.md +27 -15
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/__init__.py +1 -1
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/cli.py +10 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/base_runner.py +4 -1
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/execution.py +6 -2
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/parallel_runner.py +2 -1
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/file_comparator/csv_comparator.py +88 -88
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/file_comparator/h5_comparator.py +37 -83
- symtest_cli-1.3.3/src/symtest/file_comparator/numeric_compare.py +252 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/utils/report_generator.py +12 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3/src/symtest_cli.egg-info}/PKG-INFO +1 -1
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest_cli.egg-info/SOURCES.txt +14 -0
- symtest_cli-1.3.3/tests/e2e/__pycache__/test_user_flows.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/test_cases.yaml +9 -9
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/__pycache__/test_history_feature.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/__pycache__/test_history_feature.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/integration/__pycache__/test_new_cli_features.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/__pycache__/test_new_cli_features.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/integration/__pycache__/test_real_command_execution.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/integration/__pycache__/test_sequence.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/integration/parallel/__pycache__/test_depends_on.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/parallel/__pycache__/test_depends_on.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/__pycache__/test_config_io.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_import_expander.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_inheritance_expander.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/__pycache__/test_migrate.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_architecture_guard.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_architecture_guard.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_assertions.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_assertions.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_case_env.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_case_env.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_config_loader.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_config_loader.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_execution.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_execution.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_execution_new_features.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_execution_new_features.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_model_v2.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_model_v2.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_orchestration_accept.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_orchestration_accept.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_process_worker.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_sequence_state.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_sequence_state.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_setup.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_validation_error.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/core/__pycache__/test_validation_error.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_assertions.py +1 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/test_error_analysis.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/test_error_analysis.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/file_comparator/__pycache__/test_numeric_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/file_comparator/__pycache__/test_numeric_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/file_comparator/__pycache__/test_numeric_parity.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/file_comparator/__pycache__/test_numeric_parity.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/test_error_analysis.py +3 -4
- symtest_cli-1.3.3/tests/unit/file_comparator/test_numeric_compare.py +233 -0
- symtest_cli-1.3.3/tests/unit/file_comparator/test_numeric_parity.py +160 -0
- symtest_cli-1.3.3/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-312-pytest-7.4.4.pyc +0 -0
- symtest_cli-1.3.3/tests/unit/tui/__pycache__/conftest.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_case_controller.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_case_controller.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/utils/__pycache__/test_report_generator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/utils/__pycache__/test_report_generator.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/utils/test_report_generator.py +67 -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.2/tests/integration/__pycache__/test_new_cli_features.cpython-312-pytest-7.4.4.pyc +0 -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.2/tests/integration/__pycache__/test_sequence.cpython-312-pytest-7.4.4.pyc +0 -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_parallel_runner.cpython-312-pytest-7.4.4.pyc +0 -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.2/tests/unit/__pycache__/test_config_io.cpython-312-pytest-7.4.4.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_config_loader.cpython-312-pytest-7.4.4.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.2/tests/unit/core/__pycache__/test_execution_new_features.cpython-312-pytest-7.4.4.pyc +0 -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.2/tests/unit/core/__pycache__/test_validation_error.cpython-312-pytest-7.4.4.pyc +0 -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/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-7.4.4.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.2 → symtest_cli-1.3.3}/LICENSE +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/MANIFEST.in +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/README.md +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/docs/design.md +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/docs/design_en.md +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/docs/tui_and_config_split_design.md +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/pyproject.toml +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/setup.cfg +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/setup.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/commands/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/commands/compare.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/config/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/config/config_io.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/config/config_schema.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/config/import_expander.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/config/inheritance_expander.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/assertions.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/config_loader.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/history_store.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/last_run_store.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/process_worker.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/sequence_state.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/setup.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/test_case.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/core/types.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/file_comparator/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/file_comparator/base_comparator.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/file_comparator/binary_comparator.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/file_comparator/factory.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/file_comparator/json_comparator.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/file_comparator/result.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/file_comparator/script_comparator.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/file_comparator/text_comparator.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/file_comparator/xml_comparator.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/logging_config.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/runners/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/runners/config_runner.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/runners/json_runner.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/runners/parallel_config_runner.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/runners/parallel_json_runner.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/runners/parallel_yaml_runner.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/runners/yaml_runner.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/tui/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/tui/app.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/tui/controllers/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/tui/controllers/case_controller.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/tui/screens/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/tui/screens/case_editor.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/tui/screens/case_list.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/tui/widgets/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/tui/widgets/case_table.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/tui/widgets/expected_editor.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/tui/widgets/search_bar.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/tui/widgets/steps_editor.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/utils/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/utils/junit_xml_writer.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest/utils/path_resolver.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest_cli.egg-info/dependency_links.txt +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest_cli.egg-info/entry_points.txt +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest_cli.egg-info/requires.txt +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/src/symtest_cli.egg-info/top_level.txt +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/README.md +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/__pycache__/__init__.cpython-313.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/__pycache__/__init__.cpython-39.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/__pycache__/conftest.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/__pycache__/conftest.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/__pycache__/conftest.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/__pycache__/run_all.cpython-312.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/__pycache__/run_all.cpython-313.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/__pycache__/run_all.cpython-39.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/__pycache__/test_setup_module.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/conftest.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/demos/h5_filter_demo.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/demos/manual_report_example.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/demos/perf_parallel.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/e2e/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/e2e/__pycache__/__init__.cpython-312.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/e2e/__pycache__/__init__.cpython-313.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/e2e/__pycache__/__init__.cpython-39.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/e2e/__pycache__/test_user_flows.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/e2e/__pycache__/test_user_flows.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/e2e/__pycache__/test_user_flows.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/e2e/test_user_flows.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/circular_config_a.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/circular_config_b.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/hourglass_stdout_mismatch.txt +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/hourglass_stdout_sample.txt +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/inheritance_base.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/inheritance_chain.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/inheritance_circular.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/main_config.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/missing_fields.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/mock_fail_script.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/mock_pass_script.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/setup_main.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/setup_sub.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/sub_json_tests.yaml +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/sub_text_tests.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/test_cases.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/test_cases1.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/test_with_setup.json +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/fixtures/test_with_setup.yaml +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/__pycache__/test_history_feature.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/__pycache__/test_new_cli_features.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/__pycache__/test_real_command_execution.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/__pycache__/test_real_command_execution.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/__pycache__/test_sequence.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/__pycache__/test_sequence.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/test_binary_compare.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/test_csv_compare.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/test_h5_compare.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/test_json_compare.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/test_text_compare.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/file_compare/test_xml_compare.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/parallel/test_depends_on.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/parallel/test_parallel_runner.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/path_handling/test_spaces_in_paths.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/test_history_feature.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/test_new_cli_features.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/test_real_command_execution.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/integration/test_sequence.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/run_all.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_binary_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_binary_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_binary_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_cli.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_cli.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_config_io.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_config_io.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_h5_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_h5_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_h5_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_import_expander.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_import_expander.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_inheritance_expander.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_inheritance_expander.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_result.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_result.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_result.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_run_all.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_run_all.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/__pycache__/test_run_all.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/commands/__pycache__/test_compare_command.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/commands/__pycache__/test_compare_command.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/commands/__pycache__/test_compare_command.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/commands/test_compare_command.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_assertions.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_config_loader.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_execution.cpython-312.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_execution.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_execution_new_features.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_history_store.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_history_store.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_history_store.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_last_run_store.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_last_run_store.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_last_run_store.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_process_worker.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_process_worker.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_setup.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_setup.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_setup.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_validation_error.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_xfail.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_xfail.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/__pycache__/test_xfail.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_case_env.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_config_loader.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_config_loader_new_features.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_execution.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_execution_new_features.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_history_store.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_last_run_store.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_process_worker.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_sequence_state.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_setup.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_validation_error.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/core/test_xfail.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/__init__.cpython-312.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/test_error_analysis.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/test_hourglass_tangent_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/test_hourglass_tangent_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/test_hourglass_tangent_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/test_script_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/test_script_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/test_script_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/test_workspace_plugins.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/test_workspace_plugins.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/__pycache__/test_workspace_plugins.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/test_hourglass_tangent_comparator.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/test_script_comparator.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/file_comparator/test_workspace_plugins.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/test_json_yaml_runner.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/test_test_case_filter.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/runners/test_test_case_tag_filter.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/test_binary_comparator.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/test_cli.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/test_config_io.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/test_h5_comparator.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/test_import_expander.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/test_inheritance_expander.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/test_result.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/test_run_all.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__init__.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/__init__.cpython-312.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/__init__.cpython-313.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/conftest.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_app.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_app.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_app.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_case_controller.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_search_functions.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_search_functions.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_search_functions.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_tui_run_test.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_tui_run_test.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_tui_run_test.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_widgets_data.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_widgets_data.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/__pycache__/test_widgets_data.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/conftest.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/test_app.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/test_case_controller.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/test_search_functions.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/test_tui_run_test.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/tui/test_widgets_data.py +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/utils/__pycache__/test_report_generator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.2 → symtest_cli-1.3.3}/tests/unit/utils/test_junit_xml_writer.py +0 -0
|
@@ -248,7 +248,7 @@ test_cases:
|
|
|
248
248
|
| `xfail_reason` | 否 | xfail 的原因说明,报告中将展示此文本(如 "Bug #42 尚未修复") |
|
|
249
249
|
| `xfail_quiet` | 否 | 设为 `true` 时,xfailed 状态下报告中不输出 Command Output(stdout/stderr 大段输出),仅保留命令、返回码、失败原因等元信息 |
|
|
250
250
|
| `depends_on` | 否 | 依赖的测试用例名称列表(如 `["A", "B"]`)。当前用例必须等待所有依赖用例通过后才执行。依赖失败时自动 skip 当前用例及下游。支持并行和顺序两种 runner |
|
|
251
|
-
| `env` | 否 | case 级环境变量字典(如 `{"
|
|
251
|
+
| `env` | 否 | case 级环境变量字典(如 `{"MYAPP_SCALE": "1.0"}`),仅在执行该 case(序列模式为所有 step)时注入子进程,见 [Case 级环境变量](#case-级环境变量env) |
|
|
252
252
|
| `expected.return_code` | 否 | 期望返回码 |
|
|
253
253
|
| `expected.output_contains` | 否 | 输出需包含的字符串列表 |
|
|
254
254
|
| `expected.output_matches` | 否 | 输出需匹配的正则表达式(单个字符串) |
|
|
@@ -262,11 +262,11 @@ test_cases:
|
|
|
262
262
|
|
|
263
263
|
```json
|
|
264
264
|
{
|
|
265
|
-
"name": "
|
|
265
|
+
"name": "case 级环境变量示例",
|
|
266
266
|
"command": "solver",
|
|
267
267
|
"args": ["-i", "input.dat"],
|
|
268
268
|
"env": {
|
|
269
|
-
"
|
|
269
|
+
"MYAPP_SCALE": "1.0",
|
|
270
270
|
"OMP_NUM_THREADS": "8"
|
|
271
271
|
},
|
|
272
272
|
"expected": { "return_code": 0 }
|
|
@@ -276,11 +276,11 @@ test_cases:
|
|
|
276
276
|
### YAML
|
|
277
277
|
|
|
278
278
|
```yaml
|
|
279
|
-
- name:
|
|
279
|
+
- name: case 级环境变量示例
|
|
280
280
|
command: solver
|
|
281
281
|
args: ["-i", "input.dat"]
|
|
282
282
|
env:
|
|
283
|
-
|
|
283
|
+
MYAPP_SCALE: "1.0"
|
|
284
284
|
expected: { return_code: 0 }
|
|
285
285
|
```
|
|
286
286
|
|
|
@@ -291,7 +291,7 @@ test_cases:
|
|
|
291
291
|
```json
|
|
292
292
|
{
|
|
293
293
|
"name": "多步骤+环境变量",
|
|
294
|
-
"env": { "
|
|
294
|
+
"env": { "MYAPP_SCALE": "1.0" },
|
|
295
295
|
"steps": [
|
|
296
296
|
{ "command": "python", "args": ["./step1.py"], "expected": { "return_code": 0 } },
|
|
297
297
|
{ "command": "python", "args": ["./step2.py"], "expected": { "return_code": 0 } }
|
|
@@ -814,7 +814,7 @@ symtest run test_cases.json --last-failed
|
|
|
814
814
|
|
|
815
815
|
# 断点续跑:跳过已通过的步骤,从失败步骤继续
|
|
816
816
|
symtest run test_cases.json --resume
|
|
817
|
-
symtest run test_cases.json --resume -t
|
|
817
|
+
symtest run test_cases.json --resume -t long_pipeline
|
|
818
818
|
|
|
819
819
|
# 比较失败时更新基线文件(交互运行需输入 yes)
|
|
820
820
|
symtest run test_cases.json --update-baseline
|
|
@@ -865,11 +865,11 @@ symtest run config.json
|
|
|
865
865
|
**信任模型**:`--resume` **不校验工作区产物**(输入文件、前置步骤生成的文件等)。使用 `--resume` 即表示用户确认输入文件未被修改。如果怀疑工作区被污染,应不带 `--resume` 全量重跑。
|
|
866
866
|
|
|
867
867
|
```bash
|
|
868
|
-
# 首次全量运行,
|
|
868
|
+
# 首次全量运行,long_pipeline 的 step 4 失败(总耗时 72s)
|
|
869
869
|
symtest run config.json
|
|
870
870
|
|
|
871
|
-
# 修复后只重跑
|
|
872
|
-
symtest run config.json -t
|
|
871
|
+
# 修复后只重跑 long_pipeline,跳过 step 1-3(仅耗时 ~0.14s)
|
|
872
|
+
symtest run config.json -t long_pipeline --resume
|
|
873
873
|
|
|
874
874
|
# 全部通过后,跑一次全量确认无回归
|
|
875
875
|
symtest run config.json
|
|
@@ -1742,7 +1742,16 @@ CSV 比较按行列结构逐单元格比对;数值单元格在容差范围内
|
|
|
1742
1742
|
| `mean_abs_error` | 平均绝对误差 |
|
|
1743
1743
|
| `rms_abs_error` | 均方根绝对误差(RMSE) |
|
|
1744
1744
|
|
|
1745
|
-
|
|
1745
|
+
统计是**流式**计算的,不依赖差异截断,覆盖全体数值单元格。默认仅失败的比较输出统计,通过的比较不输出。
|
|
1746
|
+
|
|
1747
|
+
如需让**通过**的用例也输出统计信息(例如用于监控容差余量),可改用 `--error-analysis-all`(它会隐含启用 `--error-analysis`):
|
|
1748
|
+
|
|
1749
|
+
```bash
|
|
1750
|
+
# 对所有用例(含通过的)输出误差统计
|
|
1751
|
+
symtest run config.json --error-analysis-all
|
|
1752
|
+
```
|
|
1753
|
+
|
|
1754
|
+
启用后,每个**通过**的用例会在 Detailed Results 区块中以 `error_stats (baseline vs actual):` 的形式列出上述统计量(与失败用例的 `error_stats` 字段一致)。通过用例的统计也同时写入 `--output json` 的 `assertion_results[].error_stats`,便于程序化消费。仅当 `--error-analysis-all` 启用时才会对通过用例产生额外输出,未启用时行为不变。
|
|
1746
1755
|
|
|
1747
1756
|
**CLI 用法**:
|
|
1748
1757
|
|
|
@@ -1750,6 +1759,9 @@ CSV 比较按行列结构逐单元格比对;数值单元格在容差范围内
|
|
|
1750
1759
|
# 启用误差分析
|
|
1751
1760
|
symtest run config.json --error-analysis
|
|
1752
1761
|
|
|
1762
|
+
# 启用误差分析并对通过的用例也输出统计
|
|
1763
|
+
symtest run config.json --error-analysis-all
|
|
1764
|
+
|
|
1753
1765
|
# 与比较参数组合使用
|
|
1754
1766
|
symtest run config.json --error-analysis --csv-rtol 1e-4 --csv-data-filter '>0'
|
|
1755
1767
|
```
|
|
@@ -2005,8 +2017,8 @@ comparator = ComparatorFactory.create_comparator("foo")
|
|
|
2005
2017
|
```json
|
|
2006
2018
|
{
|
|
2007
2019
|
"type": "hourglass_tangent",
|
|
2008
|
-
"script": "case/.../
|
|
2009
|
-
"case_dir": "case/.../
|
|
2020
|
+
"script": "case/.../analyze_case01_tangent.py",
|
|
2021
|
+
"case_dir": "case/.../case01",
|
|
2010
2022
|
"pass_threshold": 1e-6,
|
|
2011
2023
|
"timeout": 600
|
|
2012
2024
|
}
|
|
@@ -2083,9 +2095,9 @@ python tests/run_all.py --scope unit --extra "-v -k assertions"
|
|
|
2083
2095
|
|
|
2084
2096
|
`--extra` 接收的字符串会经 `shlex` 拆分后追加到 pytest 命令行。脚本通过当前解释器(`sys.executable -m pytest`)调用 pytest,确保使用激活的环境而非 PATH 中首个 `pytest`。
|
|
2085
2097
|
|
|
2086
|
-
|
|
2098
|
+
测试环境需先激活你的 Python 环境(如 conda):
|
|
2087
2099
|
|
|
2088
2100
|
```bash
|
|
2089
|
-
conda activate
|
|
2101
|
+
conda activate <你的环境名>
|
|
2090
2102
|
python tests/run_all.py
|
|
2091
2103
|
```
|
|
@@ -248,7 +248,7 @@ test_cases:
|
|
|
248
248
|
| `xfail_reason` | No | Reason text for xfail, displayed in the report (e.g., "Bug #42 not yet fixed") |
|
|
249
249
|
| `xfail_quiet` | No | When `true`, suppress Command Output (stdout/stderr) for xfailed cases in the report; only command, return code, and failure reason metadata retained |
|
|
250
250
|
| `depends_on` | No | List of test case names this case depends on (e.g., `["A", "B"]`). The case will wait until all dependencies pass before executing. On dependency failure, the case and its downstream are auto-skipped. Works with both parallel and sequential runners |
|
|
251
|
-
| `env` | No | Case-level environment variable mapping (e.g. `{"
|
|
251
|
+
| `env` | No | Case-level environment variable mapping (e.g. `{"MYAPP_SCALE": "1.0"}`), injected into the subprocess only when this case runs (all steps in sequence mode). See [Case-Level Environment Variables](#case-level-environment-variables-env) |
|
|
252
252
|
| `expected.return_code` | No | Expected return code |
|
|
253
253
|
| `expected.output_contains` | No | List of strings the output must contain |
|
|
254
254
|
| `expected.output_matches` | No | Regex pattern the output must match (single string) |
|
|
@@ -299,11 +299,11 @@ Use the `env` field (same level as `name`) to inject environment variables into
|
|
|
299
299
|
|
|
300
300
|
```json
|
|
301
301
|
{
|
|
302
|
-
"name": "
|
|
302
|
+
"name": "Case-level env test",
|
|
303
303
|
"command": "solver",
|
|
304
304
|
"args": ["-i", "input.dat"],
|
|
305
305
|
"env": {
|
|
306
|
-
"
|
|
306
|
+
"MYAPP_SCALE": "1.0",
|
|
307
307
|
"OMP_NUM_THREADS": "8"
|
|
308
308
|
},
|
|
309
309
|
"expected": { "return_code": 0 }
|
|
@@ -313,11 +313,11 @@ Use the `env` field (same level as `name`) to inject environment variables into
|
|
|
313
313
|
### YAML
|
|
314
314
|
|
|
315
315
|
```yaml
|
|
316
|
-
- name:
|
|
316
|
+
- name: Case-level env test
|
|
317
317
|
command: solver
|
|
318
318
|
args: ["-i", "input.dat"]
|
|
319
319
|
env:
|
|
320
|
-
|
|
320
|
+
MYAPP_SCALE: "1.0"
|
|
321
321
|
expected: { return_code: 0 }
|
|
322
322
|
```
|
|
323
323
|
|
|
@@ -328,7 +328,7 @@ Use the `env` field (same level as `name`) to inject environment variables into
|
|
|
328
328
|
```json
|
|
329
329
|
{
|
|
330
330
|
"name": "multi-step with env",
|
|
331
|
-
"env": { "
|
|
331
|
+
"env": { "MYAPP_SCALE": "1.0" },
|
|
332
332
|
"steps": [
|
|
333
333
|
{ "command": "python", "args": ["./step1.py"], "expected": { "return_code": 0 } },
|
|
334
334
|
{ "command": "python", "args": ["./step2.py"], "expected": { "return_code": 0 } }
|
|
@@ -814,7 +814,7 @@ symtest run test_cases.json --last-failed
|
|
|
814
814
|
|
|
815
815
|
# Resume: skip passed steps, continue from failed step
|
|
816
816
|
symtest run test_cases.json --resume
|
|
817
|
-
symtest run test_cases.json --resume -t
|
|
817
|
+
symtest run test_cases.json --resume -t long_pipeline
|
|
818
818
|
|
|
819
819
|
# Update baseline files on comparison failure (type yes interactively)
|
|
820
820
|
symtest run test_cases.json --update-baseline
|
|
@@ -865,11 +865,11 @@ symtest run config.json
|
|
|
865
865
|
**Trust model**: `--resume` does **not verify workspace artifacts** (input files, files generated by prior steps, etc.). Using `--resume` means the user confirms input files are unmodified. If workspace contamination is suspected, rerun fully without `--resume`.
|
|
866
866
|
|
|
867
867
|
```bash
|
|
868
|
-
# First full run,
|
|
868
|
+
# First full run, long_pipeline step 4 fails (total 72s)
|
|
869
869
|
symtest run config.json
|
|
870
870
|
|
|
871
|
-
# After fixing, rerun only
|
|
872
|
-
symtest run config.json -t
|
|
871
|
+
# After fixing, rerun only long_pipeline, skipping steps 1-3 (~0.14s only)
|
|
872
|
+
symtest run config.json -t long_pipeline --resume
|
|
873
873
|
|
|
874
874
|
# After all pass, do one full run to confirm no regressions
|
|
875
875
|
symtest run config.json
|
|
@@ -1740,7 +1740,16 @@ When enabled, each failed file comparison appends `error_stats` to the Compare F
|
|
|
1740
1740
|
| `mean_abs_error` | Mean absolute error |
|
|
1741
1741
|
| `rms_abs_error` | Root-mean-square absolute error (RMSE) |
|
|
1742
1742
|
|
|
1743
|
-
Statistics are computed **in streaming fashion**, independent of the difference truncation, covering all numeric cells.
|
|
1743
|
+
Statistics are computed **in streaming fashion**, independent of the difference truncation, covering all numeric cells. By default only failed comparisons output statistics; passed comparisons do not.
|
|
1744
|
+
|
|
1745
|
+
To also output statistics for **passed** cases (e.g. to monitor tolerance headroom), use `--error-analysis-all` instead (it implicitly enables `--error-analysis`):
|
|
1746
|
+
|
|
1747
|
+
```bash
|
|
1748
|
+
# Output error statistics for all cases (including passed ones)
|
|
1749
|
+
symtest run config.json --error-analysis-all
|
|
1750
|
+
```
|
|
1751
|
+
|
|
1752
|
+
When enabled, each **passed** case lists the above statistics in the Detailed Results section as `error_stats:`. For passed cases the statistics are also written to the `assertion_results[].error_stats` field of the `--output json` report for programmatic consumption. Statistics for passed cases are produced only when `--error-analysis-all` is enabled; otherwise behavior is unchanged.
|
|
1744
1753
|
|
|
1745
1754
|
**CLI Usage**:
|
|
1746
1755
|
|
|
@@ -1748,6 +1757,9 @@ Statistics are computed **in streaming fashion**, independent of the difference
|
|
|
1748
1757
|
# Enable error analysis
|
|
1749
1758
|
symtest run config.json --error-analysis
|
|
1750
1759
|
|
|
1760
|
+
# Enable error analysis and also output statistics for passed cases
|
|
1761
|
+
symtest run config.json --error-analysis-all
|
|
1762
|
+
|
|
1751
1763
|
# Combine with comparison parameters
|
|
1752
1764
|
symtest run config.json --error-analysis --csv-rtol 1e-4 --csv-data-filter '>0'
|
|
1753
1765
|
```
|
|
@@ -2003,8 +2015,8 @@ comparator = ComparatorFactory.create_comparator("foo")
|
|
|
2003
2015
|
```json
|
|
2004
2016
|
{
|
|
2005
2017
|
"type": "hourglass_tangent",
|
|
2006
|
-
"script": "case/.../
|
|
2007
|
-
"case_dir": "case/.../
|
|
2018
|
+
"script": "case/.../analyze_case01_tangent.py",
|
|
2019
|
+
"case_dir": "case/.../case01",
|
|
2008
2020
|
"pass_threshold": 1e-6,
|
|
2009
2021
|
"timeout": 600
|
|
2010
2022
|
}
|
|
@@ -2081,9 +2093,9 @@ python tests/run_all.py --scope unit --extra "-v -k assertions"
|
|
|
2081
2093
|
|
|
2082
2094
|
`--extra` accepts a string that is split via `shlex` and appended to the pytest command line. The script invokes pytest through the current interpreter (`sys.executable -m pytest`), ensuring the activated environment is used rather than the first `pytest` found on PATH.
|
|
2083
2095
|
|
|
2084
|
-
Activate
|
|
2096
|
+
Activate your Python environment (e.g. conda) before running tests:
|
|
2085
2097
|
|
|
2086
2098
|
```bash
|
|
2087
|
-
conda activate
|
|
2099
|
+
conda activate <your-env>
|
|
2088
2100
|
python tests/run_all.py
|
|
2089
2101
|
```
|
|
@@ -130,6 +130,9 @@ Examples:
|
|
|
130
130
|
help='Enable streaming error statistics for numerical file comparisons '
|
|
131
131
|
'(CSV/H5): total_numeric_cells, mismatched_cells, '
|
|
132
132
|
'max_abs/rel_error, mean/rms_abs_error')
|
|
133
|
+
run_parser.add_argument('--error-analysis-all', action='store_true',
|
|
134
|
+
help='Like --error-analysis, but also report error statistics for '
|
|
135
|
+
'PASSED file comparisons in the report (implies --error-analysis)')
|
|
133
136
|
run_parser.add_argument('--plugin-dir', action='append', default=None,
|
|
134
137
|
dest='plugin_dirs',
|
|
135
138
|
help='Add a directory for workspace-level comparator plugins '
|
|
@@ -273,6 +276,9 @@ def run_tests(args):
|
|
|
273
276
|
update_baseline = getattr(args, 'update_baseline', False)
|
|
274
277
|
update_history = getattr(args, 'update_history', False)
|
|
275
278
|
error_analysis = getattr(args, 'error_analysis', False)
|
|
279
|
+
error_analysis_all = getattr(args, 'error_analysis_all', False)
|
|
280
|
+
if error_analysis_all:
|
|
281
|
+
error_analysis = True
|
|
276
282
|
last_failed = getattr(args, 'last_failed', False)
|
|
277
283
|
resume = getattr(args, 'resume', False)
|
|
278
284
|
plugin_dirs = getattr(args, 'plugin_dirs', None)
|
|
@@ -294,6 +300,7 @@ def run_tests(args):
|
|
|
294
300
|
update_baseline=update_baseline,
|
|
295
301
|
update_history=update_history,
|
|
296
302
|
error_analysis=error_analysis,
|
|
303
|
+
error_analysis_all=error_analysis_all,
|
|
297
304
|
last_failed=last_failed,
|
|
298
305
|
resume=resume,
|
|
299
306
|
plugin_dirs=plugin_dirs,
|
|
@@ -312,6 +319,7 @@ def run_tests(args):
|
|
|
312
319
|
update_baseline=update_baseline,
|
|
313
320
|
update_history=update_history,
|
|
314
321
|
error_analysis=error_analysis,
|
|
322
|
+
error_analysis_all=error_analysis_all,
|
|
315
323
|
last_failed=last_failed,
|
|
316
324
|
resume=resume,
|
|
317
325
|
plugin_dirs=plugin_dirs,
|
|
@@ -333,6 +341,7 @@ def run_tests(args):
|
|
|
333
341
|
update_baseline=update_baseline,
|
|
334
342
|
update_history=update_history,
|
|
335
343
|
error_analysis=error_analysis,
|
|
344
|
+
error_analysis_all=error_analysis_all,
|
|
336
345
|
last_failed=last_failed,
|
|
337
346
|
resume=resume,
|
|
338
347
|
plugin_dirs=plugin_dirs,
|
|
@@ -349,6 +358,7 @@ def run_tests(args):
|
|
|
349
358
|
update_baseline=update_baseline,
|
|
350
359
|
update_history=update_history,
|
|
351
360
|
error_analysis=error_analysis,
|
|
361
|
+
error_analysis_all=error_analysis_all,
|
|
352
362
|
last_failed=last_failed,
|
|
353
363
|
resume=resume,
|
|
354
364
|
plugin_dirs=plugin_dirs,
|
|
@@ -23,6 +23,7 @@ class BaseRunner(ABC):
|
|
|
23
23
|
update_baseline: bool = False,
|
|
24
24
|
update_history: bool = False,
|
|
25
25
|
error_analysis: bool = False,
|
|
26
|
+
error_analysis_all: bool = False,
|
|
26
27
|
last_failed: bool = False,
|
|
27
28
|
resume: bool = False,
|
|
28
29
|
plugin_dirs: Optional[List[str]] = None):
|
|
@@ -45,7 +46,8 @@ class BaseRunner(ABC):
|
|
|
45
46
|
self.regression_threshold = regression_threshold
|
|
46
47
|
self.update_baseline = update_baseline
|
|
47
48
|
self.update_history = update_history
|
|
48
|
-
self.error_analysis = error_analysis
|
|
49
|
+
self.error_analysis = error_analysis or error_analysis_all
|
|
50
|
+
self.error_analysis_all = error_analysis_all
|
|
49
51
|
self.last_failed = last_failed
|
|
50
52
|
self.resume = resume
|
|
51
53
|
|
|
@@ -62,6 +64,7 @@ class BaseRunner(ABC):
|
|
|
62
64
|
"xfailed": 0,
|
|
63
65
|
"xpassed": 0,
|
|
64
66
|
"updated": 0,
|
|
67
|
+
"error_analysis_all": error_analysis_all,
|
|
65
68
|
"details": []
|
|
66
69
|
}
|
|
67
70
|
self.assertions = Assertions()
|
|
@@ -294,6 +294,7 @@ def _dispatch_file_compare(
|
|
|
294
294
|
return {
|
|
295
295
|
"assertion": "compare_files",
|
|
296
296
|
"passed": True,
|
|
297
|
+
"error_stats": cf_result.get("error_stats"),
|
|
297
298
|
"compare_failures": [],
|
|
298
299
|
"baseline_updated": [baseline_path],
|
|
299
300
|
"message": "",
|
|
@@ -301,6 +302,7 @@ def _dispatch_file_compare(
|
|
|
301
302
|
return {
|
|
302
303
|
"assertion": "compare_files",
|
|
303
304
|
"passed": True,
|
|
305
|
+
"error_stats": cf_result.get("error_stats"),
|
|
304
306
|
"compare_failures": [],
|
|
305
307
|
"baseline_updated": [],
|
|
306
308
|
"message": "",
|
|
@@ -325,7 +327,9 @@ def _execute_command_once(
|
|
|
325
327
|
output_max_chars: int = DEFAULT_OUTPUT_MAX_CHARS,
|
|
326
328
|
) -> TestResultData:
|
|
327
329
|
"""Execute a single command once (no retry logic)."""
|
|
328
|
-
|
|
330
|
+
# perf_counter: high-resolution monotonic clock; on Windows, time.time()
|
|
331
|
+
# has ~15.6ms granularity and can yield duration == 0.0 for fast commands.
|
|
332
|
+
start_time = time.perf_counter()
|
|
329
333
|
cmd_list = _normalize_cmd_list(case["command"], [str(arg) for arg in case["args"]])
|
|
330
334
|
timeout_limit = case.get("timeout", 3600)
|
|
331
335
|
|
|
@@ -434,7 +438,7 @@ def _execute_command_once(
|
|
|
434
438
|
result["failure_kind"] = "execution_error"
|
|
435
439
|
result["next_action_hint"] = _build_next_action_hint("execution_error")
|
|
436
440
|
finally:
|
|
437
|
-
result["duration"] = time.
|
|
441
|
+
result["duration"] = time.perf_counter() - start_time
|
|
438
442
|
|
|
439
443
|
return result
|
|
440
444
|
|
|
@@ -95,10 +95,11 @@ class ParallelRunner(BaseRunner):
|
|
|
95
95
|
**kwargs: 透传给 BaseRunner 的额外参数
|
|
96
96
|
(test_case_filter, test_case_tag_filter, history_dir, regression_threshold)
|
|
97
97
|
"""
|
|
98
|
+
error_analysis_all = kwargs.get('error_analysis_all', False)
|
|
98
99
|
super().__init__(config_file, workspace, **kwargs)
|
|
99
100
|
self.max_workers = max_workers
|
|
100
101
|
self.execution_mode = execution_mode
|
|
101
|
-
self.error_analysis = error_analysis
|
|
102
|
+
self.error_analysis = error_analysis or error_analysis_all
|
|
102
103
|
self.lock = threading.Lock() # 用于线程安全的结果更新
|
|
103
104
|
|
|
104
105
|
def run_tests(self) -> bool:
|
|
@@ -10,10 +10,11 @@
|
|
|
10
10
|
|
|
11
11
|
import csv
|
|
12
12
|
import io
|
|
13
|
-
import math
|
|
14
13
|
import re
|
|
14
|
+
import numpy as np
|
|
15
15
|
from .text_comparator import TextComparator
|
|
16
16
|
from .result import Difference
|
|
17
|
+
from .numeric_compare import compare_numeric, parse_data_filter
|
|
17
18
|
|
|
18
19
|
class CsvComparator(TextComparator):
|
|
19
20
|
"""
|
|
@@ -107,16 +108,13 @@ class CsvComparator(TextComparator):
|
|
|
107
108
|
differences = []
|
|
108
109
|
max_diffs = 10
|
|
109
110
|
|
|
110
|
-
# ──
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
max_rel_error = None
|
|
118
|
-
max_rel_error_at = None
|
|
119
|
-
|
|
111
|
+
# ── Numeric core accumulators ──
|
|
112
|
+
# error_analysis mode collects ALL filtered numeric cells (matching or not)
|
|
113
|
+
# and delegates statistics to the shared numeric core.
|
|
114
|
+
stats_exp = []
|
|
115
|
+
stats_act = []
|
|
116
|
+
stats_pos = [] # (row, col) 0-based, aligned with stats_exp/stats_act
|
|
117
|
+
|
|
120
118
|
# Check row count
|
|
121
119
|
if len(content1) != len(content2):
|
|
122
120
|
differences.append(Difference(
|
|
@@ -140,42 +138,65 @@ class CsvComparator(TextComparator):
|
|
|
140
138
|
if not self.error_analysis and len(differences) >= max_diffs:
|
|
141
139
|
break
|
|
142
140
|
|
|
143
|
-
#
|
|
141
|
+
# Collect numeric cells in this row (for delegated closeness check)
|
|
142
|
+
row_exp = []
|
|
143
|
+
row_act = []
|
|
144
|
+
row_pos = [] # (row, col) 0-based
|
|
144
145
|
for j, (cell1, cell2) in enumerate(zip(row1, row2)):
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
146
|
+
num1 = num2 = None
|
|
147
|
+
try:
|
|
148
|
+
num1 = float(cell1)
|
|
149
|
+
num2 = float(cell2)
|
|
150
|
+
except (ValueError, TypeError):
|
|
151
|
+
pass # Non-numeric
|
|
152
|
+
|
|
153
|
+
is_numeric = num1 is not None and num2 is not None
|
|
154
|
+
passes_filter = True
|
|
155
|
+
if is_numeric and self.filter_func:
|
|
156
|
+
# vectorized filter applied element-wise on scalar input
|
|
157
|
+
if not (bool(self.filter_func(np.asarray(num1))) and
|
|
158
|
+
bool(self.filter_func(np.asarray(num2)))):
|
|
159
|
+
passes_filter = False
|
|
160
|
+
|
|
161
|
+
if is_numeric and passes_filter:
|
|
162
|
+
# Counted as a numeric cell (regardless of text equality)
|
|
163
|
+
row_exp.append(num1)
|
|
164
|
+
row_act.append(num2)
|
|
165
|
+
row_pos.append((i, j))
|
|
166
|
+
if self.error_analysis:
|
|
167
|
+
stats_exp.append(num1)
|
|
168
|
+
stats_act.append(num2)
|
|
169
|
+
stats_pos.append((i, j))
|
|
170
|
+
|
|
171
|
+
if cell1 == cell2:
|
|
172
|
+
continue
|
|
173
|
+
if is_numeric:
|
|
174
|
+
# Numeric cell: within-tolerance decisions are made below via the core.
|
|
175
|
+
# Filtered-out numeric cells are skipped entirely (no difference).
|
|
176
|
+
continue
|
|
177
|
+
|
|
178
|
+
# Non-numeric text mismatch
|
|
179
|
+
if len(differences) < max_diffs:
|
|
180
|
+
differences.append(Difference(
|
|
181
|
+
position=f"row {i+1}, column {j+1}",
|
|
182
|
+
expected=cell1,
|
|
183
|
+
actual=cell2,
|
|
184
|
+
diff_type="cell_mismatch"
|
|
185
|
+
))
|
|
186
|
+
|
|
187
|
+
# Determine closeness for this row's numeric cells via the shared core.
|
|
188
|
+
if row_exp:
|
|
189
|
+
row_res = compare_numeric(
|
|
190
|
+
row_exp, row_act, rtol=self.rtol, atol=self.atol,
|
|
191
|
+
filter_func=self.filter_func, collect_stats=False,
|
|
192
|
+
)
|
|
193
|
+
for k, is_mismatch in enumerate(row_res.mismatch_mask):
|
|
194
|
+
if is_mismatch and len(differences) < max_diffs:
|
|
195
|
+
ri, cj = row_pos[k]
|
|
175
196
|
differences.append(Difference(
|
|
176
|
-
position=f"row {
|
|
177
|
-
expected=
|
|
178
|
-
actual=
|
|
197
|
+
position=f"row {ri+1}, column {cj+1}",
|
|
198
|
+
expected=content1[ri][cj],
|
|
199
|
+
actual=content2[ri][cj],
|
|
179
200
|
diff_type="cell_mismatch"
|
|
180
201
|
))
|
|
181
202
|
|
|
@@ -184,17 +205,31 @@ class CsvComparator(TextComparator):
|
|
|
184
205
|
|
|
185
206
|
truncated = len(differences) >= max_diffs
|
|
186
207
|
|
|
187
|
-
# ── Store error stats ──
|
|
188
|
-
if self.error_analysis and
|
|
208
|
+
# ── Store error stats via the shared numeric core ──
|
|
209
|
+
if self.error_analysis and stats_exp:
|
|
210
|
+
res = compare_numeric(
|
|
211
|
+
stats_exp, stats_act, rtol=self.rtol, atol=self.atol,
|
|
212
|
+
filter_func=self.filter_func, collect_stats=True,
|
|
213
|
+
)
|
|
214
|
+
max_abs_error = res.max_abs_error
|
|
215
|
+
max_rel_error = res.max_rel_error
|
|
216
|
+
max_abs_error_at = None
|
|
217
|
+
max_rel_error_at = None
|
|
218
|
+
if max_abs_error is not None:
|
|
219
|
+
ri, cj = stats_pos[res.max_abs_error_index]
|
|
220
|
+
max_abs_error_at = f"row {ri+1}, column {cj+1}"
|
|
221
|
+
if max_rel_error is not None:
|
|
222
|
+
ri, cj = stats_pos[res.max_rel_error_index]
|
|
223
|
+
max_rel_error_at = f"row {ri+1}, column {cj+1}"
|
|
189
224
|
self._error_stats = {
|
|
190
|
-
"total_numeric_cells":
|
|
191
|
-
"mismatched_cells":
|
|
225
|
+
"total_numeric_cells": res.total,
|
|
226
|
+
"mismatched_cells": res.mismatched,
|
|
192
227
|
"max_abs_error": max_abs_error,
|
|
193
228
|
"max_abs_error_at": max_abs_error_at,
|
|
194
229
|
"max_rel_error": max_rel_error,
|
|
195
230
|
"max_rel_error_at": max_rel_error_at,
|
|
196
|
-
"mean_abs_error":
|
|
197
|
-
"rms_abs_error":
|
|
231
|
+
"mean_abs_error": res.mean_abs_error,
|
|
232
|
+
"rms_abs_error": res.rms_abs_error,
|
|
198
233
|
}
|
|
199
234
|
|
|
200
235
|
if not differences:
|
|
@@ -202,40 +237,5 @@ class CsvComparator(TextComparator):
|
|
|
202
237
|
return False, differences, truncated
|
|
203
238
|
|
|
204
239
|
def _parse_filter(self):
|
|
205
|
-
"""Parse data filter string and return a
|
|
206
|
-
|
|
207
|
-
return None
|
|
208
|
-
self.logger.debug(f"Parsing data filter: {self.data_filter}")
|
|
209
|
-
try:
|
|
210
|
-
match = re.match(
|
|
211
|
-
r"^(abs)?([><]=?|==)([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?)$",
|
|
212
|
-
self.data_filter.replace(" ", ""),
|
|
213
|
-
)
|
|
214
|
-
if not match:
|
|
215
|
-
self.logger.warning(
|
|
216
|
-
f"Invalid data filter format: {self.data_filter}. Ignoring filter."
|
|
217
|
-
)
|
|
218
|
-
return None
|
|
219
|
-
use_abs, op, value_str = match.groups()
|
|
220
|
-
value = float(value_str)
|
|
221
|
-
op_map = {
|
|
222
|
-
">": lambda x: x > value,
|
|
223
|
-
">=": lambda x: x >= value,
|
|
224
|
-
"<": lambda x: x < value,
|
|
225
|
-
"<=": lambda x: x <= value,
|
|
226
|
-
"==": lambda x: x == value,
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
def filter_func(x):
|
|
230
|
-
target = abs(x) if use_abs else x
|
|
231
|
-
return op_map[op](target)
|
|
232
|
-
|
|
233
|
-
self.logger.debug(
|
|
234
|
-
f"Created filter function for pattern: {use_abs or ''}{op}{value}"
|
|
235
|
-
)
|
|
236
|
-
return filter_func
|
|
237
|
-
except Exception as e:
|
|
238
|
-
self.logger.error(
|
|
239
|
-
f"Failed to parse data filter '{self.data_filter}': {e}. Ignoring filter."
|
|
240
|
-
)
|
|
241
|
-
return None
|
|
240
|
+
"""Parse data filter string and return a filter function (delegates to numeric core)"""
|
|
241
|
+
return parse_data_filter(self.data_filter, logger=self.logger)
|