@intentsolutionsio/performance-test-suite 1.0.0 → 1.0.8
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.
- package/README.md +8 -0
- package/agents/performance-tester.md +40 -3
- package/package.json +1 -1
- package/skills/running-performance-tests/SKILL.md +14 -6
- package/skills/running-performance-tests/references/README.md +0 -1
- package/skills/running-performance-tests/scripts/README.md +1 -1
- package/skills/running-performance-tests/scripts/analyze_results.py +33 -36
- package/skills/running-performance-tests/scripts/init_test.py +12 -19
- package/skills/running-performance-tests/scripts/{run_test.sh → run_test.py} +16 -16
package/README.md
CHANGED
|
@@ -64,6 +64,7 @@ export let options = {
|
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
**Validates:**
|
|
67
|
+
|
|
67
68
|
- Normal performance under expected load
|
|
68
69
|
- Response times remain acceptable
|
|
69
70
|
- Error rates stay low
|
|
@@ -87,6 +88,7 @@ export let options = {
|
|
|
87
88
|
```
|
|
88
89
|
|
|
89
90
|
**Validates:**
|
|
91
|
+
|
|
90
92
|
- Maximum capacity before failure
|
|
91
93
|
- Graceful degradation under stress
|
|
92
94
|
- Recovery after overload
|
|
@@ -109,6 +111,7 @@ export let options = {
|
|
|
109
111
|
```
|
|
110
112
|
|
|
111
113
|
**Validates:**
|
|
114
|
+
|
|
112
115
|
- Auto-scaling response
|
|
113
116
|
- Rate limiting effectiveness
|
|
114
117
|
- System stability during surge
|
|
@@ -130,6 +133,7 @@ export let options = {
|
|
|
130
133
|
```
|
|
131
134
|
|
|
132
135
|
**Validates:**
|
|
136
|
+
|
|
133
137
|
- Memory leaks over time
|
|
134
138
|
- Resource exhaustion
|
|
135
139
|
- Connection pool issues
|
|
@@ -165,24 +169,28 @@ export let options = {
|
|
|
165
169
|
The agent identifies common performance issues:
|
|
166
170
|
|
|
167
171
|
### High CPU Usage
|
|
172
|
+
|
|
168
173
|
- Inefficient algorithms
|
|
169
174
|
- Missing caching
|
|
170
175
|
- Excessive computations
|
|
171
176
|
- Unoptimized loops
|
|
172
177
|
|
|
173
178
|
### High Memory Usage
|
|
179
|
+
|
|
174
180
|
- Memory leaks
|
|
175
181
|
- Large object retention
|
|
176
182
|
- Inefficient data structures
|
|
177
183
|
- Missing garbage collection
|
|
178
184
|
|
|
179
185
|
### Slow Database
|
|
186
|
+
|
|
180
187
|
- N+1 query problems
|
|
181
188
|
- Missing indexes
|
|
182
189
|
- Inefficient queries
|
|
183
190
|
- Connection pool exhaustion
|
|
184
191
|
|
|
185
192
|
### Network Saturation
|
|
193
|
+
|
|
186
194
|
- Large response payloads
|
|
187
195
|
- Missing compression
|
|
188
196
|
- Too many requests
|
|
@@ -1,8 +1,35 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: performance-tester
|
|
3
|
-
description:
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
description: Specialized agent for load testing, performance benchmarking, and bottleneck...
|
|
4
|
+
tools:
|
|
5
|
+
- Read
|
|
6
|
+
- Write
|
|
7
|
+
- Edit
|
|
8
|
+
- Bash
|
|
9
|
+
- Glob
|
|
10
|
+
- Grep
|
|
11
|
+
- WebFetch
|
|
12
|
+
- WebSearch
|
|
13
|
+
- Task
|
|
14
|
+
- TodoWrite
|
|
15
|
+
model: sonnet
|
|
16
|
+
color: red
|
|
17
|
+
version: 1.0.0
|
|
18
|
+
author: Jeremy Longshore <jeremy@intentsolutions.io>
|
|
19
|
+
tags:
|
|
20
|
+
- testing
|
|
21
|
+
- performance
|
|
22
|
+
- tester
|
|
23
|
+
disallowedTools: []
|
|
24
|
+
skills: []
|
|
25
|
+
background: false
|
|
26
|
+
# ── upgrade levers — uncomment + set when tuning this agent ──
|
|
27
|
+
# effort: high # reasoning depth: low/medium/high/xhigh/max (omit = inherit session)
|
|
28
|
+
# maxTurns: 50 # cap the agentic loop (omit = engine default)
|
|
29
|
+
# memory: project # persistent scope: user/project/local (omit = ephemeral)
|
|
30
|
+
# isolation: worktree # run in an isolated git worktree
|
|
31
|
+
# initialPrompt: "…" # seed the agent's first turn
|
|
32
|
+
# hooks / mcpServers / permissionMode → set at the PLUGIN level, not on a plugin agent
|
|
6
33
|
---
|
|
7
34
|
# Performance Test Suite Agent
|
|
8
35
|
|
|
@@ -11,6 +38,7 @@ You are a performance testing specialist that designs and executes load tests, a
|
|
|
11
38
|
## Your Capabilities
|
|
12
39
|
|
|
13
40
|
### 1. Load Testing
|
|
41
|
+
|
|
14
42
|
- **Gradual ramp-up** - Incrementally increase load
|
|
15
43
|
- **Sustained load** - Constant traffic over time
|
|
16
44
|
- **Peak load** - Maximum capacity testing
|
|
@@ -18,24 +46,28 @@ You are a performance testing specialist that designs and executes load tests, a
|
|
|
18
46
|
- **Think time** - Realistic user behavior patterns
|
|
19
47
|
|
|
20
48
|
### 2. Stress Testing
|
|
49
|
+
|
|
21
50
|
- **Breaking point identification** - Find maximum capacity
|
|
22
51
|
- **Graceful degradation** - Verify failure handling
|
|
23
52
|
- **Recovery testing** - System recovery after overload
|
|
24
53
|
- **Resource saturation** - CPU, memory, disk, network limits
|
|
25
54
|
|
|
26
55
|
### 3. Spike Testing
|
|
56
|
+
|
|
27
57
|
- **Sudden traffic surges** - Rapid load increases
|
|
28
58
|
- **Flash sale scenarios** - High-traffic events
|
|
29
59
|
- **Auto-scaling validation** - Infrastructure response
|
|
30
60
|
- **Rate limiting** - Throttling effectiveness
|
|
31
61
|
|
|
32
62
|
### 4. Endurance Testing (Soak Testing)
|
|
63
|
+
|
|
33
64
|
- **Memory leaks** - Long-running stability
|
|
34
65
|
- **Resource exhaustion** - Gradual degradation
|
|
35
66
|
- **Connection pool issues** - Resource management
|
|
36
67
|
- **Database connection leaks** - Connection handling
|
|
37
68
|
|
|
38
69
|
### 5. Metrics Analysis
|
|
70
|
+
|
|
39
71
|
- **Response times** - P50, P95, P99 percentiles
|
|
40
72
|
- **Throughput** - Requests per second
|
|
41
73
|
- **Error rates** - Success vs failure ratio
|
|
@@ -45,6 +77,7 @@ You are a performance testing specialist that designs and executes load tests, a
|
|
|
45
77
|
## When to Activate
|
|
46
78
|
|
|
47
79
|
Activate when the user needs to:
|
|
80
|
+
|
|
48
81
|
- Perform load or stress testing
|
|
49
82
|
- Benchmark application performance
|
|
50
83
|
- Identify performance bottlenecks
|
|
@@ -220,6 +253,7 @@ class WebsiteUser(HttpUser):
|
|
|
220
253
|
## Metrics to Report
|
|
221
254
|
|
|
222
255
|
### Response Time Metrics
|
|
256
|
+
|
|
223
257
|
- **Average** - Mean response time
|
|
224
258
|
- **Median (P50)** - 50th percentile
|
|
225
259
|
- **P95** - 95% of requests faster than this
|
|
@@ -227,16 +261,19 @@ class WebsiteUser(HttpUser):
|
|
|
227
261
|
- **Max** - Slowest request
|
|
228
262
|
|
|
229
263
|
### Throughput Metrics
|
|
264
|
+
|
|
230
265
|
- **Requests/second** - Total throughput
|
|
231
266
|
- **Data transferred** - Bandwidth usage
|
|
232
267
|
- **Concurrent users** - Active connections
|
|
233
268
|
|
|
234
269
|
### Error Metrics
|
|
270
|
+
|
|
235
271
|
- **Error rate** - Percentage of failed requests
|
|
236
272
|
- **Error types** - Breakdown by HTTP status
|
|
237
273
|
- **First error** - When errors started appearing
|
|
238
274
|
|
|
239
275
|
### Resource Metrics
|
|
276
|
+
|
|
240
277
|
- **CPU usage** - Average and peak
|
|
241
278
|
- **Memory usage** - Average and peak
|
|
242
279
|
- **Network I/O** - Bandwidth utilization
|
package/package.json
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: running-performance-tests
|
|
3
|
-
description:
|
|
4
|
-
|
|
3
|
+
description: 'Execute load testing, stress testing, and performance benchmarking.
|
|
4
|
+
|
|
5
5
|
Use when performing specialized testing.
|
|
6
|
-
Trigger with phrases like "run load tests", "test performance", or "benchmark the system".
|
|
7
6
|
|
|
7
|
+
Trigger with phrases like "run load tests", "test performance", or "benchmark the
|
|
8
|
+
system".
|
|
9
|
+
|
|
10
|
+
'
|
|
8
11
|
allowed-tools: Read, Write, Edit, Grep, Glob, Bash(test:perf-*)
|
|
9
12
|
version: 1.0.0
|
|
10
13
|
author: Jeremy Longshore <jeremy@intentsolutions.io>
|
|
11
14
|
license: MIT
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
tags:
|
|
16
|
+
- testing
|
|
17
|
+
- performance
|
|
18
|
+
- performance-tests
|
|
19
|
+
compatibility: Designed for Claude Code, also compatible with Codex and OpenClaw
|
|
14
20
|
---
|
|
15
21
|
# Performance Test Suite
|
|
16
22
|
|
|
@@ -79,6 +85,7 @@ Execute load testing, stress testing, and performance benchmarking to identify b
|
|
|
79
85
|
## Examples
|
|
80
86
|
|
|
81
87
|
**k6 load test script:**
|
|
88
|
+
|
|
82
89
|
```javascript
|
|
83
90
|
import http from 'k6/http';
|
|
84
91
|
import { check, sleep } from 'k6';
|
|
@@ -107,6 +114,7 @@ export default function () {
|
|
|
107
114
|
```
|
|
108
115
|
|
|
109
116
|
**Artillery test configuration:**
|
|
117
|
+
|
|
110
118
|
```yaml
|
|
111
119
|
config:
|
|
112
120
|
target: "https://api.test.com"
|
|
@@ -137,4 +145,4 @@ scenarios:
|
|
|
137
145
|
- Locust (Python): https://docs.locust.io/
|
|
138
146
|
- Apache JMeter: https://jmeter.apache.org/
|
|
139
147
|
- autocannon (Node.js): https://github.com/mcollina/autocannon
|
|
140
|
-
- Performance testing best practices:
|
|
148
|
+
- Performance testing best practices:
|
|
@@ -6,6 +6,6 @@ Bundled resources for performance-test-suite skill
|
|
|
6
6
|
- [x] run_test.sh: Script to execute the performance test using k6 or other tools.
|
|
7
7
|
- [x] analyze_results.py: Script to analyze the test results and generate a report.
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
## Auto-Generated
|
|
10
|
+
|
|
11
11
|
Scripts generated on 2025-12-10 03:48:17
|
|
@@ -5,31 +5,25 @@ Script to analyze the test results and generate a report.
|
|
|
5
5
|
Generated: 2025-12-10 03:48:17
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import os
|
|
9
8
|
import json
|
|
10
9
|
import argparse
|
|
11
10
|
from pathlib import Path
|
|
12
|
-
from typing import Dict
|
|
11
|
+
from typing import Dict
|
|
13
12
|
from datetime import datetime
|
|
14
13
|
|
|
14
|
+
|
|
15
15
|
class Analyzer:
|
|
16
16
|
def __init__(self, target_path: str):
|
|
17
17
|
self.target_path = Path(target_path)
|
|
18
|
-
self.stats = {
|
|
19
|
-
'total_files': 0,
|
|
20
|
-
'total_size': 0,
|
|
21
|
-
'file_types': {},
|
|
22
|
-
'issues': [],
|
|
23
|
-
'recommendations': []
|
|
24
|
-
}
|
|
18
|
+
self.stats = {"total_files": 0, "total_size": 0, "file_types": {}, "issues": [], "recommendations": []}
|
|
25
19
|
|
|
26
20
|
def analyze_directory(self) -> Dict:
|
|
27
21
|
"""Analyze directory structure and contents."""
|
|
28
22
|
if not self.target_path.exists():
|
|
29
|
-
self.stats[
|
|
23
|
+
self.stats["issues"].append(f"Path does not exist: {self.target_path}")
|
|
30
24
|
return self.stats
|
|
31
25
|
|
|
32
|
-
for file_path in self.target_path.rglob(
|
|
26
|
+
for file_path in self.target_path.rglob("*"):
|
|
33
27
|
if file_path.is_file():
|
|
34
28
|
self.analyze_file(file_path)
|
|
35
29
|
|
|
@@ -37,38 +31,38 @@ class Analyzer:
|
|
|
37
31
|
|
|
38
32
|
def analyze_file(self, file_path: Path):
|
|
39
33
|
"""Analyze individual file."""
|
|
40
|
-
self.stats[
|
|
41
|
-
self.stats[
|
|
34
|
+
self.stats["total_files"] += 1
|
|
35
|
+
self.stats["total_size"] += file_path.stat().st_size
|
|
42
36
|
|
|
43
37
|
# Track file types
|
|
44
38
|
ext = file_path.suffix.lower()
|
|
45
39
|
if ext:
|
|
46
|
-
self.stats[
|
|
40
|
+
self.stats["file_types"][ext] = self.stats["file_types"].get(ext, 0) + 1
|
|
47
41
|
|
|
48
42
|
# Check for potential issues
|
|
49
43
|
if file_path.stat().st_size > 100 * 1024 * 1024: # 100MB
|
|
50
|
-
self.stats[
|
|
44
|
+
self.stats["issues"].append(f"Large file: {file_path} ({file_path.stat().st_size // 1024 // 1024}MB)")
|
|
51
45
|
|
|
52
46
|
if file_path.stat().st_size == 0:
|
|
53
|
-
self.stats[
|
|
47
|
+
self.stats["issues"].append(f"Empty file: {file_path}")
|
|
54
48
|
|
|
55
49
|
def generate_recommendations(self):
|
|
56
50
|
"""Generate recommendations based on analysis."""
|
|
57
|
-
if self.stats[
|
|
58
|
-
self.stats[
|
|
51
|
+
if self.stats["total_files"] == 0:
|
|
52
|
+
self.stats["recommendations"].append("No files found - check target path")
|
|
59
53
|
|
|
60
|
-
if len(self.stats[
|
|
61
|
-
self.stats[
|
|
54
|
+
if len(self.stats["file_types"]) > 20:
|
|
55
|
+
self.stats["recommendations"].append("Many file types detected - consider organizing")
|
|
62
56
|
|
|
63
|
-
if self.stats[
|
|
64
|
-
self.stats[
|
|
57
|
+
if self.stats["total_size"] > 1024 * 1024 * 1024: # 1GB
|
|
58
|
+
self.stats["recommendations"].append("Large total size - consider archiving old data")
|
|
65
59
|
|
|
66
60
|
def generate_report(self) -> str:
|
|
67
61
|
"""Generate analysis report."""
|
|
68
62
|
report = []
|
|
69
|
-
report.append("\n" + "="*60)
|
|
70
|
-
report.append(
|
|
71
|
-
report.append("="*60)
|
|
63
|
+
report.append("\n" + "=" * 60)
|
|
64
|
+
report.append("ANALYSIS REPORT - performance-test-suite")
|
|
65
|
+
report.append("=" * 60)
|
|
72
66
|
report.append(f"Target: {self.target_path}")
|
|
73
67
|
report.append(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
74
68
|
report.append("")
|
|
@@ -80,34 +74,35 @@ class Analyzer:
|
|
|
80
74
|
report.append(f" File Types: {len(self.stats['file_types'])}")
|
|
81
75
|
|
|
82
76
|
# Top file types
|
|
83
|
-
if self.stats[
|
|
77
|
+
if self.stats["file_types"]:
|
|
84
78
|
report.append("\n📁 TOP FILE TYPES")
|
|
85
|
-
sorted_types = sorted(self.stats[
|
|
79
|
+
sorted_types = sorted(self.stats["file_types"].items(), key=lambda x: x[1], reverse=True)[:5]
|
|
86
80
|
for ext, count in sorted_types:
|
|
87
81
|
report.append(f" {ext or 'no extension'}: {count} files")
|
|
88
82
|
|
|
89
83
|
# Issues
|
|
90
|
-
if self.stats[
|
|
84
|
+
if self.stats["issues"]:
|
|
91
85
|
report.append(f"\n⚠️ ISSUES ({len(self.stats['issues'])})")
|
|
92
|
-
for issue in self.stats[
|
|
86
|
+
for issue in self.stats["issues"][:10]:
|
|
93
87
|
report.append(f" - {issue}")
|
|
94
|
-
if len(self.stats[
|
|
88
|
+
if len(self.stats["issues"]) > 10:
|
|
95
89
|
report.append(f" ... and {len(self.stats['issues']) - 10} more")
|
|
96
90
|
|
|
97
91
|
# Recommendations
|
|
98
|
-
if self.stats[
|
|
92
|
+
if self.stats["recommendations"]:
|
|
99
93
|
report.append("\n💡 RECOMMENDATIONS")
|
|
100
|
-
for rec in self.stats[
|
|
94
|
+
for rec in self.stats["recommendations"]:
|
|
101
95
|
report.append(f" - {rec}")
|
|
102
96
|
|
|
103
97
|
report.append("")
|
|
104
98
|
return "\n".join(report)
|
|
105
99
|
|
|
100
|
+
|
|
106
101
|
def main():
|
|
107
102
|
parser = argparse.ArgumentParser(description="Script to analyze the test results and generate a report.")
|
|
108
|
-
parser.add_argument(
|
|
109
|
-
parser.add_argument(
|
|
110
|
-
parser.add_argument(
|
|
103
|
+
parser.add_argument("target", help="Target directory to analyze")
|
|
104
|
+
parser.add_argument("--output", "-o", help="Output report file")
|
|
105
|
+
parser.add_argument("--json", action="store_true", help="Output as JSON")
|
|
111
106
|
|
|
112
107
|
args = parser.parse_args()
|
|
113
108
|
|
|
@@ -127,8 +122,10 @@ def main():
|
|
|
127
122
|
else:
|
|
128
123
|
print(output)
|
|
129
124
|
|
|
130
|
-
return 0 if len(stats[
|
|
125
|
+
return 0 if len(stats["issues"]) == 0 else 1
|
|
126
|
+
|
|
131
127
|
|
|
132
128
|
if __name__ == "__main__":
|
|
133
129
|
import sys
|
|
130
|
+
|
|
134
131
|
sys.exit(main())
|
|
@@ -5,23 +5,17 @@ Script to initialize a performance test based on user input.
|
|
|
5
5
|
Generated: 2025-12-10 03:48:17
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import os
|
|
9
8
|
import json
|
|
10
9
|
import argparse
|
|
11
10
|
from pathlib import Path
|
|
12
11
|
|
|
12
|
+
|
|
13
13
|
def create_project_structure(project_name: str, output_dir: str = "."):
|
|
14
14
|
"""Create project structure for performance-test-suite."""
|
|
15
15
|
base_path = Path(output_dir) / project_name
|
|
16
16
|
|
|
17
17
|
# Create directories
|
|
18
|
-
directories = [
|
|
19
|
-
base_path,
|
|
20
|
-
base_path / "config",
|
|
21
|
-
base_path / "data",
|
|
22
|
-
base_path / "output",
|
|
23
|
-
base_path / "logs"
|
|
24
|
-
]
|
|
18
|
+
directories = [base_path, base_path / "config", base_path / "data", base_path / "output", base_path / "logs"]
|
|
25
19
|
|
|
26
20
|
for dir_path in directories:
|
|
27
21
|
dir_path.mkdir(parents=True, exist_ok=True)
|
|
@@ -33,16 +27,12 @@ def create_project_structure(project_name: str, output_dir: str = "."):
|
|
|
33
27
|
"version": "1.0.0",
|
|
34
28
|
"skill": "performance-test-suite",
|
|
35
29
|
"category": "testing",
|
|
36
|
-
"created": time.strftime(
|
|
37
|
-
"settings": {
|
|
38
|
-
"debug": False,
|
|
39
|
-
"verbose": True,
|
|
40
|
-
"max_workers": 4
|
|
41
|
-
}
|
|
30
|
+
"created": time.strftime("%Y-%m-%d %H:%M:%S"),
|
|
31
|
+
"settings": {"debug": False, "verbose": True, "max_workers": 4},
|
|
42
32
|
}
|
|
43
33
|
|
|
44
34
|
config_file = base_path / "config" / "settings.json"
|
|
45
|
-
with open(config_file,
|
|
35
|
+
with open(config_file, "w") as f:
|
|
46
36
|
json.dump(config, f, indent=2)
|
|
47
37
|
print(f"✓ Created configuration: {config_file}")
|
|
48
38
|
|
|
@@ -67,11 +57,12 @@ See skill documentation for usage instructions.
|
|
|
67
57
|
|
|
68
58
|
return base_path
|
|
69
59
|
|
|
60
|
+
|
|
70
61
|
def main():
|
|
71
62
|
parser = argparse.ArgumentParser(description="Script to initialize a performance test based on user input.")
|
|
72
|
-
parser.add_argument(
|
|
73
|
-
parser.add_argument(
|
|
74
|
-
parser.add_argument(
|
|
63
|
+
parser.add_argument("--project", "-p", required=True, help="Project name")
|
|
64
|
+
parser.add_argument("--output", "-o", default=".", help="Output directory")
|
|
65
|
+
parser.add_argument("--config", "-c", help="Configuration file")
|
|
75
66
|
|
|
76
67
|
args = parser.parse_args()
|
|
77
68
|
|
|
@@ -82,13 +73,15 @@ def main():
|
|
|
82
73
|
# Load additional configuration
|
|
83
74
|
if Path(args.config).exists():
|
|
84
75
|
with open(args.config) as f:
|
|
85
|
-
|
|
76
|
+
json.load(f)
|
|
86
77
|
print(f"✓ Loaded configuration from {args.config}")
|
|
87
78
|
|
|
88
79
|
print(f"\n✅ Project initialized successfully at {project_path}")
|
|
89
80
|
return 0
|
|
90
81
|
|
|
82
|
+
|
|
91
83
|
if __name__ == "__main__":
|
|
92
84
|
import sys
|
|
93
85
|
import time
|
|
86
|
+
|
|
94
87
|
sys.exit(main())
|
|
@@ -5,12 +5,11 @@ Script to execute the performance test using k6 or other tools.
|
|
|
5
5
|
Generated: 2025-12-10 03:48:17
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
import os
|
|
9
8
|
import sys
|
|
10
9
|
import json
|
|
11
10
|
import argparse
|
|
12
11
|
from pathlib import Path
|
|
13
|
-
|
|
12
|
+
|
|
14
13
|
|
|
15
14
|
def process_file(file_path: Path) -> bool:
|
|
16
15
|
"""Process individual file."""
|
|
@@ -24,7 +23,7 @@ def process_file(file_path: Path) -> bool:
|
|
|
24
23
|
# This is a template that can be customized
|
|
25
24
|
|
|
26
25
|
try:
|
|
27
|
-
if file_path.suffix ==
|
|
26
|
+
if file_path.suffix == ".json":
|
|
28
27
|
with open(file_path) as f:
|
|
29
28
|
data = json.load(f)
|
|
30
29
|
print(f" ✓ Valid JSON with {len(data)} keys")
|
|
@@ -37,12 +36,13 @@ def process_file(file_path: Path) -> bool:
|
|
|
37
36
|
print(f" ✗ Error: {e}")
|
|
38
37
|
return False
|
|
39
38
|
|
|
39
|
+
|
|
40
40
|
def process_directory(dir_path: Path) -> int:
|
|
41
41
|
"""Process all files in directory."""
|
|
42
42
|
processed = 0
|
|
43
43
|
failed = 0
|
|
44
44
|
|
|
45
|
-
for file_path in dir_path.rglob(
|
|
45
|
+
for file_path in dir_path.rglob("*"):
|
|
46
46
|
if file_path.is_file():
|
|
47
47
|
if process_file(file_path):
|
|
48
48
|
processed += 1
|
|
@@ -51,28 +51,27 @@ def process_directory(dir_path: Path) -> int:
|
|
|
51
51
|
|
|
52
52
|
return processed, failed
|
|
53
53
|
|
|
54
|
+
|
|
54
55
|
def main():
|
|
55
|
-
parser = argparse.ArgumentParser(
|
|
56
|
-
|
|
57
|
-
)
|
|
58
|
-
parser.add_argument(
|
|
59
|
-
parser.add_argument(
|
|
60
|
-
parser.add_argument('--verbose', '-v', action='store_true', help='Verbose output')
|
|
61
|
-
parser.add_argument('--config', '-c', help='Configuration file')
|
|
56
|
+
parser = argparse.ArgumentParser(description="Script to execute the performance test using k6 or other tools.")
|
|
57
|
+
parser.add_argument("input", help="Input file or directory")
|
|
58
|
+
parser.add_argument("--output", "-o", help="Output directory")
|
|
59
|
+
parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output")
|
|
60
|
+
parser.add_argument("--config", "-c", help="Configuration file")
|
|
62
61
|
|
|
63
62
|
args = parser.parse_args()
|
|
64
63
|
|
|
65
64
|
input_path = Path(args.input)
|
|
66
65
|
|
|
67
|
-
print(
|
|
68
|
-
print(
|
|
69
|
-
print(
|
|
66
|
+
print("🚀 performance-test-suite - run_test.sh")
|
|
67
|
+
print(" Category: testing")
|
|
68
|
+
print(" Plugin: performance-test-suite")
|
|
70
69
|
print(f" Input: {input_path}")
|
|
71
70
|
|
|
72
71
|
if args.config:
|
|
73
72
|
if Path(args.config).exists():
|
|
74
73
|
with open(args.config) as f:
|
|
75
|
-
|
|
74
|
+
json.load(f)
|
|
76
75
|
print(f" Config: {args.config}")
|
|
77
76
|
|
|
78
77
|
# Process input
|
|
@@ -81,7 +80,7 @@ def main():
|
|
|
81
80
|
result = 0 if success else 1
|
|
82
81
|
elif input_path.is_dir():
|
|
83
82
|
processed, failed = process_directory(input_path)
|
|
84
|
-
print(
|
|
83
|
+
print("\n📊 SUMMARY")
|
|
85
84
|
print(f" ✅ Processed: {processed}")
|
|
86
85
|
print(f" ❌ Failed: {failed}")
|
|
87
86
|
result = 0 if failed == 0 else 1
|
|
@@ -96,5 +95,6 @@ def main():
|
|
|
96
95
|
|
|
97
96
|
return result
|
|
98
97
|
|
|
98
|
+
|
|
99
99
|
if __name__ == "__main__":
|
|
100
100
|
sys.exit(main())
|