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