symtest-cli 1.3.2__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.
Files changed (408) hide show
  1. {symtest_cli-1.3.2/src/symtest_cli.egg-info → symtest_cli-1.4.0}/PKG-INFO +1 -1
  2. symtest_cli-1.4.0/docs/design.md +388 -0
  3. symtest_cli-1.4.0/docs/design_1_4.md +305 -0
  4. symtest_cli-1.4.0/docs/design_en.md +414 -0
  5. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/docs/user_manual.md +202 -139
  6. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/docs/user_manual_en.md +202 -139
  7. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/__init__.py +2 -2
  8. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/cli.py +40 -0
  9. symtest_cli-1.4.0/src/symtest/commands/migrate.py +63 -0
  10. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/config/config_io.py +40 -16
  11. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/config/config_schema.py +92 -71
  12. symtest_cli-1.4.0/src/symtest/config/migrate.py +95 -0
  13. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/core/__init__.py +1 -1
  14. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/core/base_runner.py +6 -4
  15. symtest_cli-1.4.0/src/symtest/core/config_loader.py +204 -0
  16. symtest_cli-1.4.0/src/symtest/core/execution/__init__.py +16 -0
  17. symtest_cli-1.4.0/src/symtest/core/execution/executor.py +153 -0
  18. symtest_cli-1.4.0/src/symtest/core/execution/result.py +24 -0
  19. symtest_cli-1.4.0/src/symtest/core/orchestration/__init__.py +17 -0
  20. symtest_cli-1.4.0/src/symtest/core/orchestration/accept.py +91 -0
  21. symtest_cli-1.3.2/src/symtest/core/config_loader.py → symtest_cli-1.4.0/src/symtest/core/orchestration/sequence.py +91 -219
  22. symtest_cli-1.4.0/src/symtest/core/orchestration/single.py +187 -0
  23. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/core/parallel_runner.py +9 -43
  24. symtest_cli-1.4.0/src/symtest/core/process_worker.py +109 -0
  25. symtest_cli-1.4.0/src/symtest/core/result.py +68 -0
  26. symtest_cli-1.4.0/src/symtest/core/test_case.py +290 -0
  27. symtest_cli-1.4.0/src/symtest/core/validation/__init__.py +15 -0
  28. {symtest_cli-1.3.2/src/symtest/core → symtest_cli-1.4.0/src/symtest/core/validation}/assertions.py +18 -29
  29. symtest_cli-1.4.0/src/symtest/core/validation/result.py +19 -0
  30. symtest_cli-1.4.0/src/symtest/core/validation/validator.py +199 -0
  31. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/file_comparator/csv_comparator.py +88 -88
  32. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/file_comparator/h5_comparator.py +37 -83
  33. symtest_cli-1.4.0/src/symtest/file_comparator/numeric_compare.py +252 -0
  34. symtest_cli-1.4.0/src/symtest/reporting/__init__.py +10 -0
  35. symtest_cli-1.4.0/src/symtest/reporting/diagnosis.py +84 -0
  36. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/runners/config_runner.py +5 -4
  37. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/runners/parallel_config_runner.py +7 -5
  38. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/tui/controllers/case_controller.py +10 -6
  39. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/utils/report_generator.py +12 -0
  40. {symtest_cli-1.3.2 → symtest_cli-1.4.0/src/symtest_cli.egg-info}/PKG-INFO +1 -1
  41. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest_cli.egg-info/SOURCES.txt +55 -2
  42. symtest_cli-1.4.0/tests/e2e/__pycache__/test_user_flows.cpython-312-pytest-7.4.4.pyc +0 -0
  43. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/e2e/test_user_flows.py +12 -6
  44. symtest_cli-1.4.0/tests/fixtures/inheritance_base.json +33 -0
  45. symtest_cli-1.4.0/tests/fixtures/inheritance_chain.json +41 -0
  46. symtest_cli-1.4.0/tests/fixtures/main_config.json +26 -0
  47. symtest_cli-1.4.0/tests/fixtures/migration/v1/circular_config_a.json +7 -0
  48. symtest_cli-1.4.0/tests/fixtures/migration/v1/circular_config_b.json +7 -0
  49. symtest_cli-1.4.0/tests/fixtures/migration/v1/inheritance_circular.json +16 -0
  50. symtest_cli-1.4.0/tests/fixtures/migration/v1/skill_test_cases_golden_file.json +33 -0
  51. symtest_cli-1.4.0/tests/fixtures/migration/v1/skill_test_cases_simple.json +16 -0
  52. symtest_cli-1.4.0/tests/fixtures/migration/v1/skill_test_cases_simple.yaml +11 -0
  53. symtest_cli-1.4.0/tests/fixtures/migration/v1/skill_test_cases_steps.json +29 -0
  54. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/test_cases.yaml +9 -9
  55. symtest_cli-1.4.0/tests/fixtures/missing_fields.json +26 -0
  56. symtest_cli-1.4.0/tests/fixtures/setup_main.json +13 -0
  57. symtest_cli-1.4.0/tests/fixtures/setup_sub.json +20 -0
  58. symtest_cli-1.4.0/tests/fixtures/sub_json_tests.yaml +29 -0
  59. symtest_cli-1.4.0/tests/fixtures/sub_text_tests.json +26 -0
  60. symtest_cli-1.4.0/tests/fixtures/test_cases.json +69 -0
  61. symtest_cli-1.4.0/tests/fixtures/test_cases.yaml +11 -0
  62. symtest_cli-1.4.0/tests/fixtures/test_cases1.json +212 -0
  63. symtest_cli-1.4.0/tests/fixtures/test_with_setup.json +48 -0
  64. symtest_cli-1.4.0/tests/fixtures/test_with_setup.yaml +45 -0
  65. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_history_feature.cpython-312-pytest-7.4.4.pyc +0 -0
  66. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_history_feature.cpython-312-pytest-9.0.3.pyc +0 -0
  67. symtest_cli-1.4.0/tests/integration/__pycache__/test_new_cli_features.cpython-312-pytest-7.4.4.pyc +0 -0
  68. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_new_cli_features.cpython-312-pytest-9.0.3.pyc +0 -0
  69. symtest_cli-1.4.0/tests/integration/__pycache__/test_real_command_execution.cpython-312-pytest-7.4.4.pyc +0 -0
  70. symtest_cli-1.4.0/tests/integration/__pycache__/test_sequence.cpython-312-pytest-7.4.4.pyc +0 -0
  71. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  72. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  73. symtest_cli-1.4.0/tests/integration/parallel/__pycache__/test_depends_on.cpython-312-pytest-7.4.4.pyc +0 -0
  74. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/parallel/__pycache__/test_depends_on.cpython-312-pytest-9.0.3.pyc +0 -0
  75. symtest_cli-1.4.0/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-312-pytest-7.4.4.pyc +0 -0
  76. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/parallel/test_depends_on.py +41 -33
  77. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/parallel/test_parallel_runner.py +12 -12
  78. symtest_cli-1.4.0/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-312-pytest-7.4.4.pyc +0 -0
  79. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/path_handling/test_spaces_in_paths.py +19 -14
  80. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/test_history_feature.py +8 -10
  81. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/test_new_cli_features.py +28 -10
  82. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/test_real_command_execution.py +17 -9
  83. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/test_sequence.py +56 -42
  84. symtest_cli-1.4.0/tests/unit/__pycache__/test_config_io.cpython-312-pytest-7.4.4.pyc +0 -0
  85. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_import_expander.cpython-312-pytest-7.4.4.pyc +0 -0
  86. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_inheritance_expander.cpython-312-pytest-7.4.4.pyc +0 -0
  87. symtest_cli-1.4.0/tests/unit/__pycache__/test_migrate.cpython-312-pytest-7.4.4.pyc +0 -0
  88. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_architecture_guard.cpython-312-pytest-7.4.4.pyc +0 -0
  89. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_architecture_guard.cpython-312-pytest-9.0.3.pyc +0 -0
  90. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_assertions.cpython-312-pytest-7.4.4.pyc +0 -0
  91. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_assertions.cpython-312-pytest-9.0.3.pyc +0 -0
  92. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_case_env.cpython-312-pytest-7.4.4.pyc +0 -0
  93. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_case_env.cpython-312-pytest-9.0.3.pyc +0 -0
  94. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_config_loader.cpython-312-pytest-7.4.4.pyc +0 -0
  95. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_config_loader.cpython-312-pytest-9.0.3.pyc +0 -0
  96. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-312-pytest-7.4.4.pyc +0 -0
  97. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-312-pytest-9.0.3.pyc +0 -0
  98. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution.cpython-312-pytest-7.4.4.pyc +0 -0
  99. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution.cpython-312-pytest-9.0.3.pyc +0 -0
  100. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_execution_new_features.cpython-312-pytest-7.4.4.pyc +0 -0
  101. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution_new_features.cpython-312-pytest-9.0.3.pyc +0 -0
  102. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_model_v2.cpython-312-pytest-7.4.4.pyc +0 -0
  103. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_model_v2.cpython-312-pytest-9.0.3.pyc +0 -0
  104. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_orchestration_accept.cpython-312-pytest-7.4.4.pyc +0 -0
  105. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_orchestration_accept.cpython-312-pytest-9.0.3.pyc +0 -0
  106. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_process_worker.cpython-312-pytest-7.4.4.pyc +0 -0
  107. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_sequence_state.cpython-312-pytest-7.4.4.pyc +0 -0
  108. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_sequence_state.cpython-312-pytest-9.0.3.pyc +0 -0
  109. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_setup.cpython-312-pytest-7.4.4.pyc +0 -0
  110. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_validation_error.cpython-312-pytest-7.4.4.pyc +0 -0
  111. symtest_cli-1.4.0/tests/unit/core/__pycache__/test_validation_error.cpython-312-pytest-9.0.3.pyc +0 -0
  112. symtest_cli-1.4.0/tests/unit/core/test_architecture_guard.py +106 -0
  113. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_assertions.py +46 -40
  114. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_case_env.py +68 -51
  115. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_config_loader.py +134 -78
  116. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_config_loader_new_features.py +53 -50
  117. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_execution.py +22 -26
  118. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_execution_new_features.py +61 -77
  119. symtest_cli-1.4.0/tests/unit/core/test_model_v2.py +310 -0
  120. symtest_cli-1.4.0/tests/unit/core/test_orchestration_accept.py +183 -0
  121. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_process_worker.py +45 -45
  122. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_setup.py +6 -6
  123. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_validation_error.py +74 -63
  124. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_error_analysis.cpython-312-pytest-7.4.4.pyc +0 -0
  125. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_error_analysis.cpython-312-pytest-9.0.3.pyc +0 -0
  126. symtest_cli-1.4.0/tests/unit/file_comparator/__pycache__/test_numeric_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  127. symtest_cli-1.4.0/tests/unit/file_comparator/__pycache__/test_numeric_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  128. symtest_cli-1.4.0/tests/unit/file_comparator/__pycache__/test_numeric_parity.cpython-312-pytest-7.4.4.pyc +0 -0
  129. symtest_cli-1.4.0/tests/unit/file_comparator/__pycache__/test_numeric_parity.cpython-312-pytest-9.0.3.pyc +0 -0
  130. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/test_error_analysis.py +3 -4
  131. symtest_cli-1.4.0/tests/unit/file_comparator/test_numeric_compare.py +233 -0
  132. symtest_cli-1.4.0/tests/unit/file_comparator/test_numeric_parity.py +160 -0
  133. symtest_cli-1.4.0/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-7.4.4.pyc +0 -0
  134. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-312-pytest-7.4.4.pyc +0 -0
  135. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-312-pytest-7.4.4.pyc +0 -0
  136. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/test_json_yaml_runner.py +6 -6
  137. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/test_test_case_filter.py +6 -6
  138. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/test_test_case_tag_filter.py +9 -9
  139. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/test_config_io.py +36 -21
  140. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/test_import_expander.py +2 -2
  141. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/test_inheritance_expander.py +4 -4
  142. symtest_cli-1.4.0/tests/unit/test_migrate.py +295 -0
  143. symtest_cli-1.4.0/tests/unit/tui/__pycache__/conftest.cpython-312-pytest-7.4.4.pyc +0 -0
  144. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_case_controller.cpython-312-pytest-7.4.4.pyc +0 -0
  145. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_case_controller.cpython-312-pytest-9.0.3.pyc +0 -0
  146. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/conftest.py +8 -8
  147. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/test_case_controller.py +27 -19
  148. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/utils/__pycache__/test_report_generator.cpython-312-pytest-7.4.4.pyc +0 -0
  149. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/utils/__pycache__/test_report_generator.cpython-312-pytest-9.0.3.pyc +0 -0
  150. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/utils/test_report_generator.py +67 -0
  151. symtest_cli-1.3.2/docs/design.md +0 -840
  152. symtest_cli-1.3.2/docs/design_en.md +0 -838
  153. symtest_cli-1.3.2/src/symtest/core/execution.py +0 -504
  154. symtest_cli-1.3.2/src/symtest/core/process_worker.py +0 -95
  155. symtest_cli-1.3.2/src/symtest/core/test_case.py +0 -121
  156. symtest_cli-1.3.2/tests/e2e/__pycache__/test_user_flows.cpython-312-pytest-7.4.4.pyc +0 -0
  157. symtest_cli-1.3.2/tests/integration/__pycache__/test_new_cli_features.cpython-312-pytest-7.4.4.pyc +0 -0
  158. symtest_cli-1.3.2/tests/integration/__pycache__/test_real_command_execution.cpython-312-pytest-7.4.4.pyc +0 -0
  159. symtest_cli-1.3.2/tests/integration/__pycache__/test_sequence.cpython-312-pytest-7.4.4.pyc +0 -0
  160. symtest_cli-1.3.2/tests/integration/parallel/__pycache__/test_depends_on.cpython-312-pytest-7.4.4.pyc +0 -0
  161. symtest_cli-1.3.2/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-312-pytest-7.4.4.pyc +0 -0
  162. symtest_cli-1.3.2/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-312-pytest-7.4.4.pyc +0 -0
  163. symtest_cli-1.3.2/tests/unit/__pycache__/test_config_io.cpython-312-pytest-7.4.4.pyc +0 -0
  164. symtest_cli-1.3.2/tests/unit/core/__pycache__/test_case_env.cpython-312-pytest-7.4.4.pyc +0 -0
  165. symtest_cli-1.3.2/tests/unit/core/__pycache__/test_config_loader.cpython-312-pytest-7.4.4.pyc +0 -0
  166. symtest_cli-1.3.2/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-312-pytest-7.4.4.pyc +0 -0
  167. symtest_cli-1.3.2/tests/unit/core/__pycache__/test_execution_new_features.cpython-312-pytest-7.4.4.pyc +0 -0
  168. symtest_cli-1.3.2/tests/unit/core/__pycache__/test_process_worker.cpython-312-pytest-7.4.4.pyc +0 -0
  169. symtest_cli-1.3.2/tests/unit/core/__pycache__/test_validation_error.cpython-312-pytest-7.4.4.pyc +0 -0
  170. symtest_cli-1.3.2/tests/unit/core/__pycache__/test_validation_error.cpython-312-pytest-9.0.3.pyc +0 -0
  171. symtest_cli-1.3.2/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-7.4.4.pyc +0 -0
  172. symtest_cli-1.3.2/tests/unit/tui/__pycache__/conftest.cpython-312-pytest-7.4.4.pyc +0 -0
  173. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/LICENSE +0 -0
  174. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/MANIFEST.in +0 -0
  175. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/README.md +0 -0
  176. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/docs/tui_and_config_split_design.md +0 -0
  177. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/pyproject.toml +0 -0
  178. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/setup.cfg +0 -0
  179. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/setup.py +0 -0
  180. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/commands/__init__.py +0 -0
  181. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/commands/compare.py +0 -0
  182. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/config/__init__.py +0 -0
  183. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/config/import_expander.py +0 -0
  184. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/config/inheritance_expander.py +0 -0
  185. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/core/history_store.py +0 -0
  186. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/core/last_run_store.py +0 -0
  187. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/core/sequence_state.py +0 -0
  188. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/core/setup.py +0 -0
  189. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/core/types.py +0 -0
  190. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/file_comparator/__init__.py +0 -0
  191. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/file_comparator/base_comparator.py +0 -0
  192. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/file_comparator/binary_comparator.py +0 -0
  193. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/file_comparator/factory.py +0 -0
  194. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/file_comparator/json_comparator.py +0 -0
  195. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/file_comparator/result.py +0 -0
  196. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/file_comparator/script_comparator.py +0 -0
  197. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/file_comparator/text_comparator.py +0 -0
  198. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/file_comparator/xml_comparator.py +0 -0
  199. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/logging_config.py +0 -0
  200. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/runners/__init__.py +0 -0
  201. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/runners/json_runner.py +0 -0
  202. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/runners/parallel_json_runner.py +0 -0
  203. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/runners/parallel_yaml_runner.py +0 -0
  204. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/runners/yaml_runner.py +0 -0
  205. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/tui/__init__.py +0 -0
  206. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/tui/app.py +0 -0
  207. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/tui/controllers/__init__.py +0 -0
  208. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/tui/screens/__init__.py +0 -0
  209. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/tui/screens/case_editor.py +0 -0
  210. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/tui/screens/case_list.py +0 -0
  211. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/tui/widgets/__init__.py +0 -0
  212. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/tui/widgets/case_table.py +0 -0
  213. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/tui/widgets/expected_editor.py +0 -0
  214. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/tui/widgets/search_bar.py +0 -0
  215. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/tui/widgets/steps_editor.py +0 -0
  216. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/utils/__init__.py +0 -0
  217. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/utils/junit_xml_writer.py +0 -0
  218. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest/utils/path_resolver.py +0 -0
  219. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest_cli.egg-info/dependency_links.txt +0 -0
  220. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest_cli.egg-info/entry_points.txt +0 -0
  221. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest_cli.egg-info/requires.txt +0 -0
  222. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/src/symtest_cli.egg-info/top_level.txt +0 -0
  223. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/README.md +0 -0
  224. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/__init__.py +0 -0
  225. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/__pycache__/__init__.cpython-312.pyc +0 -0
  226. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/__pycache__/__init__.cpython-313.pyc +0 -0
  227. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/__pycache__/__init__.cpython-39.pyc +0 -0
  228. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/__pycache__/conftest.cpython-312-pytest-7.4.4.pyc +0 -0
  229. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/__pycache__/conftest.cpython-312-pytest-9.0.3.pyc +0 -0
  230. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
  231. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/__pycache__/conftest.cpython-39-pytest-8.3.4.pyc +0 -0
  232. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/__pycache__/run_all.cpython-312.pyc +0 -0
  233. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/__pycache__/run_all.cpython-313.pyc +0 -0
  234. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/__pycache__/run_all.cpython-39.pyc +0 -0
  235. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/__pycache__/test_setup_module.cpython-312-pytest-7.4.4.pyc +0 -0
  236. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/conftest.py +0 -0
  237. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/demos/h5_filter_demo.py +0 -0
  238. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/demos/manual_report_example.py +0 -0
  239. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/demos/perf_parallel.py +0 -0
  240. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/e2e/__init__.py +0 -0
  241. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/e2e/__pycache__/__init__.cpython-312.pyc +0 -0
  242. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/e2e/__pycache__/__init__.cpython-313.pyc +0 -0
  243. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/e2e/__pycache__/__init__.cpython-39.pyc +0 -0
  244. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/e2e/__pycache__/test_user_flows.cpython-312-pytest-9.0.3.pyc +0 -0
  245. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/e2e/__pycache__/test_user_flows.cpython-313-pytest-9.0.2.pyc +0 -0
  246. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/e2e/__pycache__/test_user_flows.cpython-39-pytest-8.3.4.pyc +0 -0
  247. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/fixtures/circular_config_a.json +0 -0
  248. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/fixtures/circular_config_b.json +0 -0
  249. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/fixtures/hourglass_stdout_mismatch.txt +0 -0
  250. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/fixtures/hourglass_stdout_sample.txt +0 -0
  251. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/fixtures/inheritance_circular.json +0 -0
  252. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/inheritance_base.json +0 -0
  253. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/inheritance_chain.json +0 -0
  254. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/main_config.json +0 -0
  255. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/missing_fields.json +0 -0
  256. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/setup_main.json +0 -0
  257. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/setup_sub.json +0 -0
  258. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/sub_json_tests.yaml +0 -0
  259. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/sub_text_tests.json +0 -0
  260. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/test_cases.json +0 -0
  261. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/test_cases1.json +0 -0
  262. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/test_with_setup.json +0 -0
  263. {symtest_cli-1.3.2/tests/fixtures → symtest_cli-1.4.0/tests/fixtures/migration/v1}/test_with_setup.yaml +0 -0
  264. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/fixtures/mock_fail_script.py +0 -0
  265. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/fixtures/mock_pass_script.py +0 -0
  266. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_history_feature.cpython-313-pytest-9.0.2.pyc +0 -0
  267. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_new_cli_features.cpython-313-pytest-9.0.2.pyc +0 -0
  268. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_real_command_execution.cpython-312-pytest-9.0.3.pyc +0 -0
  269. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_real_command_execution.cpython-313-pytest-9.0.2.pyc +0 -0
  270. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_sequence.cpython-312-pytest-9.0.3.pyc +0 -0
  271. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/__pycache__/test_sequence.cpython-313-pytest-9.0.2.pyc +0 -0
  272. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  273. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  274. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-313-pytest-9.0.2.pyc +0 -0
  275. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-39-pytest-8.3.4.pyc +0 -0
  276. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  277. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  278. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-313-pytest-9.0.2.pyc +0 -0
  279. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  280. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  281. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-313-pytest-9.0.2.pyc +0 -0
  282. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-39-pytest-8.3.4.pyc +0 -0
  283. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  284. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  285. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-313-pytest-9.0.2.pyc +0 -0
  286. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-39-pytest-8.3.4.pyc +0 -0
  287. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-313-pytest-9.0.2.pyc +0 -0
  288. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-39-pytest-8.3.4.pyc +0 -0
  289. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  290. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  291. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-313-pytest-9.0.2.pyc +0 -0
  292. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/test_binary_compare.py +0 -0
  293. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/test_csv_compare.py +0 -0
  294. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/test_h5_compare.py +0 -0
  295. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/test_json_compare.py +0 -0
  296. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/test_text_compare.py +0 -0
  297. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/file_compare/test_xml_compare.py +0 -0
  298. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-312-pytest-9.0.3.pyc +0 -0
  299. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-313-pytest-9.0.2.pyc +0 -0
  300. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-39-pytest-8.3.4.pyc +0 -0
  301. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-312-pytest-9.0.3.pyc +0 -0
  302. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-313-pytest-9.0.2.pyc +0 -0
  303. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-39-pytest-8.3.4.pyc +0 -0
  304. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/run_all.py +0 -0
  305. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_binary_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
  306. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_binary_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
  307. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_binary_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
  308. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_cli.cpython-312-pytest-7.4.4.pyc +0 -0
  309. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_cli.cpython-312-pytest-9.0.3.pyc +0 -0
  310. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_cli.cpython-313-pytest-9.0.2.pyc +0 -0
  311. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_config_io.cpython-312-pytest-9.0.3.pyc +0 -0
  312. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_config_io.cpython-313-pytest-9.0.2.pyc +0 -0
  313. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_h5_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
  314. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_h5_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
  315. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_h5_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
  316. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_import_expander.cpython-312-pytest-9.0.3.pyc +0 -0
  317. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_import_expander.cpython-313-pytest-9.0.2.pyc +0 -0
  318. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_inheritance_expander.cpython-312-pytest-9.0.3.pyc +0 -0
  319. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_inheritance_expander.cpython-313-pytest-9.0.2.pyc +0 -0
  320. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_result.cpython-312-pytest-7.4.4.pyc +0 -0
  321. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_result.cpython-312-pytest-9.0.3.pyc +0 -0
  322. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_result.cpython-313-pytest-9.0.2.pyc +0 -0
  323. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_run_all.cpython-312-pytest-7.4.4.pyc +0 -0
  324. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_run_all.cpython-312-pytest-9.0.3.pyc +0 -0
  325. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/__pycache__/test_run_all.cpython-313-pytest-9.0.2.pyc +0 -0
  326. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/commands/__pycache__/test_compare_command.cpython-312-pytest-7.4.4.pyc +0 -0
  327. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/commands/__pycache__/test_compare_command.cpython-312-pytest-9.0.3.pyc +0 -0
  328. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/commands/__pycache__/test_compare_command.cpython-313-pytest-9.0.2.pyc +0 -0
  329. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/commands/test_compare_command.py +0 -0
  330. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_assertions.cpython-313-pytest-9.0.2.pyc +0 -0
  331. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_config_loader.cpython-313-pytest-9.0.2.pyc +0 -0
  332. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_config_loader_new_features.cpython-313-pytest-9.0.2.pyc +0 -0
  333. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution.cpython-312.pyc +0 -0
  334. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution.cpython-313-pytest-9.0.2.pyc +0 -0
  335. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_execution_new_features.cpython-313-pytest-9.0.2.pyc +0 -0
  336. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_history_store.cpython-312-pytest-7.4.4.pyc +0 -0
  337. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_history_store.cpython-312-pytest-9.0.3.pyc +0 -0
  338. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_history_store.cpython-313-pytest-9.0.2.pyc +0 -0
  339. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_last_run_store.cpython-312-pytest-7.4.4.pyc +0 -0
  340. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_last_run_store.cpython-312-pytest-9.0.3.pyc +0 -0
  341. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_last_run_store.cpython-313-pytest-9.0.2.pyc +0 -0
  342. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_process_worker.cpython-312-pytest-9.0.3.pyc +0 -0
  343. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_process_worker.cpython-313-pytest-9.0.2.pyc +0 -0
  344. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_setup.cpython-312-pytest-9.0.3.pyc +0 -0
  345. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_setup.cpython-313-pytest-9.0.2.pyc +0 -0
  346. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_setup.cpython-39-pytest-8.3.4.pyc +0 -0
  347. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_validation_error.cpython-313-pytest-9.0.2.pyc +0 -0
  348. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_xfail.cpython-312-pytest-7.4.4.pyc +0 -0
  349. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_xfail.cpython-312-pytest-9.0.3.pyc +0 -0
  350. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/__pycache__/test_xfail.cpython-313-pytest-9.0.2.pyc +0 -0
  351. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_history_store.py +0 -0
  352. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_last_run_store.py +0 -0
  353. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_sequence_state.py +0 -0
  354. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/core/test_xfail.py +0 -0
  355. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/__init__.cpython-312.pyc +0 -0
  356. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_error_analysis.cpython-313-pytest-9.0.2.pyc +0 -0
  357. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_hourglass_tangent_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
  358. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_hourglass_tangent_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
  359. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_hourglass_tangent_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
  360. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_script_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
  361. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_script_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
  362. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_script_comparator.cpython-313-pytest-9.0.2.pyc +0 -0
  363. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_workspace_plugins.cpython-312-pytest-7.4.4.pyc +0 -0
  364. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_workspace_plugins.cpython-312-pytest-9.0.3.pyc +0 -0
  365. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/__pycache__/test_workspace_plugins.cpython-313-pytest-9.0.2.pyc +0 -0
  366. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/test_hourglass_tangent_comparator.py +0 -0
  367. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/test_script_comparator.py +0 -0
  368. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/file_comparator/test_workspace_plugins.py +0 -0
  369. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-9.0.3.pyc +0 -0
  370. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312.pyc +0 -0
  371. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-313-pytest-9.0.2.pyc +0 -0
  372. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-39-pytest-8.3.4.pyc +0 -0
  373. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-312-pytest-9.0.3.pyc +0 -0
  374. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-313-pytest-9.0.2.pyc +0 -0
  375. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-312-pytest-9.0.3.pyc +0 -0
  376. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-313-pytest-9.0.2.pyc +0 -0
  377. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/test_binary_comparator.py +0 -0
  378. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/test_cli.py +0 -0
  379. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/test_h5_comparator.py +0 -0
  380. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/test_result.py +0 -0
  381. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/test_run_all.py +0 -0
  382. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__init__.py +0 -0
  383. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/__init__.cpython-312.pyc +0 -0
  384. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/__init__.cpython-313.pyc +0 -0
  385. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/conftest.cpython-312-pytest-9.0.3.pyc +0 -0
  386. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/conftest.cpython-313-pytest-9.0.2.pyc +0 -0
  387. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_app.cpython-312-pytest-7.4.4.pyc +0 -0
  388. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_app.cpython-312-pytest-9.0.3.pyc +0 -0
  389. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_app.cpython-313-pytest-9.0.2.pyc +0 -0
  390. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_case_controller.cpython-313-pytest-9.0.2.pyc +0 -0
  391. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_search_functions.cpython-312-pytest-7.4.4.pyc +0 -0
  392. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_search_functions.cpython-312-pytest-9.0.3.pyc +0 -0
  393. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_search_functions.cpython-313-pytest-9.0.2.pyc +0 -0
  394. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_tui_run_test.cpython-312-pytest-7.4.4.pyc +0 -0
  395. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_tui_run_test.cpython-312-pytest-9.0.3.pyc +0 -0
  396. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_tui_run_test.cpython-313-pytest-9.0.2.pyc +0 -0
  397. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_widgets_data.cpython-312-pytest-7.4.4.pyc +0 -0
  398. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_widgets_data.cpython-312-pytest-9.0.3.pyc +0 -0
  399. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/__pycache__/test_widgets_data.cpython-313-pytest-9.0.2.pyc +0 -0
  400. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/test_app.py +0 -0
  401. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/test_search_functions.py +0 -0
  402. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/test_tui_run_test.py +0 -0
  403. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/tui/test_widgets_data.py +0 -0
  404. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-312-pytest-7.4.4.pyc +0 -0
  405. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-312-pytest-9.0.3.pyc +0 -0
  406. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-313-pytest-9.0.2.pyc +0 -0
  407. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/utils/__pycache__/test_report_generator.cpython-313-pytest-9.0.2.pyc +0 -0
  408. {symtest_cli-1.3.2 → symtest_cli-1.4.0}/tests/unit/utils/test_junit_xml_writer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: symtest-cli
3
- Version: 1.3.2
3
+ Version: 1.4.0
4
4
  Summary: Regression testing for CLI applications, with multi-step workflows and numerical file comparison.
5
5
  Home-page: https://github.com/ozil111/symtest-cli
6
6
  Author: Xiaotong Wang
@@ -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 拆除,单一解析器 |