symtest-cli 1.3.3__tar.gz → 1.4.0__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.3/src/symtest_cli.egg-info → symtest_cli-1.4.0}/PKG-INFO +1 -1
- symtest_cli-1.4.0/docs/design.md +388 -0
- symtest_cli-1.4.0/docs/design_1_4.md +305 -0
- symtest_cli-1.4.0/docs/design_en.md +414 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/docs/user_manual.md +179 -128
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/docs/user_manual_en.md +179 -128
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/__init__.py +2 -2
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/cli.py +30 -0
- symtest_cli-1.4.0/src/symtest/commands/migrate.py +63 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/config/config_io.py +40 -16
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/config/config_schema.py +92 -71
- symtest_cli-1.4.0/src/symtest/config/migrate.py +95 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/core/__init__.py +1 -1
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/core/base_runner.py +2 -3
- symtest_cli-1.4.0/src/symtest/core/config_loader.py +204 -0
- symtest_cli-1.4.0/src/symtest/core/execution/__init__.py +16 -0
- symtest_cli-1.4.0/src/symtest/core/execution/executor.py +153 -0
- symtest_cli-1.4.0/src/symtest/core/execution/result.py +24 -0
- symtest_cli-1.4.0/src/symtest/core/orchestration/__init__.py +17 -0
- symtest_cli-1.4.0/src/symtest/core/orchestration/accept.py +91 -0
- symtest_cli-1.3.3/src/symtest/core/config_loader.py → symtest_cli-1.4.0/src/symtest/core/orchestration/sequence.py +91 -219
- symtest_cli-1.4.0/src/symtest/core/orchestration/single.py +187 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/core/parallel_runner.py +7 -42
- symtest_cli-1.4.0/src/symtest/core/process_worker.py +109 -0
- symtest_cli-1.4.0/src/symtest/core/result.py +68 -0
- symtest_cli-1.4.0/src/symtest/core/test_case.py +290 -0
- symtest_cli-1.4.0/src/symtest/core/validation/__init__.py +15 -0
- {symtest_cli-1.3.3/src/symtest/core → symtest_cli-1.4.0/src/symtest/core/validation}/assertions.py +18 -29
- symtest_cli-1.4.0/src/symtest/core/validation/result.py +19 -0
- symtest_cli-1.4.0/src/symtest/core/validation/validator.py +199 -0
- symtest_cli-1.4.0/src/symtest/reporting/__init__.py +10 -0
- symtest_cli-1.4.0/src/symtest/reporting/diagnosis.py +84 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/runners/config_runner.py +5 -4
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/runners/parallel_config_runner.py +7 -5
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/tui/controllers/case_controller.py +10 -6
- {symtest_cli-1.3.3 → symtest_cli-1.4.0/src/symtest_cli.egg-info}/PKG-INFO +1 -1
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest_cli.egg-info/SOURCES.txt +41 -2
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/e2e/test_user_flows.py +12 -6
- symtest_cli-1.4.0/tests/fixtures/inheritance_base.json +33 -0
- symtest_cli-1.4.0/tests/fixtures/inheritance_chain.json +41 -0
- symtest_cli-1.4.0/tests/fixtures/main_config.json +26 -0
- symtest_cli-1.4.0/tests/fixtures/migration/v1/circular_config_a.json +7 -0
- symtest_cli-1.4.0/tests/fixtures/migration/v1/circular_config_b.json +7 -0
- symtest_cli-1.4.0/tests/fixtures/migration/v1/inheritance_circular.json +16 -0
- symtest_cli-1.4.0/tests/fixtures/migration/v1/skill_test_cases_golden_file.json +33 -0
- symtest_cli-1.4.0/tests/fixtures/migration/v1/skill_test_cases_simple.json +16 -0
- symtest_cli-1.4.0/tests/fixtures/migration/v1/skill_test_cases_simple.yaml +11 -0
- symtest_cli-1.4.0/tests/fixtures/migration/v1/skill_test_cases_steps.json +29 -0
- symtest_cli-1.4.0/tests/fixtures/missing_fields.json +26 -0
- symtest_cli-1.4.0/tests/fixtures/setup_main.json +13 -0
- symtest_cli-1.4.0/tests/fixtures/setup_sub.json +20 -0
- symtest_cli-1.4.0/tests/fixtures/sub_json_tests.yaml +29 -0
- symtest_cli-1.4.0/tests/fixtures/sub_text_tests.json +26 -0
- symtest_cli-1.4.0/tests/fixtures/test_cases.json +69 -0
- symtest_cli-1.4.0/tests/fixtures/test_cases.yaml +11 -0
- symtest_cli-1.4.0/tests/fixtures/test_cases1.json +212 -0
- symtest_cli-1.4.0/tests/fixtures/test_with_setup.json +48 -0
- symtest_cli-1.4.0/tests/fixtures/test_with_setup.yaml +45 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/parallel/test_depends_on.py +41 -33
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/parallel/test_parallel_runner.py +12 -12
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/path_handling/test_spaces_in_paths.py +19 -14
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/test_history_feature.py +8 -10
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/test_new_cli_features.py +28 -10
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/test_real_command_execution.py +17 -9
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/test_sequence.py +56 -42
- symtest_cli-1.4.0/tests/unit/core/test_architecture_guard.py +106 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_assertions.py +45 -40
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_case_env.py +68 -51
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_config_loader.py +134 -78
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_config_loader_new_features.py +53 -50
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_execution.py +22 -26
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_execution_new_features.py +61 -77
- symtest_cli-1.4.0/tests/unit/core/test_model_v2.py +310 -0
- symtest_cli-1.4.0/tests/unit/core/test_orchestration_accept.py +183 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_process_worker.py +45 -45
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_setup.py +6 -6
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_validation_error.py +74 -63
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/test_json_yaml_runner.py +6 -6
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/test_test_case_filter.py +6 -6
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/test_test_case_tag_filter.py +9 -9
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/test_config_io.py +36 -21
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/test_import_expander.py +2 -2
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/test_inheritance_expander.py +4 -4
- symtest_cli-1.4.0/tests/unit/test_migrate.py +295 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/conftest.py +8 -8
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/test_case_controller.py +27 -19
- symtest_cli-1.3.3/docs/design.md +0 -840
- symtest_cli-1.3.3/docs/design_en.md +0 -838
- symtest_cli-1.3.3/src/symtest/core/execution.py +0 -508
- symtest_cli-1.3.3/src/symtest/core/process_worker.py +0 -95
- symtest_cli-1.3.3/src/symtest/core/test_case.py +0 -121
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/LICENSE +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/MANIFEST.in +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/README.md +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/docs/tui_and_config_split_design.md +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/pyproject.toml +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/setup.cfg +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/setup.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/commands/__init__.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/commands/compare.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/config/__init__.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/config/import_expander.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/config/inheritance_expander.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/core/history_store.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/core/last_run_store.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/core/sequence_state.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/core/setup.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/core/types.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/file_comparator/__init__.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/file_comparator/base_comparator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/file_comparator/binary_comparator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/file_comparator/csv_comparator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/file_comparator/factory.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/file_comparator/h5_comparator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/file_comparator/json_comparator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/file_comparator/numeric_compare.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/file_comparator/result.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/file_comparator/script_comparator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/file_comparator/text_comparator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/file_comparator/xml_comparator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/logging_config.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/runners/__init__.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/runners/json_runner.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/runners/parallel_json_runner.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/runners/parallel_yaml_runner.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/runners/yaml_runner.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/tui/__init__.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/tui/app.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/tui/controllers/__init__.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/tui/screens/__init__.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/tui/screens/case_editor.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/tui/screens/case_list.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/tui/widgets/__init__.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/tui/widgets/case_table.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/tui/widgets/expected_editor.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/tui/widgets/search_bar.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/tui/widgets/steps_editor.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/utils/__init__.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/utils/junit_xml_writer.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/utils/path_resolver.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest/utils/report_generator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest_cli.egg-info/dependency_links.txt +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest_cli.egg-info/entry_points.txt +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest_cli.egg-info/requires.txt +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/src/symtest_cli.egg-info/top_level.txt +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/README.md +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/__init__.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/__pycache__/__init__.cpython-313.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/__pycache__/__init__.cpython-39.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/__pycache__/conftest.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/__pycache__/conftest.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/__pycache__/conftest.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/__pycache__/run_all.cpython-312.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/__pycache__/run_all.cpython-313.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/__pycache__/run_all.cpython-39.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/__pycache__/test_setup_module.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/conftest.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/demos/h5_filter_demo.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/demos/manual_report_example.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/demos/perf_parallel.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/e2e/__init__.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/e2e/__pycache__/__init__.cpython-312.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/e2e/__pycache__/__init__.cpython-313.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/e2e/__pycache__/__init__.cpython-39.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/e2e/__pycache__/test_user_flows.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/e2e/__pycache__/test_user_flows.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/e2e/__pycache__/test_user_flows.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/e2e/__pycache__/test_user_flows.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/fixtures/circular_config_a.json +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/fixtures/circular_config_b.json +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/fixtures/hourglass_stdout_mismatch.txt +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/fixtures/hourglass_stdout_sample.txt +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/fixtures/inheritance_circular.json +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/inheritance_base.json +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/inheritance_chain.json +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/main_config.json +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/missing_fields.json +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/setup_main.json +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/setup_sub.json +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/sub_json_tests.yaml +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/sub_text_tests.json +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/test_cases.json +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/test_cases.yaml +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/test_cases1.json +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/test_with_setup.json +0 -0
- {symtest_cli-1.3.3/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/test_with_setup.yaml +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/fixtures/mock_fail_script.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/fixtures/mock_pass_script.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_history_feature.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_history_feature.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_history_feature.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_new_cli_features.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_new_cli_features.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_new_cli_features.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_real_command_execution.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_real_command_execution.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_real_command_execution.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_sequence.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_sequence.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_sequence.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/test_binary_compare.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/test_csv_compare.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/test_h5_compare.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/test_json_compare.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/test_text_compare.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/file_compare/test_xml_compare.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/parallel/__pycache__/test_depends_on.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/parallel/__pycache__/test_depends_on.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/run_all.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_binary_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_binary_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_binary_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_cli.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_cli.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_config_io.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_config_io.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_config_io.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_h5_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_h5_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_h5_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_import_expander.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_import_expander.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_import_expander.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_inheritance_expander.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_inheritance_expander.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_inheritance_expander.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_migrate.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_result.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_result.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_result.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_run_all.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_run_all.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_run_all.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/commands/__pycache__/test_compare_command.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/commands/__pycache__/test_compare_command.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/commands/__pycache__/test_compare_command.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/commands/test_compare_command.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_architecture_guard.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_architecture_guard.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_assertions.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_assertions.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_assertions.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_case_env.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_case_env.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_config_loader.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_config_loader.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_config_loader.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution.cpython-312.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution_new_features.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution_new_features.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution_new_features.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_history_store.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_history_store.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_history_store.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_last_run_store.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_last_run_store.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_last_run_store.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_model_v2.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_model_v2.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_orchestration_accept.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_orchestration_accept.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_process_worker.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_process_worker.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_process_worker.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_sequence_state.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_sequence_state.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_setup.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_setup.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_setup.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_setup.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_validation_error.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_validation_error.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_validation_error.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_xfail.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_xfail.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_xfail.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_history_store.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_last_run_store.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_sequence_state.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/core/test_xfail.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/__init__.cpython-312.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_error_analysis.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_error_analysis.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_error_analysis.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_hourglass_tangent_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_hourglass_tangent_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_hourglass_tangent_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_numeric_compare.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_numeric_compare.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_numeric_parity.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_numeric_parity.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_script_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_script_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_script_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_workspace_plugins.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_workspace_plugins.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_workspace_plugins.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/test_error_analysis.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/test_hourglass_tangent_comparator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/test_numeric_compare.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/test_numeric_parity.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/test_script_comparator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/file_comparator/test_workspace_plugins.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-39-pytest-8.3.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/test_binary_comparator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/test_cli.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/test_h5_comparator.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/test_result.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/test_run_all.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__init__.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/__init__.cpython-312.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/__init__.cpython-313.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/conftest.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/conftest.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_app.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_app.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_app.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_case_controller.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_case_controller.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_case_controller.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_search_functions.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_search_functions.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_search_functions.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_tui_run_test.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_tui_run_test.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_tui_run_test.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_widgets_data.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_widgets_data.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_widgets_data.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/test_app.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/test_search_functions.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/test_tui_run_test.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/tui/test_widgets_data.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/utils/__pycache__/test_report_generator.cpython-312-pytest-7.4.4.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/utils/__pycache__/test_report_generator.cpython-312-pytest-9.0.3.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/utils/__pycache__/test_report_generator.cpython-313-pytest-9.0.2.pyc +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/utils/test_junit_xml_writer.py +0 -0
- {symtest_cli-1.3.3 → symtest_cli-1.4.0}/tests/unit/utils/test_report_generator.py +0 -0
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
# CLI Test Framework 设计文档
|
|
2
|
+
|
|
3
|
+
> **维护原则(单一事实来源)**:本文档不镜像代码结构——不再维护目录树、类签名、
|
|
4
|
+
> 函数清单、dataclass 字段定义等会随代码漂移的内容。目录结构与 API 以
|
|
5
|
+
> `src/symtest/` 源码及其 docstring 为准,用法示例见 `examples/`。
|
|
6
|
+
> 本文档只承载代码里读不出来的设计信息:架构分层、职责边界、关键流程语义、
|
|
7
|
+
> 扩展契约、设计决策与核心架构宪法。
|
|
8
|
+
|
|
9
|
+
## 1. 架构总览
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
13
|
+
│ CLI 入口层 symtest run / tui / validate / schema / │
|
|
14
|
+
│ compare-files(+ TUI 交互界面) │
|
|
15
|
+
└───────────────────────────┬─────────────────────────────────┘
|
|
16
|
+
▼
|
|
17
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
18
|
+
│ 业务层 Runners(顺序 / 并行 / DAG / 资源感知) │
|
|
19
|
+
│ File Comparators(多类型 + 插件) │
|
|
20
|
+
└───────────────────────────┬─────────────────────────────────┘
|
|
21
|
+
▼
|
|
22
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
23
|
+
│ 配置管线 raw JSON/YAML → expand_imports │
|
|
24
|
+
│ → resolve_inheritance → apply_variables │
|
|
25
|
+
│ → substitute_placeholders → parse_test_cases │
|
|
26
|
+
└───────────────────────────┬─────────────────────────────────┘
|
|
27
|
+
▼
|
|
28
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
29
|
+
│ Core 层 TestCase 模型 · 断言引擎 · 单测试执行 │
|
|
30
|
+
│ Runner 基类 · Setup 插件 · .symtest 状态存储 │
|
|
31
|
+
│ 路径解析 · 报告生成 · JUnit XML │
|
|
32
|
+
└─────────────────────────────────────────────────────────────┘
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
框架分为四层:**CLI 入口层**(含 TUI)、**Runner / Comparator 业务层**、**Config 管线层**、**Core 基础层**。
|
|
36
|
+
|
|
37
|
+
层与层不是自由组合:跨层数据流与依赖方向受 §10「核心架构宪法」约束,
|
|
38
|
+
新增 feature 请先对照宪法确定归属。
|
|
39
|
+
|
|
40
|
+
## 2. 模块地图
|
|
41
|
+
|
|
42
|
+
以包为单位的职责划分(文件级明细与公开 API 以源码为准):
|
|
43
|
+
|
|
44
|
+
| 包 | 职责 |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `cli.py` / `commands/` | 子命令入口、参数装配与日志激活 |
|
|
47
|
+
| `core/` | TestCase 数据模型、断言引擎、单测试执行、Runner 基类(顺序 / 并行 / DAG)、`.symtest` 状态存储、Setup 插件体系 |
|
|
48
|
+
| `config/` | 配置 IO、JSON Schema 校验(draft 2020-12)、import 展开、extends 继承、变量与占位符替换 |
|
|
49
|
+
| `runners/` | Config/JSON/YAML × 顺序/并行 的薄封装运行器 |
|
|
50
|
+
| `file_comparator/` | 比较器家族 + 工厂 + workspace 插件发现(详见 §6) |
|
|
51
|
+
| `utils/` | 路径解析、报告生成、JUnit XML 输出 |
|
|
52
|
+
| `tui/` | Textual 交互式用例管理(详见 §7) |
|
|
53
|
+
|
|
54
|
+
### 2.1 入口点
|
|
55
|
+
|
|
56
|
+
| 命令 | 映射 |
|
|
57
|
+
|---|---|
|
|
58
|
+
| `symtest run` | `symtest.cli:run_tests` |
|
|
59
|
+
| `symtest tui` | `symtest.tui.app:run_tui` |
|
|
60
|
+
| `symtest validate` | `symtest.cli:run_validate` |
|
|
61
|
+
| `symtest schema` | `symtest.cli:run_schema` |
|
|
62
|
+
| `symtest compare` | `symtest.cli:run_compare` |
|
|
63
|
+
|
|
64
|
+
## 3. 配置管线
|
|
65
|
+
|
|
66
|
+
配置文件在加载时经过五步管线处理:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
raw JSON/YAML 文件
|
|
70
|
+
│
|
|
71
|
+
▼
|
|
72
|
+
expand_imports() # 递归展开 import 引用(合并 setup、注入 tags)
|
|
73
|
+
│
|
|
74
|
+
▼
|
|
75
|
+
resolve_inheritance() # 解析 extends 继承链(deep-merge、去重 abstract)
|
|
76
|
+
│
|
|
77
|
+
▼
|
|
78
|
+
apply_variables() # 注入 --var 全局变量 + case-level variables
|
|
79
|
+
│
|
|
80
|
+
▼
|
|
81
|
+
substitute_placeholders() # 递归替换 {placeholder} 占位符
|
|
82
|
+
│
|
|
83
|
+
▼
|
|
84
|
+
parse_test_cases() # 转换为 List[TestCase](命令路径解析)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 3.1 Import 展开 (`import_expander.py`)
|
|
88
|
+
|
|
89
|
+
主配置文件通过 `"import"` 引用子配置文件:
|
|
90
|
+
|
|
91
|
+
- 递归展开所有 import,内联到主配置中
|
|
92
|
+
- import 级 tags 注入到被引文件的每个 case
|
|
93
|
+
- setup 深度合并
|
|
94
|
+
- 循环引用检测
|
|
95
|
+
|
|
96
|
+
配置形态与用法示例见 `examples/`。
|
|
97
|
+
|
|
98
|
+
### 3.2 继承展开 (`inheritance_expander.py`)
|
|
99
|
+
|
|
100
|
+
`extends` 字段实现用例模板继承:
|
|
101
|
+
|
|
102
|
+
- 深度合并(dict)/ 整体替换(list)策略
|
|
103
|
+
- `abstract: true` 的模板不参与执行
|
|
104
|
+
- extends 链上的 `variables` 收集后统一替换
|
|
105
|
+
- 循环继承检测
|
|
106
|
+
|
|
107
|
+
### 3.3 配置验证 (`config_io.py`)
|
|
108
|
+
|
|
109
|
+
`symtest validate` 子命令在不执行测试的情况下校验配置:
|
|
110
|
+
|
|
111
|
+
- Error 级(影响 valid):JSON/YAML 语法、必填字段、import 目标存在性、循环引用、extends 目标存在性、循环继承
|
|
112
|
+
- Warning 级(不影响 valid):命令可执行性(PATH 查找)、`compare_files` baseline 文件存在性
|
|
113
|
+
|
|
114
|
+
## 4. 执行语义
|
|
115
|
+
|
|
116
|
+
> 本章只记载跨模块的行为语义约定;类属性、方法签名与默认值以源码为准。
|
|
117
|
+
|
|
118
|
+
### 4.1 Runner 模板与状态映射
|
|
119
|
+
|
|
120
|
+
- 模板流程固定:`load_test_cases()` → 过滤(名称精确 / tags 交集 / `--last-failed`)→ `setup_all()` → 逐 case 执行 → xfail 状态映射 → 历史与 last-run 更新 → `teardown_all()`(逆序,保证出错也继续清理)
|
|
121
|
+
- JSON/YAML Runner 仅注入不同的 config_loader,通用逻辑统一在顺序 / 并行通用运行器中
|
|
122
|
+
- xfail:`expected_failure=True` 时 `passed → xpassed`(意外通过,计入失败);任意非 passed → `xfailed`(预期失败,不计入失败)
|
|
123
|
+
- JUnit XML 状态映射:`xfailed → <skipped>`、`xpassed → <failure>`、`timeout → <error>`、`failed` 按消息类型分 `<failure>` / `<error>`
|
|
124
|
+
- 历史:累计平均更新;写入前先按 `regression_threshold` 与旧均值做回归检测;`--update-history` 清除后重记
|
|
125
|
+
- `--last-failed`:每次运行只覆写本次参与执行的用例状态,子集运行不丢失其余用例状态
|
|
126
|
+
|
|
127
|
+
### 4.2 测试双模式
|
|
128
|
+
|
|
129
|
+
单命令模式(`command + args + expected`)与 steps 序列模式二选一;每个 step 是
|
|
130
|
+
"执行 + 判定"的原子对(command / args / timeout / retry_count / expected)。
|
|
131
|
+
字段全集见 `core/test_case.py` 与 JSON Schema,本文不复述。
|
|
132
|
+
|
|
133
|
+
### 4.3 并行与资源调度
|
|
134
|
+
|
|
135
|
+
- LPT 策略:长任务先行;启用 history 时优先用 `.symtest` 历史 `avg_duration` 排序,其次才看声明的 `estimated_time`
|
|
136
|
+
- `AtomicSemaphore` 资源池:`safe_capacity = max(1, cpu_count − 2)`;每个 case 按 `cpu_cores` acquire/release
|
|
137
|
+
- 按权重比例分配相对 CPU 核数,并自动注入 `OMP_NUM_THREADS` / `MKL_NUM_THREADS` / `NPROC`
|
|
138
|
+
- 环境变量优先级:`os.environ` < 调度器注入 < case 级 env(经 subprocess 注入,不改进程全局环境)
|
|
139
|
+
- 线程模式共享内存 + 结果/打印锁;进程模式经 process worker 隔离;可回退顺序执行
|
|
140
|
+
|
|
141
|
+
### 4.4 DAG 依赖调度语义
|
|
142
|
+
|
|
143
|
+
- `depends_on` 非空自动切换拓扑模式;无依赖时走零开销 fast path
|
|
144
|
+
- Kahn 入度表 + 就绪队列,依赖满足后立即提交后继
|
|
145
|
+
- 依赖"满足" = `passed` 或 `xfailed`;`failed` / `xpassed` 触发 BFS 级联 skip 全部下游
|
|
146
|
+
- `skipped` 不计入 `failed` 计数,报告中单独列出
|
|
147
|
+
- 顺序 runner 同样按拓扑序执行,依赖失效时跳过下游
|
|
148
|
+
|
|
149
|
+
### 4.5 单测试执行
|
|
150
|
+
|
|
151
|
+
PathResolver 解析(系统命令直通、shell builtin 平台包装、复合命令拆分解析)
|
|
152
|
+
→ subprocess 隔离执行(捕获 stdout / stderr / returncode / duration)
|
|
153
|
+
→ 断言校验(return_code / contains / matches / compare_files)
|
|
154
|
+
→ 失败按 `retry_count` 重试
|
|
155
|
+
→ 超时 kill 整个进程组
|
|
156
|
+
→ 返回附带 `next_action_hint` 的结构化结果。
|
|
157
|
+
|
|
158
|
+
当前实现的上述行为仍聚合在一处;1.4 将按 §10 宪法重排为
|
|
159
|
+
Executor / Validator / Orchestration 三段(迁移明细见 docs/design_1_4.md)。
|
|
160
|
+
|
|
161
|
+
### 4.6 断言与文件比较集成
|
|
162
|
+
|
|
163
|
+
- `compare_files` 是一等断言,经 ComparatorFactory 按类型分发(详见 §6)
|
|
164
|
+
- 所有断言可选;未声明的字段不做校验
|
|
165
|
+
- `--error-analysis` 为 CSV/H5 数值比较提供流式误差统计:`total_numeric_cells` / `mismatched_cells` / `max_abs_error` / `max_rel_error` / `mean_abs_error` / `rms_abs_error`
|
|
166
|
+
|
|
167
|
+
## 5. 运行时状态持久化(`.symtest/`)
|
|
168
|
+
|
|
169
|
+
| 状态 | 内容 | 更新时机 / 语义 |
|
|
170
|
+
|---|---|---|
|
|
171
|
+
| 历史记录 | per-case `avg_duration` / `last_duration` / `run_count` | 运行后累计平均更新;先回归检测后写入 |
|
|
172
|
+
| `last_run.json` | case → 上次状态 | 覆写参与执行的用例;未执行的保留旧状态 |
|
|
173
|
+
| `sequence_state/<case>.json` | steps + case expected 的 SHA-256 配置哈希、已通过的 step 集 | 每步 pass 后保存;全部通过后清理 |
|
|
174
|
+
| `sequence_state/cache/*.log` | 步骤输出缓存 | 与上同步;供 resume 拼接复现 |
|
|
175
|
+
|
|
176
|
+
**resume 语义**:`--resume` 比对配置哈希——匹配则跳过已过步骤并拼接缓存输出,
|
|
177
|
+
失配即全量重跑。纯信任模型:不验证 workspace 产物,由用户保证未被修改。
|
|
178
|
+
|
|
179
|
+
## 6. 文件比较子系统
|
|
180
|
+
|
|
181
|
+
### 6.1 比较器分层
|
|
182
|
+
|
|
183
|
+
- 文本系比较器共享 difflib 行级基底,json / csv / xml 为其结构化特化(键对齐 / 列结构 / DOM 对齐)
|
|
184
|
+
- h5 面向科学数据集;binary 流式分块 + LCS 相似度;script 委托外部脚本
|
|
185
|
+
- 统一返回 ComparisonResult(identical / differences / error / script command_output),支持 text / json / html 渲染;支持行列窗口范围参数截取后比较
|
|
186
|
+
|
|
187
|
+
### 6.2 工厂与插件发现
|
|
188
|
+
|
|
189
|
+
- `file_type` 取值:`text` / `json` / `csv` / `xml` / `h5` / `binary` / `script`;工厂按类型分发,支持动态注册与全局 reset(测试用)
|
|
190
|
+
- 插件发现四处来源:内置 `*_comparator.py` 自动发现、`workspace/comparators/` 自动扫描、`--plugin-dir` CLI 参数、`CLITEST_PLUGIN_DIRS` 环境变量(供进程模式 worker 使用)
|
|
191
|
+
- 命名约定:`*_comparator.py` + `*Comparator` 类名
|
|
192
|
+
|
|
193
|
+
### 6.3 script 比较协议(对外契约)
|
|
194
|
+
|
|
195
|
+
- 子进程方式执行 `<interpreter> <script> <actual> <baseline>`
|
|
196
|
+
- 默认 exit code 0 → 通过;可选 `pass_pattern` / `fail_pattern` 正则匹配 stdout 细化判定
|
|
197
|
+
- 超时可配
|
|
198
|
+
|
|
199
|
+
## 7. TUI 子系统
|
|
200
|
+
|
|
201
|
+
基于 Textual 的终端交互界面:App + Controller(load / create / update /
|
|
202
|
+
delete / run_single / save 业务动作)+ 列表 / 编辑两屏 + 表格封装、多模式搜索条
|
|
203
|
+
(名称 / 命令 / 标签)、expected 编辑器、steps 编辑器。
|
|
204
|
+
|
|
205
|
+
快捷键:`q` / Ctrl+Q 退出、`r` 刷新、`e` 编辑、`f` 单跑、`/` 搜索、`a` 新增、`d` 删除、`s` 保存。
|
|
206
|
+
|
|
207
|
+
TUI 与 runner 共用同一解析器;宽松的展示形态在 TUI 侧自行处理(§10 原则 6)。
|
|
208
|
+
|
|
209
|
+
## 8. 扩展点
|
|
210
|
+
|
|
211
|
+
| 扩展点 | 基类 | 用途 |
|
|
212
|
+
|---|---|---|
|
|
213
|
+
| 新配置格式 | `BaseRunner` | 支持新的测试定义格式(如 XML、TOML) |
|
|
214
|
+
| 自定义 Setup | `BaseSetup` | 数据库初始化、服务启停等 |
|
|
215
|
+
| 自定义断言 | 扩展 `Assertions` | 特定业务校验逻辑 |
|
|
216
|
+
| 新比较器 | `BaseComparator` | 支持新的文件格式比较,放入 `comparators/` 目录自动发现 |
|
|
217
|
+
| 新 Runner | `ParallelRunner` / `BaseRunner` | 自定义并行调度策略 |
|
|
218
|
+
| TUI 扩展 | `CaseController` / Widgets | 扩展终端管理界面 |
|
|
219
|
+
|
|
220
|
+
## 9. 设计决策
|
|
221
|
+
|
|
222
|
+
| 决策 | 原因 |
|
|
223
|
+
|---|---|
|
|
224
|
+
| Runner 用模板方法模式 | 统一执行流程(load → filter → setup → run → history → last-run → teardown),子类只需实现配置解析和单测试执行 |
|
|
225
|
+
| Config 管线化处理 | import/extends/variables 正交分解,每步职责单一,可独立测试和组合 |
|
|
226
|
+
| JSON/YAML Runner 统一为 ConfigRunner | 消除代码重复,通过注入 config_loader 适配不同格式 |
|
|
227
|
+
| Setup 逆序 teardown | 类似栈语义,后初始化的依赖先清理 |
|
|
228
|
+
| 信号量管理 CPU 核心 | 比线程池 worker 数更精细,允许不同 case 声明不同核心需求 |
|
|
229
|
+
| LPT 调度策略 | 长任务先启动,减少尾延迟;优先使用 `.symtest` 历史数据 |
|
|
230
|
+
| 累计平均更新历史 | 直觉简单,随运行次数增多单次异常自然稀释 |
|
|
231
|
+
| 回归检测在更新前执行 | 先与旧均值比较再更新,确保对比的是"历史基线" |
|
|
232
|
+
| `.symtest/` 目录 | 不干扰用户目录视图,JSON 格式便于调试;状态文件统一管理 |
|
|
233
|
+
| 环境变量注入 | 科学计算求解器常忽略 Python 级线程控制 |
|
|
234
|
+
| case 级 env 通过 subprocess 注入 | 不改进程全局 `os.environ`,进程隔离、并行线程安全;优先级 `os.environ` < 调度器 < case env |
|
|
235
|
+
| Comparator 工厂 + 插件发现 | 按文件类型创建比较器,workspace `comparators/` 目录自动发现插件 |
|
|
236
|
+
| subprocess 隔离执行 | 每个 test case 独立子进程,保证测试间互不影响 |
|
|
237
|
+
| xfail 机制 | 支持预期失败的测试(CI 中不阻塞流水线),意外通过时告警 |
|
|
238
|
+
| --last-failed 覆写策略 | 只覆写本次执行的用例状态,避免子集运行时丢失未执行用例的状态 |
|
|
239
|
+
| --resume 纯信任模型 | 不验证 artifact,由用户保证 workspace 未被修改,简化实现 |
|
|
240
|
+
| retry_count 重试机制 | 应对偶发性网络抖动或竞态条件,首次失败后自动重试 |
|
|
241
|
+
| DAG 依赖调度 | 基于 Kahn 拓扑 + 就绪队列,依赖满足后立即提交;依赖失败级联 skip 下游;无依赖时走 fast path 零开销 |
|
|
242
|
+
| --update-baseline | 比较失败时自动将实际输出覆盖 baseline,适合批量更新基准 |
|
|
243
|
+
| next_action_hint 结构化建议 | 失败结果附带下一步操作建议(update_baseline / update_expected / increase_timeout / investigate),便于 AI 消费 |
|
|
244
|
+
| TUI 基于 Textual | 利用成熟的终端 UI 框架,提供交互式用例管理 |
|
|
245
|
+
| JUnit XML 输出 | 兼容 GitLab CI / Jenkins / CircleCI 等主流 CI 系统的测试报告格式 |
|
|
246
|
+
| Logging 统一化 | 通过 `logging` 模块集中管理,CLI 入口激活控制台输出,库用户按需启用 |
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## 10. 核心架构宪法
|
|
251
|
+
|
|
252
|
+
> **地位与效力**:本节自 Symtest 1.4 Phase 0 评审定稿,是本项目的核心架构契约,
|
|
253
|
+
> 对所有后续 feature 具有最高约束力——任何功能需求先对照本宪法确定归属,再写代码。
|
|
254
|
+
> 修订宪法必须在变更说明中显式指出所放宽/违反的条款及理由。
|
|
255
|
+
> 定稿前的演进推导见开发阶段文档 docs/design_1_4.md。
|
|
256
|
+
|
|
257
|
+
### 10.1 数据流主线
|
|
258
|
+
|
|
259
|
+
```
|
|
260
|
+
TestCase(specification,永不执行)
|
|
261
|
+
├── ExecutionSpec ──▶ Executor.execute() ──▶ ExecutionResult
|
|
262
|
+
├── ExpectationSpec ─┐
|
|
263
|
+
└── SchedulingSpec ──▶ Orchestration(何时跑、跑哪个、组合与重试)
|
|
264
|
+
│
|
|
265
|
+
Validator.validate(ExpectationSpec, ExecutionResult)
|
|
266
|
+
▼
|
|
267
|
+
ValidationResult ──▶ TestResult ──▶ Reporter
|
|
268
|
+
console / JSON / JUnit / AI diagnosis
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
一次 attempt = `Executor.execute → Validator.validate`;verdict 由编排层聚合为 TestResult。
|
|
272
|
+
|
|
273
|
+
### 10.2 六条原则
|
|
274
|
+
|
|
275
|
+
#### 原则 1 — TestCase 是声明,不执行任何事情
|
|
276
|
+
|
|
277
|
+
`TestCase = specification`。禁止出现 `test_case.run()` / `test_case.validate()` /
|
|
278
|
+
`test_case.update_baseline()` 这类方法;TestCase 只描述**执行什么**
|
|
279
|
+
(ExecutionSpec)、**如何判定**(ExpectationSpec)、**调度约束**
|
|
280
|
+
(SchedulingSpec)与元数据。
|
|
281
|
+
|
|
282
|
+
概念模型分层 ≠ 配置 DSL 必须机械映射类层次:`name/tags/description` 允许保留
|
|
283
|
+
顶层以避免啰嗦;真正必须拆出去的是执行语义、验证语义、调度语义。
|
|
284
|
+
|
|
285
|
+
#### 原则 2 — Execution 不知道"通过/失败"
|
|
286
|
+
|
|
287
|
+
```
|
|
288
|
+
Executor: ExecutionSpec ──execute──▶ ExecutionResult
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
ExecutionResult 只承载执行事实:`return_code / stdout / stderr / duration /
|
|
292
|
+
timed_out / error / artifacts`。
|
|
293
|
+
|
|
294
|
+
Executor 禁止感知:`expected_return_code / output_contains / baseline / rtol /
|
|
295
|
+
file comparison / xfail / next_action_hint`。超时只报告 `timed_out=True`,
|
|
296
|
+
"timeout 是否算失败"由 Validator 判定。
|
|
297
|
+
|
|
298
|
+
#### 原则 3 — Validation 不执行被测程序,且永远只读
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
Validator: ExpectationSpec + ExecutionResult ──validate──▶ ValidationResult
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Validator 禁止 `subprocess.Popen` 被测进程、kill 进程、retry。
|
|
305
|
+
|
|
306
|
+
**例外条款(受控豁免)**:comparator 是验证的内部工具,`script` comparator
|
|
307
|
+
执行的是"比较工具"而非"被测程序",属本条明确豁免范围。
|
|
308
|
+
|
|
309
|
+
**baseline 语义**:Validator 永远只读文件。`--update-baseline` 由 runner 在拿到
|
|
310
|
+
ValidationResult 后执行独立的 accept 步骤(复制 actual → baseline)再判定。
|
|
311
|
+
|
|
312
|
+
#### 原则 4 — Orchestration 组合,而不实现底层语义
|
|
313
|
+
|
|
314
|
+
Runner / Scheduler / DAG / ParallelRunner 负责:什么时候执行、执行哪个 case、
|
|
315
|
+
顺序、依赖、并发、**retry policy**(一次 attempt =
|
|
316
|
+
`Executor.execute → Validator.validate`,runner 拿 verdict 决定是否重跑,
|
|
317
|
+
flaky 判定也在编排层);但不自己实现 subprocess 管理、float 比较、stdout 判断。
|
|
318
|
+
|
|
319
|
+
#### 原则 5 — Reporting 只能消费 Result
|
|
320
|
+
|
|
321
|
+
```
|
|
322
|
+
TestResult ──▶ Reporter ──┬── console
|
|
323
|
+
├── JSON
|
|
324
|
+
├── JUnit
|
|
325
|
+
└── AI diagnosis
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Reporter 的合法输入只能是 Result 类型;`next_action_hint` 属于 result consumer
|
|
329
|
+
(diagnosis),不得存在于 execution 层。
|
|
330
|
+
|
|
331
|
+
#### 原则 6 — 核心模型不依赖表现层
|
|
332
|
+
|
|
333
|
+
`core` 绝对不能 import:`cli` / `tui` / `reporter` / AI-specific adapter。
|
|
334
|
+
|
|
335
|
+
解析器全系统唯一:TUI 与 runner 使用同一 parser,不允许存在 "TUI mode 后门"
|
|
336
|
+
(如 workspace=None 时放宽校验);宽松形态由 TUI 侧自行处理。
|
|
337
|
+
|
|
338
|
+
### 10.3 模块依赖方向
|
|
339
|
+
|
|
340
|
+
允许:
|
|
341
|
+
|
|
342
|
+
- `orchestration` import `execution` / `validation`(它是唯一组合者);
|
|
343
|
+
- `reporting` 仅 import result 类型
|
|
344
|
+
(ExecutionResult / ValidationResult / TestResult)。
|
|
345
|
+
|
|
346
|
+
禁止:
|
|
347
|
+
|
|
348
|
+
- `execution` 与 `validation` 互不 import;
|
|
349
|
+
- `executor` 不得 import `assertions` / validation 侧模块;
|
|
350
|
+
- `validator` 不得启动被测进程(见原则 3);
|
|
351
|
+
- `core` 不得 import `cli` / `tui` / `reporter`。
|
|
352
|
+
|
|
353
|
+
### 10.4 违宪归属速查
|
|
354
|
+
|
|
355
|
+
任何新需求先问归属:
|
|
356
|
+
|
|
357
|
+
| 提问 | 归属 |
|
|
358
|
+
|---|---|
|
|
359
|
+
| 增加 GPU resource requirement? | SchedulingSpec |
|
|
360
|
+
| 增加 stderr regex assertion? | ExpectationSpec / Validator |
|
|
361
|
+
| 支持 Docker command execution? | Executor |
|
|
362
|
+
| AI 告诉我下一步该干嘛? | Result consumer / diagnosis |
|
|
363
|
+
|
|
364
|
+
判据:若仍经常出现"这个功能到底放 execution、runner 还是 testcase?"的争论,
|
|
365
|
+
说明宪法没有被正确适用,应回到 10.2 逐条对照。
|
|
366
|
+
|
|
367
|
+
### 10.5 宪法可执行化
|
|
368
|
+
|
|
369
|
+
宪法不是纯文档约定,配套 architecture guard 测试并由 CI 强制:
|
|
370
|
+
|
|
371
|
+
- 断言 import 图:如 `execution/executor.py` 的 import 不得出现
|
|
372
|
+
`assertions` / `validation`;`core/**` 不得 import `cli` / `tui` /
|
|
373
|
+
`reporter`;
|
|
374
|
+
- guard 测试纳入常规回归套件(`python tests\run_all.py`),违规即失败;
|
|
375
|
+
- 冲突裁决次序:guard 测试 > 本节文字 > 个人偏好。
|
|
376
|
+
|
|
377
|
+
### 10.6 现状差距与收敛路径
|
|
378
|
+
|
|
379
|
+
定稿时刻(1.4 Phase 0)现行实现与本宪法的已知偏差如下,将在 1.4 对应 Phase 内
|
|
380
|
+
逐项收敛(迁移明细见 docs/design_1_4.md):
|
|
381
|
+
|
|
382
|
+
| 现状 | 违反 | 收敛 |
|
|
383
|
+
|---|---|---|
|
|
384
|
+
| `execution.py::validate_result` 住在执行层 | 原则 2 | Phase 2 迁入 `validation/validator.py` |
|
|
385
|
+
| `next_action_hint` 在 execution 层构造 | 原则 5 | Phase 2 迁入 `reporting/diagnosis.py` |
|
|
386
|
+
| retry 循环在 executor 内部 | 原则 2 / 4 | Phase 2 上移编排层 |
|
|
387
|
+
| Validator 侧 update_baseline 写文件 | 原则 3 | Phase 2 改为 runner 独立 accept 步骤 |
|
|
388
|
+
| `parse_test_cases` TUI mode 后门 | 原则 6 | Phase 2 拆除,单一解析器 |
|