cli-test-framework 0.3.2__tar.gz → 0.3.4__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.
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/CHANGELOG.md +14 -2
- cli_test_framework-0.3.4/PKG-INFO +522 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/README.md +18 -5
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/docs/user_manual.md +2 -2
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/setup.py +10 -9
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/__init__.py +1 -1
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/commands/compare.py +3 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/file_comparator/factory.py +1 -1
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/file_comparator/h5_comparator.py +33 -2
- cli_test_framework-0.3.4/src/cli_test_framework.egg-info/PKG-INFO +522 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework.egg-info/requires.txt +3 -2
- cli_test_framework-0.3.2/PKG-INFO +0 -546
- cli_test_framework-0.3.2/src/cli_test_framework.egg-info/PKG-INFO +0 -546
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/MANIFEST.in +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/pyproject.toml +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/setup.cfg +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/cli.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/commands/__init__.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/core/__init__.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/core/assertions.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/core/base_runner.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/core/parallel_runner.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/core/process_worker.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/core/setup.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/core/test_case.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/file_comparator/__init__.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/file_comparator/base_comparator.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/file_comparator/binary_comparator.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/file_comparator/csv_comparator.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/file_comparator/json_comparator.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/file_comparator/result.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/file_comparator/text_comparator.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/file_comparator/xml_comparator.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/runners/__init__.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/runners/json_runner.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/runners/parallel_json_runner.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/runners/yaml_runner.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/utils/__init__.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/utils/path_resolver.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/utils/report_generator.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework.egg-info/SOURCES.txt +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework.egg-info/dependency_links.txt +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework.egg-info/entry_points.txt +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework.egg-info/top_level.txt +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/__init__.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/__pycache__/__init__.cpython-312.pyc +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/__pycache__/test_parallel_runner.cpython-312-pytest-7.4.4.pyc +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/__pycache__/test_setup_module.cpython-312-pytest-7.4.4.pyc +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/fixtures/test_cases.json +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/fixtures/test_cases.yaml +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/fixtures/test_cases1.json +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/fixtures/test_with_setup.json +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/fixtures/test_with_setup.yaml +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/performance_test.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/test1.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/test_comprehensive_space.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/test_parallel_runner.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/test_parallel_space.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/test_report.txt +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/test_runners.py +0 -0
- {cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/tests/test_setup_module.py +0 -0
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
# 变更日志
|
|
2
2
|
|
|
3
|
-
## [v0.3.
|
|
3
|
+
## [v0.3.3] - 2025-06-09
|
|
4
|
+
|
|
5
|
+
### 🔧 项目信息更新
|
|
6
|
+
- **GitHub仓库更新**:更新项目仓库地址为 https://github.com/ozil111/cli-test-framework
|
|
7
|
+
- **PyPI主页优化**:恢复使用README.md作为PyPI项目主页描述,更适合对外展示
|
|
8
|
+
- **文档链接调整**:用户手册通过Documentation链接访问,结构更加清晰
|
|
9
|
+
|
|
10
|
+
### 📚 链接修复
|
|
11
|
+
- 更新所有文档中的GitHub仓库链接
|
|
12
|
+
- 修正PyPI项目的Documentation链接指向
|
|
13
|
+
- 改善文档访问体验和项目结构
|
|
14
|
+
|
|
15
|
+
## [v0.3.2] - 2024-06-09
|
|
4
16
|
|
|
5
17
|
### 🔧 重大改进
|
|
6
18
|
- **PyPI文档更新**:PyPI项目页面现在显示完整的用户手册内容(包含Setup模块文档)
|
|
@@ -13,7 +25,7 @@
|
|
|
13
25
|
- 增加了指向完整用户手册的链接和说明
|
|
14
26
|
- 改善了文档结构和可读性
|
|
15
27
|
|
|
16
|
-
## [v0.3.1] - 2024-
|
|
28
|
+
## [v0.3.1] - 2024-06-08
|
|
17
29
|
|
|
18
30
|
### 🔧 改进
|
|
19
31
|
- **文档更新**:完善了用户手册中的Setup模块文档
|
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cli-test-framework
|
|
3
|
+
Version: 0.3.4
|
|
4
|
+
Summary: A powerful command line testing framework in Python with setup modules, parallel execution, and file comparison capabilities.
|
|
5
|
+
Home-page: https://github.com/ozil111/cli-test-framework
|
|
6
|
+
Author: Xiaotong Wang
|
|
7
|
+
Author-email: xiaotongwang98@gmail.com
|
|
8
|
+
Project-URL: Documentation, https://github.com/ozil111/cli-test-framework/blob/main/docs/user_manual.md
|
|
9
|
+
Project-URL: Source, https://github.com/ozil111/cli-test-framework
|
|
10
|
+
Project-URL: Tracker, https://github.com/ozil111/cli-test-framework/issues
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Topic :: Software Development :: Testing
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Requires-Python: >=3.9
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Requires-Dist: dukpy==0.5.0
|
|
21
|
+
Requires-Dist: h5py>=3.10.0
|
|
22
|
+
Requires-Dist: numpy<2.0.0,>=1.24.0
|
|
23
|
+
Requires-Dist: PyYAML>=6.0
|
|
24
|
+
Requires-Dist: setuptools>=75.8.0
|
|
25
|
+
Requires-Dist: wheel>=0.45.1
|
|
26
|
+
Dynamic: author
|
|
27
|
+
Dynamic: author-email
|
|
28
|
+
Dynamic: classifier
|
|
29
|
+
Dynamic: description
|
|
30
|
+
Dynamic: description-content-type
|
|
31
|
+
Dynamic: home-page
|
|
32
|
+
Dynamic: project-url
|
|
33
|
+
Dynamic: requires-dist
|
|
34
|
+
Dynamic: requires-python
|
|
35
|
+
Dynamic: summary
|
|
36
|
+
|
|
37
|
+
# CLI Testing Framework
|
|
38
|
+
|
|
39
|
+
## 1. Overview
|
|
40
|
+
|
|
41
|
+
This is a lightweight and extensible automated testing framework that supports defining test cases via JSON/YAML formats, providing complete test execution, result verification, and report generation capabilities. The framework is designed to provide standardized test management for command-line tools and scripts, with enterprise-grade parallel execution support and advanced file comparison features.
|
|
42
|
+
|
|
43
|
+
## 2. Features
|
|
44
|
+
|
|
45
|
+
- **🚀 Parallel Test Execution**: Support for multi-threading and multi-processing parallel testing with significant performance improvements
|
|
46
|
+
- **🔧 Setup Module System**: Plugin-based architecture for pre-test setup tasks (environment variables, database initialization, service startup)
|
|
47
|
+
- **🏗️ Modular Architecture**: Decoupled design of core components (runner/assertion/report/setup)
|
|
48
|
+
- **📄 Multi-Format Support**: Native support for JSON/YAML test case formats
|
|
49
|
+
- **🧠 Intelligent Command Parsing**: Smart handling of complex commands like `"python ./script.py"`
|
|
50
|
+
- **📁 Smart Path Resolution**: Automatic handling of relative and absolute path conversions
|
|
51
|
+
- **✅ Rich Assertion Mechanism**: Return code validation, output content matching, regex verification
|
|
52
|
+
- **🔌 Extensible Interfaces**: Quickly implement new test format support by inheriting BaseRunner
|
|
53
|
+
- **🔒 Isolated Execution Environment**: Independent sub-process execution ensures test isolation
|
|
54
|
+
- **📊 Comprehensive Reports**: Detailed pass rate statistics and failure diagnostics
|
|
55
|
+
- **🔧 Thread-Safe Design**: Robust concurrent execution with proper synchronization
|
|
56
|
+
- **📝 Advanced File Comparison**: Support for comparing various file types (text, binary, JSON, HDF5) with detailed diff output
|
|
57
|
+
|
|
58
|
+
## 3. Quick Start
|
|
59
|
+
|
|
60
|
+
### Environment Requirements
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install cli-test-framework
|
|
64
|
+
Python >= 3.9
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Sequential Execution
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from src.runners.json_runner import JSONRunner
|
|
71
|
+
|
|
72
|
+
runner = JSONRunner(
|
|
73
|
+
config_file="path/to/test_cases.json",
|
|
74
|
+
workspace="/project/root"
|
|
75
|
+
)
|
|
76
|
+
success = runner.run_tests()
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Parallel Execution
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from src.runners.parallel_json_runner import ParallelJSONRunner
|
|
83
|
+
|
|
84
|
+
# Multi-threaded execution (recommended for I/O-intensive tests)
|
|
85
|
+
runner = ParallelJSONRunner(
|
|
86
|
+
config_file="path/to/test_cases.json",
|
|
87
|
+
workspace="/project/root",
|
|
88
|
+
max_workers=4, # Maximum concurrent workers
|
|
89
|
+
execution_mode="thread" # "thread" or "process"
|
|
90
|
+
)
|
|
91
|
+
success = runner.run_tests()
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Setup Module Usage
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from cli_test_framework import JSONRunner, EnvironmentSetup
|
|
98
|
+
|
|
99
|
+
# Using built-in environment variable setup
|
|
100
|
+
runner = JSONRunner("test_cases.json")
|
|
101
|
+
env_setup = EnvironmentSetup({
|
|
102
|
+
"TEST_ENV": "development",
|
|
103
|
+
"API_URL": "http://localhost:8080"
|
|
104
|
+
})
|
|
105
|
+
runner.setup_manager.add_setup(env_setup)
|
|
106
|
+
success = runner.run_tests()
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### File Comparison
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Compare two text files
|
|
113
|
+
compare-files file1.txt file2.txt
|
|
114
|
+
|
|
115
|
+
# Compare JSON files with key-based comparison
|
|
116
|
+
compare-files data1.json data2.json --json-compare-mode key-based --json-key-field id
|
|
117
|
+
|
|
118
|
+
# Compare HDF5 files with specific options
|
|
119
|
+
compare-files data1.h5 data2.h5 --h5-table table1,table2 --h5-rtol 1e-6
|
|
120
|
+
|
|
121
|
+
# Compare binary files with similarity check
|
|
122
|
+
compare-files binary1.bin binary2.bin --similarity
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## 4. Test Case Format
|
|
126
|
+
|
|
127
|
+
### JSON Format
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"setup": {
|
|
132
|
+
"environment_variables": {
|
|
133
|
+
"TEST_ENV": "development",
|
|
134
|
+
"API_URL": "http://localhost:8080",
|
|
135
|
+
"DEBUG_MODE": "true"
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"test_cases": [
|
|
139
|
+
{
|
|
140
|
+
"name": "Environment Variable Test",
|
|
141
|
+
"command": "python",
|
|
142
|
+
"args": ["-c", "import os; print(f'Environment: {os.environ.get(\"TEST_ENV\")}')"],
|
|
143
|
+
"expected": {
|
|
144
|
+
"return_code": 0,
|
|
145
|
+
"output_contains": ["Environment: development"]
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"name": "File Comparison Test",
|
|
150
|
+
"command": "compare-files",
|
|
151
|
+
"args": ["file1.txt", "file2.txt", "--verbose"],
|
|
152
|
+
"expected": {
|
|
153
|
+
"return_code": 0,
|
|
154
|
+
"output_contains": ["Files are identical"],
|
|
155
|
+
"output_matches": [".*comparison completed.*"]
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### YAML Format
|
|
163
|
+
|
|
164
|
+
```yaml
|
|
165
|
+
setup:
|
|
166
|
+
environment_variables:
|
|
167
|
+
TEST_ENV: "production"
|
|
168
|
+
DATABASE_URL: "sqlite:///test.db"
|
|
169
|
+
|
|
170
|
+
test_cases:
|
|
171
|
+
- name: Environment Test
|
|
172
|
+
command: python
|
|
173
|
+
args:
|
|
174
|
+
- "-c"
|
|
175
|
+
- "import os; print(f'DB: {os.environ.get(\"DATABASE_URL\")}')"
|
|
176
|
+
expected:
|
|
177
|
+
return_code: 0
|
|
178
|
+
output_contains:
|
|
179
|
+
- "DB: sqlite:///test.db"
|
|
180
|
+
|
|
181
|
+
- name: Directory Scan Test
|
|
182
|
+
command: ls
|
|
183
|
+
args:
|
|
184
|
+
- -l
|
|
185
|
+
- docs/
|
|
186
|
+
expected:
|
|
187
|
+
return_code: 0
|
|
188
|
+
output_matches: ".*\\.md$"
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## 5. File Comparison Features
|
|
192
|
+
|
|
193
|
+
### Supported File Types
|
|
194
|
+
|
|
195
|
+
- **Text Files**: Plain text, source code, markdown, etc.
|
|
196
|
+
- **JSON Files**: With exact or key-based comparison
|
|
197
|
+
- **HDF5 Files**: Structure and content comparison with numerical tolerance
|
|
198
|
+
- **Binary Files**: With optional similarity index calculation
|
|
199
|
+
|
|
200
|
+
### Comparison Options
|
|
201
|
+
|
|
202
|
+
#### Text Comparison
|
|
203
|
+
```bash
|
|
204
|
+
compare-files file1.txt file2.txt \
|
|
205
|
+
--start-line 10 \
|
|
206
|
+
--end-line 20 \
|
|
207
|
+
--encoding utf-8
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### JSON Comparison
|
|
211
|
+
```bash
|
|
212
|
+
compare-files data1.json data2.json \
|
|
213
|
+
--json-compare-mode key-based \
|
|
214
|
+
--json-key-field id,name
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### HDF5 Comparison
|
|
218
|
+
|
|
219
|
+
**New Feature**: HDF5 group path expansion! By default, when you specify a group path in `--h5-table`, the comparator will automatically expand and compare all datasets and subgroups within that path.
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
# Compare specific tables/groups with auto-expansion (default behavior)
|
|
223
|
+
compare-files data1.h5 data2.h5 \
|
|
224
|
+
--h5-table group1/subgroupA \
|
|
225
|
+
--h5-rtol 1e-5 \
|
|
226
|
+
--h5-atol 1e-8
|
|
227
|
+
|
|
228
|
+
# Disable auto-expansion to compare only the specified path itself
|
|
229
|
+
compare-files data1.h5 data2.h5 \
|
|
230
|
+
--h5-table group1 \
|
|
231
|
+
--h5-no-expand-path
|
|
232
|
+
|
|
233
|
+
# Use regex patterns (also supports auto-expansion)
|
|
234
|
+
compare-files data1.h5 data2.h5 \
|
|
235
|
+
--h5-table-regex "group1/.*" \
|
|
236
|
+
--h5-structure-only
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
#### Binary Comparison
|
|
240
|
+
```bash
|
|
241
|
+
compare-files binary1.bin binary2.bin \
|
|
242
|
+
--similarity \
|
|
243
|
+
--chunk-size 16384
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Output Formats
|
|
247
|
+
|
|
248
|
+
- **Text**: Human-readable diff output
|
|
249
|
+
- **JSON**: Structured comparison results
|
|
250
|
+
- **HTML**: Visual diff with syntax highlighting
|
|
251
|
+
|
|
252
|
+
## 6. System Architecture
|
|
253
|
+
|
|
254
|
+
### Enhanced Architecture Flow
|
|
255
|
+
|
|
256
|
+
```mermaid
|
|
257
|
+
graph TD
|
|
258
|
+
A[Test Cases] --> B{Execution Mode}
|
|
259
|
+
B -->|Sequential| C[JSONRunner/YAMLRunner]
|
|
260
|
+
B -->|Parallel| D[ParallelRunner]
|
|
261
|
+
D --> E[ThreadPoolExecutor/ProcessPoolExecutor]
|
|
262
|
+
C --> F[Command Parser]
|
|
263
|
+
E --> F
|
|
264
|
+
F --> G[Path Resolver]
|
|
265
|
+
G --> H[Sub-process Execution]
|
|
266
|
+
H --> I[Assertion Engine]
|
|
267
|
+
I --> J[Thread-Safe Result Collection]
|
|
268
|
+
J --> K[Report Generator]
|
|
269
|
+
L[File Comparator] --> M[Text Comparator]
|
|
270
|
+
L --> N[JSON Comparator]
|
|
271
|
+
L --> O[HDF5 Comparator]
|
|
272
|
+
L --> P[Binary Comparator]
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### Core Components
|
|
276
|
+
|
|
277
|
+
#### 1. Intelligent Command Parser
|
|
278
|
+
```python
|
|
279
|
+
# Handles complex commands like "python ./script.py"
|
|
280
|
+
command_parts = case["command"].split()
|
|
281
|
+
if len(command_parts) > 1:
|
|
282
|
+
actual_command = resolve_command(command_parts[0]) # "python"
|
|
283
|
+
script_parts = resolve_paths(command_parts[1:]) # "./script.py" -> full path
|
|
284
|
+
final_command = f"{actual_command} {' '.join(script_parts)}"
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
#### 2. Enhanced Path Resolver
|
|
288
|
+
```python
|
|
289
|
+
def resolve_command(self, command: str) -> str:
|
|
290
|
+
system_commands = {
|
|
291
|
+
'echo', 'ping', 'python', 'node', 'java', 'docker', ...
|
|
292
|
+
}
|
|
293
|
+
if command in system_commands or Path(command).is_absolute():
|
|
294
|
+
return command
|
|
295
|
+
return str(self.workspace / command)
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
#### 3. Parallel Runner Base Class
|
|
299
|
+
```python
|
|
300
|
+
class ParallelRunner(BaseRunner):
|
|
301
|
+
def __init__(self, max_workers=None, execution_mode="thread"):
|
|
302
|
+
self.max_workers = max_workers or os.cpu_count()
|
|
303
|
+
self.execution_mode = execution_mode
|
|
304
|
+
self._results_lock = threading.Lock()
|
|
305
|
+
self._print_lock = threading.Lock()
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
## 7. Advanced Usage
|
|
309
|
+
|
|
310
|
+
### Performance Testing
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
# Quick performance test
|
|
314
|
+
python performance_test.py
|
|
315
|
+
|
|
316
|
+
# Unit tests for parallel functionality
|
|
317
|
+
python -m pytest tests/test_parallel_runner.py -v
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Error Handling and Fallback
|
|
321
|
+
|
|
322
|
+
```python
|
|
323
|
+
try:
|
|
324
|
+
runner = ParallelJSONRunner(config_file="test_cases.json")
|
|
325
|
+
success = runner.run_tests()
|
|
326
|
+
|
|
327
|
+
if not success:
|
|
328
|
+
# Check failed tests
|
|
329
|
+
for detail in runner.results["details"]:
|
|
330
|
+
if detail["status"] == "failed":
|
|
331
|
+
print(f"Failed test: {detail['name']}")
|
|
332
|
+
print(f"Error: {detail['message']}")
|
|
333
|
+
|
|
334
|
+
except Exception as e:
|
|
335
|
+
print(f"Execution error: {e}")
|
|
336
|
+
# Fallback to sequential execution
|
|
337
|
+
runner.run_tests_sequential()
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### Best Practices
|
|
341
|
+
|
|
342
|
+
1. **Choose Appropriate Concurrency**:
|
|
343
|
+
```python
|
|
344
|
+
import os
|
|
345
|
+
|
|
346
|
+
# For CPU-intensive tasks
|
|
347
|
+
max_workers = os.cpu_count()
|
|
348
|
+
|
|
349
|
+
# For I/O-intensive tasks
|
|
350
|
+
max_workers = os.cpu_count() * 2
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
2. **Test Case Design**:
|
|
354
|
+
- ✅ Ensure test independence (no dependencies between tests)
|
|
355
|
+
- ✅ Avoid shared resource conflicts (different files/ports)
|
|
356
|
+
- ✅ Use relative paths (framework handles resolution automatically)
|
|
357
|
+
|
|
358
|
+
3. **Debugging**:
|
|
359
|
+
```python
|
|
360
|
+
# Enable verbose output for debugging
|
|
361
|
+
runner = ParallelJSONRunner(
|
|
362
|
+
config_file="test_cases.json",
|
|
363
|
+
max_workers=1, # Set to 1 for easier debugging
|
|
364
|
+
execution_mode="thread"
|
|
365
|
+
)
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## 8. Example Demonstrations
|
|
369
|
+
|
|
370
|
+
### Input Example
|
|
371
|
+
|
|
372
|
+
```json
|
|
373
|
+
{
|
|
374
|
+
"test_cases": [
|
|
375
|
+
{
|
|
376
|
+
"name": "Python Version Check",
|
|
377
|
+
"command": "python --version",
|
|
378
|
+
"args": [],
|
|
379
|
+
"expected": {
|
|
380
|
+
"output_matches": "Python 3\\.[89]\\.",
|
|
381
|
+
"return_code": 0
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
"name": "File Processing Test",
|
|
386
|
+
"command": "python ./process_file.py",
|
|
387
|
+
"args": ["input.txt", "--output", "result.txt"],
|
|
388
|
+
"expected": {
|
|
389
|
+
"return_code": 0,
|
|
390
|
+
"output_contains": ["Processing completed"]
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
]
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Output Report
|
|
398
|
+
|
|
399
|
+
```
|
|
400
|
+
Test Results Summary:
|
|
401
|
+
Total Tests: 15
|
|
402
|
+
Passed: 15
|
|
403
|
+
Failed: 0
|
|
404
|
+
|
|
405
|
+
Performance Statistics:
|
|
406
|
+
Sequential execution time: 12.45 seconds
|
|
407
|
+
Parallel execution time: 3.21 seconds
|
|
408
|
+
Speedup ratio: 3.88x
|
|
409
|
+
|
|
410
|
+
Detailed Results:
|
|
411
|
+
✓ Python Version Check
|
|
412
|
+
✓ File Processing Test
|
|
413
|
+
✓ JSON Comparison Test
|
|
414
|
+
...
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
## 9. Troubleshooting
|
|
418
|
+
|
|
419
|
+
### Common Issues
|
|
420
|
+
|
|
421
|
+
1. **Process Mode Serialization Error**
|
|
422
|
+
- **Cause**: Objects contain non-serializable attributes (like locks)
|
|
423
|
+
- **Solution**: Use independent process worker functions
|
|
424
|
+
|
|
425
|
+
2. **Path Resolution Error**
|
|
426
|
+
- **Cause**: System commands treated as relative paths
|
|
427
|
+
- **Solution**: Update `PathResolver` system command list
|
|
428
|
+
|
|
429
|
+
3. **Performance Not Improved**
|
|
430
|
+
- **Cause**: Test cases too short, parallel overhead exceeds benefits
|
|
431
|
+
- **Solution**: Increase test case count or use more complex tests
|
|
432
|
+
|
|
433
|
+
4. **Command Not Found Error**
|
|
434
|
+
- **Cause**: Complex commands like `"python ./script.py"` not parsed correctly
|
|
435
|
+
- **Solution**: Framework now automatically handles this (fixed in latest version)
|
|
436
|
+
|
|
437
|
+
### Debug Tips
|
|
438
|
+
|
|
439
|
+
```python
|
|
440
|
+
# Enable detailed logging
|
|
441
|
+
import logging
|
|
442
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
443
|
+
|
|
444
|
+
# Check detailed results
|
|
445
|
+
import json
|
|
446
|
+
print(json.dumps(runner.results, indent=2, ensure_ascii=False))
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
## 10. Extension and Customization
|
|
450
|
+
|
|
451
|
+
### Adding New Runners
|
|
452
|
+
|
|
453
|
+
```python
|
|
454
|
+
class XMLRunner(BaseRunner):
|
|
455
|
+
def load_test_cases(self):
|
|
456
|
+
import xml.etree.ElementTree as ET
|
|
457
|
+
# Parse XML structure and convert to TestCase objects
|
|
458
|
+
|
|
459
|
+
class CustomParallelRunner(ParallelRunner):
|
|
460
|
+
def custom_preprocessing(self):
|
|
461
|
+
# Add custom logic before test execution
|
|
462
|
+
pass
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Custom Assertions
|
|
466
|
+
|
|
467
|
+
```python
|
|
468
|
+
class CustomAssertions(Assertions):
|
|
469
|
+
@staticmethod
|
|
470
|
+
def performance_threshold(execution_time, max_time):
|
|
471
|
+
if execution_time > max_time:
|
|
472
|
+
raise AssertionError(f"Execution too slow: {execution_time}s > {max_time}s")
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
## 11. Version Compatibility
|
|
476
|
+
|
|
477
|
+
- **Python Version**: 3.6+
|
|
478
|
+
- **Dependencies**: Standard library only (no external dependencies for core functionality)
|
|
479
|
+
- **Backward Compatibility**: Fully compatible with existing `JSONRunner` code
|
|
480
|
+
- **Platform Support**: Windows, macOS, Linux
|
|
481
|
+
|
|
482
|
+
## 12. Performance Benchmarks
|
|
483
|
+
|
|
484
|
+
| Test Scenario | Sequential | Parallel (Thread) | Parallel (Process) | Speedup |
|
|
485
|
+
|---------------|------------|-------------------|-------------------|---------|
|
|
486
|
+
| 10 I/O tests | 5.2s | 1.4s | 2.1s | 3.7x |
|
|
487
|
+
| 20 CPU tests | 12.8s | 8.9s | 6.2s | 2.1x |
|
|
488
|
+
| Mixed tests | 8.5s | 2.3s | 3.1s | 3.7x |
|
|
489
|
+
|
|
490
|
+
## 13. Contributing
|
|
491
|
+
|
|
492
|
+
1. Fork the repository
|
|
493
|
+
2. Create a feature branch
|
|
494
|
+
3. Add tests for new functionality
|
|
495
|
+
4. Ensure all tests pass: `python -m pytest tests/ -v`
|
|
496
|
+
5. Submit a pull request
|
|
497
|
+
|
|
498
|
+
## 14. License
|
|
499
|
+
|
|
500
|
+
This project is licensed under the MIT License - see the LICENSE file for details.
|
|
501
|
+
|
|
502
|
+
---
|
|
503
|
+
|
|
504
|
+
## 📚 Complete Documentation
|
|
505
|
+
|
|
506
|
+
For comprehensive documentation including detailed Setup Module guide, API reference, and advanced usage examples, see:
|
|
507
|
+
|
|
508
|
+
**[📖 Complete User Manual](https://github.com/ozil111/cli-test-framework/blob/main/docs/user_manual.md)**
|
|
509
|
+
|
|
510
|
+
The user manual includes:
|
|
511
|
+
- 🔧 **Setup Module**: Complete guide for environment variables and custom plugins
|
|
512
|
+
- 🚀 **Parallel Testing**: Advanced parallel execution strategies
|
|
513
|
+
- 📁 **File Comparison**: Detailed comparison capabilities for all file types
|
|
514
|
+
- 🔌 **API Reference**: Full API documentation and examples
|
|
515
|
+
- 🛠️ **Troubleshooting**: Common issues and solutions
|
|
516
|
+
- 📝 **Best Practices**: Recommended patterns and configurations
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
**🚀 Ready to supercharge your testing workflow with setup modules, parallel execution and advanced file comparison!**
|
|
521
|
+
|
|
522
|
+
For detailed parallel testing guide, see: [PARALLEL_TESTING_GUIDE.md](https://github.com/ozil111/cli-test-framework/blob/main/PARALLEL_TESTING_GUIDE.md)
|
|
@@ -25,7 +25,7 @@ This is a lightweight and extensible automated testing framework that supports d
|
|
|
25
25
|
|
|
26
26
|
```bash
|
|
27
27
|
pip install cli-test-framework
|
|
28
|
-
Python >= 3.
|
|
28
|
+
Python >= 3.9
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
### Sequential Execution
|
|
@@ -179,12 +179,25 @@ compare-files data1.json data2.json \
|
|
|
179
179
|
```
|
|
180
180
|
|
|
181
181
|
#### HDF5 Comparison
|
|
182
|
+
|
|
183
|
+
**New Feature**: HDF5 group path expansion! By default, when you specify a group path in `--h5-table`, the comparator will automatically expand and compare all datasets and subgroups within that path.
|
|
184
|
+
|
|
182
185
|
```bash
|
|
186
|
+
# Compare specific tables/groups with auto-expansion (default behavior)
|
|
183
187
|
compare-files data1.h5 data2.h5 \
|
|
184
|
-
--h5-table
|
|
185
|
-
--h5-structure-only \
|
|
188
|
+
--h5-table group1/subgroupA \
|
|
186
189
|
--h5-rtol 1e-5 \
|
|
187
190
|
--h5-atol 1e-8
|
|
191
|
+
|
|
192
|
+
# Disable auto-expansion to compare only the specified path itself
|
|
193
|
+
compare-files data1.h5 data2.h5 \
|
|
194
|
+
--h5-table group1 \
|
|
195
|
+
--h5-no-expand-path
|
|
196
|
+
|
|
197
|
+
# Use regex patterns (also supports auto-expansion)
|
|
198
|
+
compare-files data1.h5 data2.h5 \
|
|
199
|
+
--h5-table-regex "group1/.*" \
|
|
200
|
+
--h5-structure-only
|
|
188
201
|
```
|
|
189
202
|
|
|
190
203
|
#### Binary Comparison
|
|
@@ -456,7 +469,7 @@ This project is licensed under the MIT License - see the LICENSE file for detail
|
|
|
456
469
|
|
|
457
470
|
For comprehensive documentation including detailed Setup Module guide, API reference, and advanced usage examples, see:
|
|
458
471
|
|
|
459
|
-
**[📖 Complete User Manual](docs/user_manual.md)**
|
|
472
|
+
**[📖 Complete User Manual](https://github.com/ozil111/cli-test-framework/blob/main/docs/user_manual.md)**
|
|
460
473
|
|
|
461
474
|
The user manual includes:
|
|
462
475
|
- 🔧 **Setup Module**: Complete guide for environment variables and custom plugins
|
|
@@ -470,4 +483,4 @@ The user manual includes:
|
|
|
470
483
|
|
|
471
484
|
**🚀 Ready to supercharge your testing workflow with setup modules, parallel execution and advanced file comparison!**
|
|
472
485
|
|
|
473
|
-
For detailed parallel testing guide, see: [PARALLEL_TESTING_GUIDE.md](PARALLEL_TESTING_GUIDE.md)
|
|
486
|
+
For detailed parallel testing guide, see: [PARALLEL_TESTING_GUIDE.md](https://github.com/ozil111/cli-test-framework/blob/main/PARALLEL_TESTING_GUIDE.md)
|
|
@@ -27,7 +27,7 @@ The CLI Testing Framework is a powerful tool designed for testing command-line a
|
|
|
27
27
|
## Installation
|
|
28
28
|
|
|
29
29
|
### Prerequisites
|
|
30
|
-
- Python 3.
|
|
30
|
+
- Python 3.9 or higher
|
|
31
31
|
- pip package manager
|
|
32
32
|
|
|
33
33
|
### Basic Installation
|
|
@@ -37,7 +37,7 @@ pip install cli-test-framework
|
|
|
37
37
|
|
|
38
38
|
### Development Installation
|
|
39
39
|
```bash
|
|
40
|
-
git clone https://github.com/
|
|
40
|
+
git clone https://github.com/ozil111/cli-test-framework.git
|
|
41
41
|
cd cli-test-framework
|
|
42
42
|
pip install -e .
|
|
43
43
|
```
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
from setuptools import setup, find_packages
|
|
2
2
|
import os
|
|
3
3
|
|
|
4
|
-
# Read the contents of the
|
|
4
|
+
# Read the contents of the README file
|
|
5
5
|
this_directory = os.path.abspath(os.path.dirname(__file__))
|
|
6
|
-
with open(os.path.join(this_directory, '
|
|
6
|
+
with open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f:
|
|
7
7
|
long_description = f.read()
|
|
8
8
|
|
|
9
9
|
setup(
|
|
10
10
|
name="cli-test-framework",
|
|
11
|
-
version="0.3.
|
|
11
|
+
version="0.3.4",
|
|
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.",
|
|
15
15
|
long_description=long_description,
|
|
16
16
|
long_description_content_type="text/markdown",
|
|
17
|
-
url="https://github.com/
|
|
17
|
+
url="https://github.com/ozil111/cli-test-framework",
|
|
18
18
|
packages=find_packages(where="src"),
|
|
19
19
|
package_dir={"": "src"},
|
|
20
20
|
install_requires=[
|
|
21
21
|
"dukpy==0.5.0",
|
|
22
|
-
"h5py>=3.
|
|
23
|
-
"numpy>=2.0.
|
|
22
|
+
"h5py>=3.10.0",
|
|
23
|
+
"numpy>=1.24.0,<2.0.0",
|
|
24
|
+
"PyYAML>=6.0",
|
|
24
25
|
"setuptools>=75.8.0",
|
|
25
26
|
"wheel>=0.45.1"
|
|
26
27
|
],
|
|
@@ -41,8 +42,8 @@ setup(
|
|
|
41
42
|
],
|
|
42
43
|
python_requires='>=3.9',
|
|
43
44
|
project_urls={
|
|
44
|
-
'Documentation': 'https://github.com/
|
|
45
|
-
'Source': 'https://github.com/
|
|
46
|
-
'Tracker': 'https://github.com/
|
|
45
|
+
'Documentation': 'https://github.com/ozil111/cli-test-framework/blob/main/docs/user_manual.md',
|
|
46
|
+
'Source': 'https://github.com/ozil111/cli-test-framework',
|
|
47
|
+
'Tracker': 'https://github.com/ozil111/cli-test-framework/issues',
|
|
47
48
|
},
|
|
48
49
|
)
|
|
@@ -5,7 +5,7 @@ This package provides tools for testing command-line applications and scripts
|
|
|
5
5
|
with support for parallel execution and advanced file comparison capabilities.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
__version__ = "0.3.
|
|
8
|
+
__version__ = "0.3.3"
|
|
9
9
|
__author__ = "Xiaotong Wang"
|
|
10
10
|
__email__ = "xiaotongwang98@gmail.com"
|
|
11
11
|
|
{cli_test_framework-0.3.2 → cli_test_framework-0.3.4}/src/cli_test_framework/commands/compare.py
RENAMED
|
@@ -67,6 +67,8 @@ def parse_arguments():
|
|
|
67
67
|
help="Relative tolerance for numerical comparison in HDF5 files")
|
|
68
68
|
h5_group.add_argument("--h5-atol", type=float, default=1e-8,
|
|
69
69
|
help="Absolute tolerance for numerical comparison in HDF5 files")
|
|
70
|
+
h5_group.add_argument("--h5-no-expand-path", dest="h5_expand_path", action="store_false",
|
|
71
|
+
help="Do not expand HDF5 group paths to compare all sub-items.")
|
|
70
72
|
|
|
71
73
|
return parser.parse_args()
|
|
72
74
|
|
|
@@ -148,6 +150,7 @@ def main():
|
|
|
148
150
|
comparator_kwargs["show_content_diff"] = args.h5_show_content_diff
|
|
149
151
|
comparator_kwargs["rtol"] = args.h5_rtol
|
|
150
152
|
comparator_kwargs["atol"] = args.h5_atol
|
|
153
|
+
comparator_kwargs["expand_path"] = args.h5_expand_path
|
|
151
154
|
|
|
152
155
|
if file_type == "binary":
|
|
153
156
|
comparator_kwargs["similarity"] = args.similarity
|