cli-test-framework 0.8.1__tar.gz → 0.9.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 (163) hide show
  1. {cli_test_framework-0.8.1/src/cli_test_framework.egg-info → cli_test_framework-0.9.0}/PKG-INFO +20 -2
  2. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/README.md +19 -1
  3. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/docs/user_manual.md +84 -0
  4. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/setup.py +1 -1
  5. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/cli.py +6 -0
  6. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/core/base_runner.py +12 -4
  7. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/core/config_loader.py +2 -0
  8. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/core/parallel_runner.py +4 -7
  9. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/core/test_case.py +2 -0
  10. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/runners/config_runner.py +3 -6
  11. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/runners/json_runner.py +2 -7
  12. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/runners/parallel_config_runner.py +3 -6
  13. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/runners/parallel_json_runner.py +2 -6
  14. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/runners/parallel_yaml_runner.py +2 -6
  15. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/runners/yaml_runner.py +2 -7
  16. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0/src/cli_test_framework.egg-info}/PKG-INFO +20 -2
  17. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework.egg-info/SOURCES.txt +2 -0
  18. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/__pycache__/test_history_feature.cpython-312-pytest-9.0.3.pyc +0 -0
  19. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/__pycache__/test_sequence.cpython-312-pytest-9.0.3.pyc +0 -0
  20. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  21. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/__pycache__/test_cli.cpython-312-pytest-9.0.3.pyc +0 -0
  22. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/__pycache__/test_assertions.cpython-312-pytest-9.0.3.pyc +0 -0
  23. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/__pycache__/test_execution.cpython-312-pytest-9.0.3.pyc +0 -0
  24. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/__pycache__/test_process_worker.cpython-312-pytest-9.0.3.pyc +0 -0
  25. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/__pycache__/test_setup.cpython-312-pytest-9.0.3.pyc +0 -0
  26. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-9.0.3.pyc +0 -0
  27. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-312-pytest-9.0.3.pyc +0 -0
  28. cli_test_framework-0.9.0/tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-312-pytest-9.0.3.pyc +0 -0
  29. cli_test_framework-0.9.0/tests/unit/runners/test_test_case_tag_filter.py +254 -0
  30. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/test_cli.py +1 -0
  31. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-312-pytest-9.0.3.pyc +0 -0
  32. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/utils/__pycache__/test_report_generator.cpython-312-pytest-9.0.3.pyc +0 -0
  33. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/MANIFEST.in +0 -0
  34. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/docs/design.md +0 -0
  35. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/docs/design_en.md +0 -0
  36. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/docs/user_manual_en.md +0 -0
  37. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/pyproject.toml +0 -0
  38. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/setup.cfg +0 -0
  39. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/__init__.py +0 -0
  40. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/commands/__init__.py +0 -0
  41. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/commands/compare.py +0 -0
  42. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/core/__init__.py +0 -0
  43. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/core/assertions.py +0 -0
  44. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/core/execution.py +0 -0
  45. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/core/history_store.py +0 -0
  46. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/core/process_worker.py +0 -0
  47. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/core/setup.py +0 -0
  48. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/core/types.py +0 -0
  49. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/file_comparator/__init__.py +0 -0
  50. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/file_comparator/base_comparator.py +0 -0
  51. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/file_comparator/binary_comparator.py +0 -0
  52. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/file_comparator/csv_comparator.py +0 -0
  53. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/file_comparator/factory.py +0 -0
  54. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/file_comparator/h5_comparator.py +0 -0
  55. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/file_comparator/json_comparator.py +0 -0
  56. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/file_comparator/result.py +0 -0
  57. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/file_comparator/text_comparator.py +0 -0
  58. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/file_comparator/xml_comparator.py +0 -0
  59. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/logging_config.py +0 -0
  60. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/runners/__init__.py +0 -0
  61. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/utils/__init__.py +0 -0
  62. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/utils/junit_xml_writer.py +0 -0
  63. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/utils/path_resolver.py +0 -0
  64. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework/utils/report_generator.py +0 -0
  65. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework.egg-info/dependency_links.txt +0 -0
  66. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework.egg-info/entry_points.txt +0 -0
  67. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework.egg-info/requires.txt +0 -0
  68. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/src/cli_test_framework.egg-info/top_level.txt +0 -0
  69. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/README.md +0 -0
  70. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/__init__.py +0 -0
  71. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/__pycache__/__init__.cpython-312.pyc +0 -0
  72. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/__pycache__/__init__.cpython-39.pyc +0 -0
  73. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/__pycache__/conftest.cpython-312-pytest-7.4.4.pyc +0 -0
  74. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/__pycache__/conftest.cpython-312-pytest-9.0.3.pyc +0 -0
  75. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/__pycache__/conftest.cpython-39-pytest-8.3.4.pyc +0 -0
  76. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/__pycache__/run_all.cpython-312.pyc +0 -0
  77. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/__pycache__/run_all.cpython-39.pyc +0 -0
  78. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/__pycache__/test_parallel_runner.cpython-312-pytest-7.4.4.pyc +0 -0
  79. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/__pycache__/test_setup_module.cpython-312-pytest-7.4.4.pyc +0 -0
  80. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/conftest.py +0 -0
  81. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/demos/h5_filter_demo.py +0 -0
  82. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/demos/manual_report_example.py +0 -0
  83. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/demos/perf_parallel.py +0 -0
  84. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/e2e/__init__.py +0 -0
  85. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/e2e/__pycache__/__init__.cpython-312.pyc +0 -0
  86. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/e2e/__pycache__/__init__.cpython-39.pyc +0 -0
  87. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/e2e/__pycache__/test_user_flows.cpython-312-pytest-7.4.4.pyc +0 -0
  88. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/e2e/__pycache__/test_user_flows.cpython-312-pytest-9.0.3.pyc +0 -0
  89. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/e2e/__pycache__/test_user_flows.cpython-39-pytest-8.3.4.pyc +0 -0
  90. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/e2e/test_user_flows.py +0 -0
  91. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/fixtures/test_cases.json +0 -0
  92. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/fixtures/test_cases.yaml +0 -0
  93. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/fixtures/test_cases1.json +0 -0
  94. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/fixtures/test_with_setup.json +0 -0
  95. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/fixtures/test_with_setup.yaml +0 -0
  96. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/__pycache__/test_history_feature.cpython-312-pytest-7.4.4.pyc +0 -0
  97. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/__pycache__/test_real_command_execution.cpython-312-pytest-7.4.4.pyc +0 -0
  98. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/__pycache__/test_real_command_execution.cpython-312-pytest-9.0.3.pyc +0 -0
  99. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/__pycache__/test_sequence.cpython-312-pytest-7.4.4.pyc +0 -0
  100. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  101. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_binary_compare.cpython-39-pytest-8.3.4.pyc +0 -0
  102. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  103. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_csv_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  104. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  105. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  106. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_h5_compare.cpython-39-pytest-8.3.4.pyc +0 -0
  107. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  108. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  109. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_json_compare.cpython-39-pytest-8.3.4.pyc +0 -0
  110. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  111. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  112. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_text_compare.cpython-39-pytest-8.3.4.pyc +0 -0
  113. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-312-pytest-7.4.4.pyc +0 -0
  114. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/__pycache__/test_xml_compare.cpython-312-pytest-9.0.3.pyc +0 -0
  115. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/test_binary_compare.py +0 -0
  116. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/test_csv_compare.py +0 -0
  117. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/test_h5_compare.py +0 -0
  118. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/test_json_compare.py +0 -0
  119. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/test_text_compare.py +0 -0
  120. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/file_compare/test_xml_compare.py +0 -0
  121. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-312-pytest-7.4.4.pyc +0 -0
  122. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-312-pytest-9.0.3.pyc +0 -0
  123. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/parallel/__pycache__/test_parallel_runner.cpython-39-pytest-8.3.4.pyc +0 -0
  124. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/parallel/test_parallel_runner.py +0 -0
  125. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-312-pytest-7.4.4.pyc +0 -0
  126. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-312-pytest-9.0.3.pyc +0 -0
  127. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/path_handling/__pycache__/test_spaces_in_paths.cpython-39-pytest-8.3.4.pyc +0 -0
  128. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/path_handling/test_spaces_in_paths.py +0 -0
  129. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/test_history_feature.py +0 -0
  130. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/test_real_command_execution.py +0 -0
  131. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/integration/test_sequence.py +0 -0
  132. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/run_all.py +0 -0
  133. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/test_report.txt +0 -0
  134. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/__pycache__/test_cli.cpython-312-pytest-7.4.4.pyc +0 -0
  135. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/__pycache__/test_h5_comparator.cpython-312-pytest-7.4.4.pyc +0 -0
  136. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/__pycache__/test_h5_comparator.cpython-312-pytest-9.0.3.pyc +0 -0
  137. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/__pycache__/test_run_all.cpython-312-pytest-7.4.4.pyc +0 -0
  138. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/__pycache__/test_run_all.cpython-312-pytest-9.0.3.pyc +0 -0
  139. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/commands/__pycache__/test_compare_command.cpython-312-pytest-7.4.4.pyc +0 -0
  140. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/commands/__pycache__/test_compare_command.cpython-312-pytest-9.0.3.pyc +0 -0
  141. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/commands/test_compare_command.py +0 -0
  142. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/__pycache__/test_assertions.cpython-312-pytest-7.4.4.pyc +0 -0
  143. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/__pycache__/test_history_store.cpython-312-pytest-7.4.4.pyc +0 -0
  144. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/__pycache__/test_history_store.cpython-312-pytest-9.0.3.pyc +0 -0
  145. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/__pycache__/test_process_worker.cpython-312-pytest-7.4.4.pyc +0 -0
  146. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/__pycache__/test_setup.cpython-312-pytest-7.4.4.pyc +0 -0
  147. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/__pycache__/test_setup.cpython-39-pytest-8.3.4.pyc +0 -0
  148. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/test_assertions.py +0 -0
  149. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/test_execution.py +0 -0
  150. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/test_history_store.py +0 -0
  151. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/test_process_worker.py +0 -0
  152. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/core/test_setup.py +0 -0
  153. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-7.4.4.pyc +0 -0
  154. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-39-pytest-8.3.4.pyc +0 -0
  155. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/runners/__pycache__/test_test_case_filter.cpython-312-pytest-7.4.4.pyc +0 -0
  156. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/runners/test_json_yaml_runner.py +0 -0
  157. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/runners/test_test_case_filter.py +0 -0
  158. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/test_h5_comparator.py +0 -0
  159. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/test_run_all.py +0 -0
  160. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-312-pytest-7.4.4.pyc +0 -0
  161. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/utils/__pycache__/test_report_generator.cpython-312-pytest-7.4.4.pyc +0 -0
  162. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/utils/test_junit_xml_writer.py +0 -0
  163. {cli_test_framework-0.8.1 → cli_test_framework-0.9.0}/tests/unit/utils/test_report_generator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cli-test-framework
3
- Version: 0.8.1
3
+ Version: 0.9.0
4
4
  Summary: A powerful command line testing framework in Python with setup modules, parallel execution, and file comparison capabilities.
5
5
  Home-page: https://github.com/ozil111/cli-test-framework
6
6
  Author: Xiaotong Wang
@@ -56,7 +56,7 @@ CLI Test Framework was built for that workflow.
56
56
  - **Sequence Steps** — Multi-step execution within a single test case, fail-fast
57
57
  - **Setup Module** — Auto-configure environment variables before tests, auto-cleanup after
58
58
  - **File Comparison** — Text / JSON / CSV / XML / HDF5 / Binary, with CLI and embedded assertion support
59
- - **Filtered Execution** — Run specific test cases by name
59
+ - **Filtered Execution** — Run specific test cases by name or tag
60
60
  - **JUnit XML Output** — `--junit-xml` for GitLab CI / Jenkins / CircleCI test report panels
61
61
 
62
62
  ## Quick Start
@@ -76,6 +76,7 @@ pip install cli-test-framework
76
76
  "name": "hello",
77
77
  "command": "echo",
78
78
  "args": ["Hello World"],
79
+ "tags": ["smoke"],
79
80
  "expected": {
80
81
  "return_code": 0,
81
82
  "output_contains": ["Hello World"]
@@ -145,6 +146,19 @@ Multiple files and mixed assertion types coexist naturally:
145
146
  cli-test run test_cases.json --parallel --workers 4
146
147
  ```
147
148
 
149
+ ### Run Specific Cases
150
+
151
+ ```bash
152
+ # By name
153
+ cli-test run test_cases.json -t test_1 -t test_2
154
+
155
+ # By tag
156
+ cli-test run test_cases.json --tag smoke
157
+
158
+ # Combine name and tag (AND logic)
159
+ cli-test run test_cases.json -t test_1 --tag smoke
160
+ ```
161
+
148
162
  ### JUnit XML (CI Integration)
149
163
 
150
164
  ```bash
@@ -184,6 +198,10 @@ compare-files result1.h5 result2.h5 --h5-table-regex "output_.*" --h5-rtol 1e-5
184
198
 
185
199
  ## Changelog
186
200
 
201
+ ### 0.9.0
202
+
203
+ - **Tag filtering**: New `tags` field in test case definitions for categorization. Use `--tag` CLI option or `test_case_tag_filter` Python API to batch-filter test cases. Acts as OR within tags, AND with name filtering.
204
+
187
205
  ### 0.8.0
188
206
 
189
207
  - **JUnit XML output**: New `--junit-xml <filepath>` CLI option writes JUnit-format XML reports that integrate directly with GitLab CI, Jenkins, CircleCI, and other CI tools. Supports `passed` / `failed` / `timeout` / `error` status mapping. Zero extra dependencies — built with `xml.etree.ElementTree`.
@@ -20,7 +20,7 @@ CLI Test Framework was built for that workflow.
20
20
  - **Sequence Steps** — Multi-step execution within a single test case, fail-fast
21
21
  - **Setup Module** — Auto-configure environment variables before tests, auto-cleanup after
22
22
  - **File Comparison** — Text / JSON / CSV / XML / HDF5 / Binary, with CLI and embedded assertion support
23
- - **Filtered Execution** — Run specific test cases by name
23
+ - **Filtered Execution** — Run specific test cases by name or tag
24
24
  - **JUnit XML Output** — `--junit-xml` for GitLab CI / Jenkins / CircleCI test report panels
25
25
 
26
26
  ## Quick Start
@@ -40,6 +40,7 @@ pip install cli-test-framework
40
40
  "name": "hello",
41
41
  "command": "echo",
42
42
  "args": ["Hello World"],
43
+ "tags": ["smoke"],
43
44
  "expected": {
44
45
  "return_code": 0,
45
46
  "output_contains": ["Hello World"]
@@ -109,6 +110,19 @@ Multiple files and mixed assertion types coexist naturally:
109
110
  cli-test run test_cases.json --parallel --workers 4
110
111
  ```
111
112
 
113
+ ### Run Specific Cases
114
+
115
+ ```bash
116
+ # By name
117
+ cli-test run test_cases.json -t test_1 -t test_2
118
+
119
+ # By tag
120
+ cli-test run test_cases.json --tag smoke
121
+
122
+ # Combine name and tag (AND logic)
123
+ cli-test run test_cases.json -t test_1 --tag smoke
124
+ ```
125
+
112
126
  ### JUnit XML (CI Integration)
113
127
 
114
128
  ```bash
@@ -148,6 +162,10 @@ compare-files result1.h5 result2.h5 --h5-table-regex "output_.*" --h5-rtol 1e-5
148
162
 
149
163
  ## Changelog
150
164
 
165
+ ### 0.9.0
166
+
167
+ - **Tag filtering**: New `tags` field in test case definitions for categorization. Use `--tag` CLI option or `test_case_tag_filter` Python API to batch-filter test cases. Acts as OR within tags, AND with name filtering.
168
+
151
169
  ### 0.8.0
152
170
 
153
171
  - **JUnit XML output**: New `--junit-xml <filepath>` CLI option writes JUnit-format XML reports that integrate directly with GitLab CI, Jenkins, CircleCI, and other CI tools. Supports `passed` / `failed` / `timeout` / `error` status mapping. Zero extra dependencies — built with `xml.etree.ElementTree`.
@@ -5,6 +5,7 @@
5
5
  - [安装](#安装)
6
6
  - [测试用例定义](#测试用例定义)
7
7
  - [运行测试](#运行测试)
8
+ - [标签过滤](#标签过滤)
8
9
  - [Setup 模块](#setup-模块)
9
10
  - [并行测试](#并行测试)
10
11
  - [顺序步骤测试](#顺序步骤测试)
@@ -100,6 +101,7 @@ test_cases:
100
101
  | `args` | 否 | 命令参数列表 |
101
102
  | `description` | 否 | 测试用例描述 |
102
103
  | `timeout` | 否 | 超时秒数,默认 3600,设 `null` 无限制 |
104
+ | `tags` | 否 | 标签列表,用于批量过滤(如 `["smoke", "fast"]`) |
103
105
  | `resources` | 否 | 资源配置,见[资源感知调度](#资源感知调度) |
104
106
  | `expected.return_code` | 否 | 期望返回码 |
105
107
  | `expected.output_contains` | 否 | 输出需包含的字符串列表 |
@@ -162,6 +164,13 @@ cli-test run test_cases.json --parallel --execution-mode process
162
164
  # 只运行指定用例
163
165
  cli-test run test_cases.json -t test_name_1 -t test_name_2
164
166
 
167
+ # 按标签过滤
168
+ cli-test run test_cases.json --tag smoke
169
+ cli-test run test_cases.json --tag smoke --tag regression
170
+
171
+ # 同时按名称和标签过滤(AND 关系)
172
+ cli-test run test_cases.json -t test_name_1 --tag smoke
173
+
165
174
  # 详细输出
166
175
  cli-test run test_cases.json --verbose
167
176
 
@@ -191,6 +200,7 @@ runner = JSONRunner(
191
200
  config_file="test_cases.json",
192
201
  workspace="/path/to/project", # 可选,默认项目根目录
193
202
  test_case_filter=["test_1"], # 可选,只运行指定用例
203
+ test_case_tag_filter=["smoke"], # 可选,只运行包含指定标签的用例
194
204
  history_dir="./hist", # 可选,启用历史记录与回归检测
195
205
  regression_threshold=2.0, # 可选,回归阈值倍数,默认 1.5
196
206
  )
@@ -235,6 +245,80 @@ for detail in runner.results["details"]:
235
245
  print(detail["name"], detail["status"], detail.get("message", ""))
236
246
  ```
237
247
 
248
+ ## 标签过滤
249
+
250
+ 通过标签(tags)可以对测试用例进行分类,并在运行时按标签批量过滤。标签过滤与名称过滤可同时使用,满足 AND 关系(两个条件都必须满足)。
251
+
252
+ ### 在测试用例中定义标签
253
+
254
+ JSON:
255
+
256
+ ```json
257
+ {
258
+ "test_cases": [
259
+ {
260
+ "name": "快速测试",
261
+ "command": "echo",
262
+ "args": ["hello"],
263
+ "tags": ["smoke", "fast"],
264
+ "expected": { "return_code": 0 }
265
+ },
266
+ {
267
+ "name": "完整回归测试",
268
+ "command": "python",
269
+ "args": ["long_test.py"],
270
+ "tags": ["regression", "slow"],
271
+ "expected": { "return_code": 0 }
272
+ }
273
+ ]
274
+ }
275
+ ```
276
+
277
+ YAML:
278
+
279
+ ```yaml
280
+ test_cases:
281
+ - name: 快速测试
282
+ command: echo
283
+ args: ["hello"]
284
+ tags: ["smoke", "fast"]
285
+ expected:
286
+ return_code: 0
287
+ ```
288
+
289
+ `tags` 是可选字段,不指定则默认为空列表。每个用例可以有多个标签。
290
+
291
+ ### 运行时过滤
292
+
293
+ ```bash
294
+ # 只运行带 "smoke" 标签的用例
295
+ cli-test run test_cases.json --tag smoke
296
+
297
+ # 运行带 "smoke" 或 "regression" 标签的用例(OR 关系)
298
+ cli-test run test_cases.json --tag smoke --tag regression
299
+
300
+ # 同时按名称和标签过滤(AND 关系)
301
+ cli-test run test_cases.json -t alpha --tag fast
302
+ ```
303
+
304
+ ### Python API
305
+
306
+ ```python
307
+ runner = JSONRunner(
308
+ config_file="test_cases.json",
309
+ test_case_tag_filter=["smoke"], # 只运行含 smoke 标签的用例
310
+ )
311
+ success = runner.run_tests()
312
+
313
+ # 结合名称过滤
314
+ runner = JSONRunner(
315
+ config_file="test_cases.json",
316
+ test_case_filter=["alpha", "beta"],
317
+ test_case_tag_filter=["fast"],
318
+ )
319
+ success = runner.run_tests()
320
+ ```
321
+
238
322
  ## Setup 模块
239
323
 
240
324
  Setup 模块在测试前执行初始化、测试后执行清理。
@@ -8,7 +8,7 @@ with open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f:
8
8
 
9
9
  setup(
10
10
  name="cli-test-framework",
11
- version="0.8.1",
11
+ version="0.9.0",
12
12
  author="Xiaotong Wang",
13
13
  author_email="xiaotongwang98@gmail.com",
14
14
  description="A powerful command line testing framework in Python with setup modules, parallel execution, and file comparison capabilities.",
@@ -51,6 +51,8 @@ Examples:
51
51
  help='Output format for test results')
52
52
  run_parser.add_argument('--test-case', '-t', action='append', default=None,
53
53
  help='Run only specified test case(s) by name (can be used multiple times)')
54
+ run_parser.add_argument('--tag', action='append', default=None,
55
+ help='Run only test cases with matching tag(s) (can be used multiple times)')
54
56
  run_parser.add_argument('--history-dir',
55
57
  help='Directory for .symtest runtime history (enables smart scheduling & regression detection)')
56
58
  run_parser.add_argument('--regression-threshold', type=float, default=1.5,
@@ -145,6 +147,7 @@ def run_tests(args):
145
147
  max_workers=args.workers,
146
148
  execution_mode=args.execution_mode,
147
149
  test_case_filter=args.test_case,
150
+ test_case_tag_filter=args.tag,
148
151
  history_dir=history_dir,
149
152
  regression_threshold=regression_threshold,
150
153
  )
@@ -155,6 +158,7 @@ def run_tests(args):
155
158
  max_workers=args.workers,
156
159
  execution_mode=args.execution_mode,
157
160
  test_case_filter=args.test_case,
161
+ test_case_tag_filter=args.tag,
158
162
  history_dir=history_dir,
159
163
  regression_threshold=regression_threshold,
160
164
  )
@@ -168,6 +172,7 @@ def run_tests(args):
168
172
  config_file=str(config_file),
169
173
  workspace=args.workspace,
170
174
  test_case_filter=args.test_case,
175
+ test_case_tag_filter=args.tag,
171
176
  history_dir=history_dir,
172
177
  regression_threshold=regression_threshold,
173
178
  )
@@ -176,6 +181,7 @@ def run_tests(args):
176
181
  config_file=str(config_file),
177
182
  workspace=args.workspace,
178
183
  test_case_filter=args.test_case,
184
+ test_case_tag_filter=args.tag,
179
185
  history_dir=history_dir,
180
186
  regression_threshold=regression_threshold,
181
187
  )
@@ -14,6 +14,7 @@ logger = logging.getLogger("cli_test_framework.core.base_runner")
14
14
  class BaseRunner(ABC):
15
15
  def __init__(self, config_file: str, workspace: Optional[str] = None,
16
16
  test_case_filter: Optional[List[str]] = None,
17
+ test_case_tag_filter: Optional[List[str]] = None,
17
18
  history_dir: Optional[str] = None,
18
19
  regression_threshold: float = 1.5):
19
20
  if workspace:
@@ -27,6 +28,7 @@ class BaseRunner(ABC):
27
28
  self.config_path = self.workspace / config_path
28
29
  self.test_cases: List[TestCase] = []
29
30
  self.test_case_filter: Optional[List[str]] = test_case_filter
31
+ self.test_case_tag_filter: Optional[List[str]] = test_case_tag_filter
30
32
  if history_dir:
31
33
  self.history_dir = str((self.workspace / history_dir).resolve())
32
34
  else:
@@ -63,16 +65,22 @@ class BaseRunner(ABC):
63
65
  # pass
64
66
 
65
67
  def _apply_test_case_filter(self) -> None:
66
- """根据 test_case_filter 过滤测试用例"""
67
- if self.test_case_filter:
68
+ """根据 test_case_filter 和 test_case_tag_filter 过滤测试用例"""
69
+ if self.test_case_filter or self.test_case_tag_filter:
68
70
  original_count = len(self.test_cases)
69
- self.test_cases = [tc for tc in self.test_cases if tc.name in self.test_case_filter]
71
+ self.test_cases = [
72
+ tc for tc in self.test_cases
73
+ if (not self.test_case_filter or tc.name in self.test_case_filter)
74
+ and (not self.test_case_tag_filter
75
+ or set(tc.tags or []) & set(self.test_case_tag_filter))
76
+ ]
70
77
  filtered_out = original_count - len(self.test_cases)
71
78
  if filtered_out > 0:
72
79
  logger.info("Filtered out %d test case(s). Running %d specified case(s).",
73
80
  filtered_out, len(self.test_cases))
74
81
  if not self.test_cases:
75
- logger.warning("No matching test cases found for: %s", self.test_case_filter)
82
+ logger.warning("No matching test cases found for: names=%s, tags=%s",
83
+ self.test_case_filter, self.test_case_tag_filter)
76
84
 
77
85
  def run_tests(self) -> bool:
78
86
  """Run all test cases and return whether all tests passed"""
@@ -79,6 +79,7 @@ def parse_test_cases(
79
79
  steps=steps,
80
80
  description=case.get("description", ""),
81
81
  resources=case.get("resources"),
82
+ tags=case.get("tags", []),
82
83
  ))
83
84
  else:
84
85
  # ── Single-command mode (backward-compatible) ──
@@ -100,6 +101,7 @@ def parse_test_cases(
100
101
  description=case.get("description", ""),
101
102
  timeout=case.get("timeout"),
102
103
  resources=case.get("resources"),
104
+ tags=case.get("tags", []),
103
105
  ))
104
106
 
105
107
  return cases
@@ -81,9 +81,7 @@ class ParallelRunner(BaseRunner):
81
81
  def __init__(self, config_file: str, workspace: Optional[str] = None,
82
82
  max_workers: Optional[int] = None,
83
83
  execution_mode: str = "thread",
84
- test_case_filter: Optional[List[str]] = None,
85
- history_dir: Optional[str] = None,
86
- regression_threshold: float = 1.5):
84
+ **kwargs):
87
85
  """
88
86
  初始化并行运行器
89
87
 
@@ -92,11 +90,10 @@ class ParallelRunner(BaseRunner):
92
90
  workspace: 工作目录
93
91
  max_workers: 最大并发数,默认为CPU核心数
94
92
  execution_mode: 执行模式,'thread'(线程) 或 'process'(进程)
95
- test_case_filter: 只运行指定名称的测试用例
96
- history_dir: .symtest 历史记录目录
97
- regression_threshold: 回归检测阈值
93
+ **kwargs: 透传给 BaseRunner 的额外参数
94
+ (test_case_filter, test_case_tag_filter, history_dir, regression_threshold)
98
95
  """
99
- super().__init__(config_file, workspace, test_case_filter, history_dir, regression_threshold)
96
+ super().__init__(config_file, workspace, **kwargs)
100
97
  self.max_workers = max_workers
101
98
  self.execution_mode = execution_mode
102
99
  self.lock = threading.Lock() # 用于线程安全的结果更新
@@ -21,6 +21,7 @@ class TestCase:
21
21
  timeout: Optional[float] = None
22
22
  resources: Optional[Dict[str, Any]] = None
23
23
  steps: Optional[List[TestCaseStep]] = None
24
+ tags: List[str] = field(default_factory=list)
24
25
 
25
26
  def to_dict(self) -> Dict[str, Any]:
26
27
  """Convert test case to dictionary format"""
@@ -31,6 +32,7 @@ class TestCase:
31
32
  "expected": self.expected,
32
33
  "timeout": self.timeout,
33
34
  "resources": self.resources,
35
+ "tags": self.tags,
34
36
  }
35
37
  if self.steps is not None:
36
38
  result["steps"] = [
@@ -29,12 +29,9 @@ class ConfigRunner(BaseRunner):
29
29
 
30
30
  def __init__(self, config_file: str = "test_cases.json",
31
31
  workspace: Optional[str] = None,
32
- test_case_filter: Optional[list] = None,
33
- history_dir: Optional[str] = None,
34
- regression_threshold: float = 1.5,
35
- config_loader: Optional[Callable[[BinaryIO], Dict[str, Any]]] = None):
36
- super().__init__(config_file, workspace, test_case_filter,
37
- history_dir, regression_threshold)
32
+ config_loader: Optional[Callable[[BinaryIO], Dict[str, Any]]] = None,
33
+ **kwargs):
34
+ super().__init__(config_file, workspace, **kwargs)
38
35
  self._config_loader = config_loader
39
36
  # Backward-compatible attribute for tests that patch path_resolver
40
37
  self.path_resolver = PathResolver(self.workspace)
@@ -12,15 +12,10 @@ class JSONRunner(ConfigRunner):
12
12
  """Sequential JSON test runner (backward-compatible thin wrapper)."""
13
13
 
14
14
  def __init__(self, config_file="test_cases.json",
15
- workspace: Optional[str] = None,
16
- test_case_filter: Optional[list] = None,
17
- history_dir: Optional[str] = None,
18
- regression_threshold: float = 1.5):
15
+ workspace: Optional[str] = None, **kwargs):
19
16
  super().__init__(
20
17
  config_file=config_file,
21
18
  workspace=workspace,
22
- test_case_filter=test_case_filter,
23
- history_dir=history_dir,
24
- regression_threshold=regression_threshold,
25
19
  config_loader=json.load,
20
+ **kwargs,
26
21
  )
@@ -31,10 +31,8 @@ class ParallelConfigRunner(ParallelRunner):
31
31
  workspace: Optional[str] = None,
32
32
  max_workers: Optional[int] = None,
33
33
  execution_mode: str = "thread",
34
- test_case_filter: Optional[list] = None,
35
- history_dir: Optional[str] = None,
36
- regression_threshold: float = 1.5,
37
- config_loader: Optional[Callable[[BinaryIO], Dict[str, Any]]] = None):
34
+ config_loader: Optional[Callable[[BinaryIO], Dict[str, Any]]] = None,
35
+ **kwargs):
38
36
  # Auto-detect physical CPU cores (reserve 2 for OS)
39
37
  self.total_physical = os.cpu_count() or 4
40
38
  self.safe_capacity = max(1, self.total_physical - 2)
@@ -43,8 +41,7 @@ class ParallelConfigRunner(ParallelRunner):
43
41
  max_workers = self.total_physical
44
42
 
45
43
  super().__init__(config_file, workspace, max_workers,
46
- execution_mode, test_case_filter,
47
- history_dir, regression_threshold)
44
+ execution_mode, **kwargs)
48
45
  self._config_loader = config_loader
49
46
  # Backward-compatible attribute for tests that patch path_resolver
50
47
  self.path_resolver = PathResolver(self.workspace)
@@ -15,16 +15,12 @@ class ParallelJSONRunner(ParallelConfigRunner):
15
15
  workspace: Optional[str] = None,
16
16
  max_workers: Optional[int] = None,
17
17
  execution_mode: str = "thread",
18
- test_case_filter: Optional[list] = None,
19
- history_dir: Optional[str] = None,
20
- regression_threshold: float = 1.5):
18
+ **kwargs):
21
19
  super().__init__(
22
20
  config_file=config_file,
23
21
  workspace=workspace,
24
22
  max_workers=max_workers,
25
23
  execution_mode=execution_mode,
26
- test_case_filter=test_case_filter,
27
- history_dir=history_dir,
28
- regression_threshold=regression_threshold,
29
24
  config_loader=json.load,
25
+ **kwargs,
30
26
  )
@@ -20,16 +20,12 @@ class ParallelYAMLRunner(ParallelConfigRunner):
20
20
  workspace: Optional[str] = None,
21
21
  max_workers: Optional[int] = None,
22
22
  execution_mode: str = "thread",
23
- test_case_filter: Optional[list] = None,
24
- history_dir: Optional[str] = None,
25
- regression_threshold: float = 1.5):
23
+ **kwargs):
26
24
  super().__init__(
27
25
  config_file=config_file,
28
26
  workspace=workspace,
29
27
  max_workers=max_workers,
30
28
  execution_mode=execution_mode,
31
- test_case_filter=test_case_filter,
32
- history_dir=history_dir,
33
- regression_threshold=regression_threshold,
34
29
  config_loader=_yaml_load,
30
+ **kwargs,
35
31
  )
@@ -17,15 +17,10 @@ class YAMLRunner(ConfigRunner):
17
17
  """Sequential YAML test runner (backward-compatible thin wrapper)."""
18
18
 
19
19
  def __init__(self, config_file="test_cases.yaml",
20
- workspace: Optional[str] = None,
21
- test_case_filter: Optional[list] = None,
22
- history_dir: Optional[str] = None,
23
- regression_threshold: float = 1.5):
20
+ workspace: Optional[str] = None, **kwargs):
24
21
  super().__init__(
25
22
  config_file=config_file,
26
23
  workspace=workspace,
27
- test_case_filter=test_case_filter,
28
- history_dir=history_dir,
29
- regression_threshold=regression_threshold,
30
24
  config_loader=_yaml_load,
25
+ **kwargs,
31
26
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cli-test-framework
3
- Version: 0.8.1
3
+ Version: 0.9.0
4
4
  Summary: A powerful command line testing framework in Python with setup modules, parallel execution, and file comparison capabilities.
5
5
  Home-page: https://github.com/ozil111/cli-test-framework
6
6
  Author: Xiaotong Wang
@@ -56,7 +56,7 @@ CLI Test Framework was built for that workflow.
56
56
  - **Sequence Steps** — Multi-step execution within a single test case, fail-fast
57
57
  - **Setup Module** — Auto-configure environment variables before tests, auto-cleanup after
58
58
  - **File Comparison** — Text / JSON / CSV / XML / HDF5 / Binary, with CLI and embedded assertion support
59
- - **Filtered Execution** — Run specific test cases by name
59
+ - **Filtered Execution** — Run specific test cases by name or tag
60
60
  - **JUnit XML Output** — `--junit-xml` for GitLab CI / Jenkins / CircleCI test report panels
61
61
 
62
62
  ## Quick Start
@@ -76,6 +76,7 @@ pip install cli-test-framework
76
76
  "name": "hello",
77
77
  "command": "echo",
78
78
  "args": ["Hello World"],
79
+ "tags": ["smoke"],
79
80
  "expected": {
80
81
  "return_code": 0,
81
82
  "output_contains": ["Hello World"]
@@ -145,6 +146,19 @@ Multiple files and mixed assertion types coexist naturally:
145
146
  cli-test run test_cases.json --parallel --workers 4
146
147
  ```
147
148
 
149
+ ### Run Specific Cases
150
+
151
+ ```bash
152
+ # By name
153
+ cli-test run test_cases.json -t test_1 -t test_2
154
+
155
+ # By tag
156
+ cli-test run test_cases.json --tag smoke
157
+
158
+ # Combine name and tag (AND logic)
159
+ cli-test run test_cases.json -t test_1 --tag smoke
160
+ ```
161
+
148
162
  ### JUnit XML (CI Integration)
149
163
 
150
164
  ```bash
@@ -184,6 +198,10 @@ compare-files result1.h5 result2.h5 --h5-table-regex "output_.*" --h5-rtol 1e-5
184
198
 
185
199
  ## Changelog
186
200
 
201
+ ### 0.9.0
202
+
203
+ - **Tag filtering**: New `tags` field in test case definitions for categorization. Use `--tag` CLI option or `test_case_tag_filter` Python API to batch-filter test cases. Acts as OR within tags, AND with name filtering.
204
+
187
205
  ### 0.8.0
188
206
 
189
207
  - **JUnit XML output**: New `--junit-xml <filepath>` CLI option writes JUnit-format XML reports that integrate directly with GitLab CI, Jenkins, CircleCI, and other CI tools. Supports `passed` / `failed` / `timeout` / `error` status mapping. Zero extra dependencies — built with `xml.etree.ElementTree`.
@@ -146,11 +146,13 @@ tests/unit/core/__pycache__/test_setup.cpython-312-pytest-9.0.3.pyc
146
146
  tests/unit/core/__pycache__/test_setup.cpython-39-pytest-8.3.4.pyc
147
147
  tests/unit/runners/test_json_yaml_runner.py
148
148
  tests/unit/runners/test_test_case_filter.py
149
+ tests/unit/runners/test_test_case_tag_filter.py
149
150
  tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-7.4.4.pyc
150
151
  tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-312-pytest-9.0.3.pyc
151
152
  tests/unit/runners/__pycache__/test_json_yaml_runner.cpython-39-pytest-8.3.4.pyc
152
153
  tests/unit/runners/__pycache__/test_test_case_filter.cpython-312-pytest-7.4.4.pyc
153
154
  tests/unit/runners/__pycache__/test_test_case_filter.cpython-312-pytest-9.0.3.pyc
155
+ tests/unit/runners/__pycache__/test_test_case_tag_filter.cpython-312-pytest-9.0.3.pyc
154
156
  tests/unit/utils/test_junit_xml_writer.py
155
157
  tests/unit/utils/test_report_generator.py
156
158
  tests/unit/utils/__pycache__/test_junit_xml_writer.cpython-312-pytest-7.4.4.pyc