@pennyfarthing/benchmark 10.2.0
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/commands/benchmark-control.md +69 -0
- package/commands/benchmark.md +485 -0
- package/commands/job-fair.md +102 -0
- package/commands/solo.md +447 -0
- package/dist/benchmark-integration.d.ts +182 -0
- package/dist/benchmark-integration.d.ts.map +1 -0
- package/dist/benchmark-integration.js +710 -0
- package/dist/benchmark-integration.js.map +1 -0
- package/dist/benchmark-integration.test.d.ts +6 -0
- package/dist/benchmark-integration.test.d.ts.map +1 -0
- package/dist/benchmark-integration.test.js +41 -0
- package/dist/benchmark-integration.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/job-fair-aggregator.d.ts +150 -0
- package/dist/job-fair-aggregator.d.ts.map +1 -0
- package/dist/job-fair-aggregator.js +547 -0
- package/dist/job-fair-aggregator.js.map +1 -0
- package/dist/job-fair-aggregator.test.d.ts +6 -0
- package/dist/job-fair-aggregator.test.d.ts.map +1 -0
- package/dist/job-fair-aggregator.test.js +35 -0
- package/dist/job-fair-aggregator.test.js.map +1 -0
- package/dist/package-exports.test.d.ts +13 -0
- package/dist/package-exports.test.d.ts.map +1 -0
- package/dist/package-exports.test.js +192 -0
- package/dist/package-exports.test.js.map +1 -0
- package/docs/BENCHMARK-METHODOLOGY.md +105 -0
- package/docs/BENCHMARKING.md +311 -0
- package/docs/OCEAN-BENCHMARKING.md +210 -0
- package/docs/benchmarks-guide.md +62 -0
- package/package.json +66 -0
- package/scenarios/README.md +145 -0
- package/scenarios/architecture/database-selection.yaml +119 -0
- package/scenarios/architecture/legacy-modernization.yaml +153 -0
- package/scenarios/architecture/scaling-decision.yaml +88 -0
- package/scenarios/code-review/graphql-api-review.yaml +714 -0
- package/scenarios/code-review/order-service.yaml +622 -0
- package/scenarios/code-review/react-auth-component.yaml +569 -0
- package/scenarios/code-review/security-review.yaml +145 -0
- package/scenarios/code-review/terraform-infrastructure.yaml +582 -0
- package/scenarios/debug/buggy-user-service.yaml +541 -0
- package/scenarios/debug/null-pointer.yaml +130 -0
- package/scenarios/debugging/async-control-flow.yaml +161 -0
- package/scenarios/debugging/auth-bypass.yaml +197 -0
- package/scenarios/debugging/error-handling.yaml +178 -0
- package/scenarios/debugging/input-validation.yaml +157 -0
- package/scenarios/debugging/null-check-missing.yaml +139 -0
- package/scenarios/debugging/off-by-one-loop.yaml +132 -0
- package/scenarios/debugging/race-condition.yaml +180 -0
- package/scenarios/debugging/resource-leak.yaml +166 -0
- package/scenarios/debugging/simple-logic-error.yaml +115 -0
- package/scenarios/debugging/sql-injection.yaml +163 -0
- package/scenarios/dev/event-processor-tdd.yaml +764 -0
- package/scenarios/dev/migration-disaster.yaml +415 -0
- package/scenarios/dev/race-condition-cache.yaml +546 -0
- package/scenarios/dev/tdd-shopping-cart.yaml +681 -0
- package/scenarios/schema.yaml +639 -0
- package/scenarios/sm/dependency-deadlock.yaml +414 -0
- package/scenarios/sm/executive-pet-project.yaml +336 -0
- package/scenarios/sm/layoff-planning.yaml +356 -0
- package/scenarios/sm/sprint-planning-conflict.yaml +303 -0
- package/scenarios/sm/story-breakdown.yaml +240 -0
- package/scenarios/sm/three-sprint-failure.yaml +397 -0
- package/scenarios/swe-bench/README.md +57 -0
- package/scenarios/swe-bench/astropy-12907.yaml +128 -0
- package/scenarios/swe-bench/astropy-13398.yaml +177 -0
- package/scenarios/swe-bench/astropy-14309.yaml +180 -0
- package/scenarios/swe-bench/django-10097.yaml +106 -0
- package/scenarios/swe-bench/django-10554.yaml +140 -0
- package/scenarios/swe-bench/django-10973.yaml +93 -0
- package/scenarios/swe-bench/flask-5014-reviewer.yaml +145 -0
- package/scenarios/swe-bench/flask-5014-tea.yaml +123 -0
- package/scenarios/swe-bench/flask-5014.yaml +91 -0
- package/scenarios/swe-bench/import-swebench.py +246 -0
- package/scenarios/swe-bench/matplotlib-13989.yaml +139 -0
- package/scenarios/swe-bench/matplotlib-14623.yaml +127 -0
- package/scenarios/swe-bench/requests-1142-reviewer.yaml +144 -0
- package/scenarios/swe-bench/requests-1142-tea.yaml +135 -0
- package/scenarios/swe-bench/requests-1142.yaml +100 -0
- package/scenarios/swe-bench/requests-2931.yaml +98 -0
- package/scenarios/swe-bench/seaborn-3069.yaml +102 -0
- package/scenarios/swe-bench/sphinx-7590.yaml +108 -0
- package/scenarios/swe-bench/xarray-3993.yaml +104 -0
- package/scenarios/swe-bench/xarray-6992.yaml +136 -0
- package/scenarios/tea/checkout-component-tests.yaml +596 -0
- package/scenarios/tea/cli-tool-tests.yaml +561 -0
- package/scenarios/tea/microservice-integration-tests.yaml +520 -0
- package/scenarios/tea/payment-processor-tests.yaml +550 -0
- package/scripts/aggregate-benchmark-stats.js +315 -0
- package/scripts/aggregate-benchmark-stats.sh +8 -0
- package/scripts/benchmark-runner.js +392 -0
- package/scripts/benchmark-runner.sh +8 -0
- package/scripts/consolidate-job-fair.sh +107 -0
- package/scripts/convert-jobfair-to-benchmarks.sh +230 -0
- package/scripts/job-fair-batch.sh +116 -0
- package/scripts/job-fair-progress.sh +35 -0
- package/scripts/job-fair-runner.sh +278 -0
- package/scripts/job-fair-status.sh +80 -0
- package/scripts/job-fair-watcher-v2.sh +38 -0
- package/scripts/job-fair-watcher.sh +50 -0
- package/scripts/parallel-benchmark.sh +140 -0
- package/scripts/solo-runner.sh +344 -0
- package/scripts/test/ensure-swebench-data.sh +59 -0
- package/scripts/test/ground-truth-judge.py +220 -0
- package/scripts/test/swebench-judge.py +374 -0
- package/scripts/test/test-cache.sh +165 -0
- package/scripts/test/test-setup.sh +337 -0
- package/scripts/theme/compute-theme-tiers.sh +13 -0
- package/scripts/theme/compute_theme_tiers.py +402 -0
- package/scripts/theme/update-theme-tiers.sh +97 -0
- package/skills/finalize-run/SKILL.md +261 -0
- package/skills/judge/SKILL.md +644 -0
- package/skills/persona-benchmark/SKILL.md +187 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Scenario: CLI Tool Test Suite
|
|
3
|
+
# Category: tea
|
|
4
|
+
# Purpose: Test CLI/systems testing skills with Go
|
|
5
|
+
|
|
6
|
+
id: tea-004
|
|
7
|
+
name: cli-tool-tests
|
|
8
|
+
title: "CLI Tool Test Suite Design"
|
|
9
|
+
category: tea
|
|
10
|
+
difficulty: hard # Empirical: control mean 64.50
|
|
11
|
+
version: "1.0"
|
|
12
|
+
|
|
13
|
+
description: |
|
|
14
|
+
A CLI tool for managing configuration files with subcommands for init, get,
|
|
15
|
+
set, delete, and validate. Must write tests covering argument parsing, file
|
|
16
|
+
I/O, error handling, and user-facing output. Tests systems programming test
|
|
17
|
+
skills distinct from web/API testing.
|
|
18
|
+
|
|
19
|
+
purpose: |
|
|
20
|
+
This scenario tests CLI testing expertise. CLI tools have unique testing
|
|
21
|
+
concerns: argument parsing, exit codes, stdout/stderr handling, file system
|
|
22
|
+
interactions. Measures ability to test command-line interfaces thoroughly.
|
|
23
|
+
|
|
24
|
+
prompt: |
|
|
25
|
+
You are a Test Engineer designing tests for a configuration management CLI tool.
|
|
26
|
+
Write a comprehensive test suite using Go's testing package.
|
|
27
|
+
|
|
28
|
+
The CLI has these commands:
|
|
29
|
+
- `config init` - Initialize a new config file
|
|
30
|
+
- `config get <key>` - Get a config value
|
|
31
|
+
- `config set <key> <value>` - Set a config value
|
|
32
|
+
- `config delete <key>` - Delete a config key
|
|
33
|
+
- `config validate` - Validate config file syntax
|
|
34
|
+
- `config list` - List all config keys
|
|
35
|
+
|
|
36
|
+
Global flags:
|
|
37
|
+
- `--config <path>` - Config file path (default: ~/.config/app/config.yaml)
|
|
38
|
+
- `--format <json|yaml|text>` - Output format
|
|
39
|
+
- `--quiet` - Suppress non-essential output
|
|
40
|
+
- `--verbose` - Show detailed output
|
|
41
|
+
|
|
42
|
+
Write tests covering:
|
|
43
|
+
1. Argument parsing (valid/invalid args, flags, subcommands)
|
|
44
|
+
2. Exit codes (0 for success, 1 for error, 2 for usage error)
|
|
45
|
+
3. Stdout vs stderr output (data to stdout, errors to stderr)
|
|
46
|
+
4. File system operations (create, read, write, permissions)
|
|
47
|
+
5. Error messages (user-friendly, actionable)
|
|
48
|
+
6. Edge cases (missing file, invalid YAML, concurrent access)
|
|
49
|
+
|
|
50
|
+
For each test:
|
|
51
|
+
1. Use table-driven tests where appropriate
|
|
52
|
+
2. Test both success and failure paths
|
|
53
|
+
3. Verify exit codes, stdout, and stderr
|
|
54
|
+
4. Use temporary directories for file tests
|
|
55
|
+
|
|
56
|
+
code:
|
|
57
|
+
language: go
|
|
58
|
+
filename: config_cli.go
|
|
59
|
+
content: |
|
|
60
|
+
package main
|
|
61
|
+
|
|
62
|
+
import (
|
|
63
|
+
"encoding/json"
|
|
64
|
+
"fmt"
|
|
65
|
+
"io"
|
|
66
|
+
"os"
|
|
67
|
+
"path/filepath"
|
|
68
|
+
|
|
69
|
+
"gopkg.in/yaml.v3"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
// Config represents the configuration structure
|
|
73
|
+
type Config struct {
|
|
74
|
+
data map[string]interface{}
|
|
75
|
+
filepath string
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// CLI represents the command-line interface
|
|
79
|
+
type CLI struct {
|
|
80
|
+
stdout io.Writer
|
|
81
|
+
stderr io.Writer
|
|
82
|
+
configDir string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// NewCLI creates a new CLI instance
|
|
86
|
+
func NewCLI(stdout, stderr io.Writer, configDir string) *CLI {
|
|
87
|
+
return &CLI{
|
|
88
|
+
stdout: stdout,
|
|
89
|
+
stderr: stderr,
|
|
90
|
+
configDir: configDir,
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Run executes the CLI with the given arguments
|
|
95
|
+
func (c *CLI) Run(args []string) int {
|
|
96
|
+
if len(args) < 1 {
|
|
97
|
+
fmt.Fprintln(c.stderr, "Usage: config <command> [options]")
|
|
98
|
+
return 2
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Parse global flags
|
|
102
|
+
configPath := filepath.Join(c.configDir, "config.yaml")
|
|
103
|
+
format := "text"
|
|
104
|
+
quiet := false
|
|
105
|
+
verbose := false
|
|
106
|
+
|
|
107
|
+
// Filter out flags and get command
|
|
108
|
+
var cmdArgs []string
|
|
109
|
+
for i := 0; i < len(args); i++ {
|
|
110
|
+
switch args[i] {
|
|
111
|
+
case "--config":
|
|
112
|
+
if i+1 < len(args) {
|
|
113
|
+
configPath = args[i+1]
|
|
114
|
+
i++
|
|
115
|
+
}
|
|
116
|
+
case "--format":
|
|
117
|
+
if i+1 < len(args) {
|
|
118
|
+
format = args[i+1]
|
|
119
|
+
i++
|
|
120
|
+
}
|
|
121
|
+
case "--quiet":
|
|
122
|
+
quiet = true
|
|
123
|
+
case "--verbose":
|
|
124
|
+
verbose = true
|
|
125
|
+
default:
|
|
126
|
+
cmdArgs = append(cmdArgs, args[i])
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if len(cmdArgs) < 1 {
|
|
131
|
+
fmt.Fprintln(c.stderr, "Error: no command specified")
|
|
132
|
+
return 2
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
command := cmdArgs[0]
|
|
136
|
+
cmdArgs = cmdArgs[1:]
|
|
137
|
+
|
|
138
|
+
switch command {
|
|
139
|
+
case "init":
|
|
140
|
+
return c.cmdInit(configPath, quiet)
|
|
141
|
+
case "get":
|
|
142
|
+
if len(cmdArgs) < 1 {
|
|
143
|
+
fmt.Fprintln(c.stderr, "Error: get requires a key argument")
|
|
144
|
+
return 2
|
|
145
|
+
}
|
|
146
|
+
return c.cmdGet(configPath, cmdArgs[0], format)
|
|
147
|
+
case "set":
|
|
148
|
+
if len(cmdArgs) < 2 {
|
|
149
|
+
fmt.Fprintln(c.stderr, "Error: set requires key and value arguments")
|
|
150
|
+
return 2
|
|
151
|
+
}
|
|
152
|
+
return c.cmdSet(configPath, cmdArgs[0], cmdArgs[1], quiet)
|
|
153
|
+
case "delete":
|
|
154
|
+
if len(cmdArgs) < 1 {
|
|
155
|
+
fmt.Fprintln(c.stderr, "Error: delete requires a key argument")
|
|
156
|
+
return 2
|
|
157
|
+
}
|
|
158
|
+
return c.cmdDelete(configPath, cmdArgs[0], quiet)
|
|
159
|
+
case "validate":
|
|
160
|
+
return c.cmdValidate(configPath, verbose)
|
|
161
|
+
case "list":
|
|
162
|
+
return c.cmdList(configPath, format)
|
|
163
|
+
default:
|
|
164
|
+
fmt.Fprintf(c.stderr, "Error: unknown command %q\n", command)
|
|
165
|
+
return 2
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
func (c *CLI) cmdInit(configPath string, quiet bool) int {
|
|
170
|
+
dir := filepath.Dir(configPath)
|
|
171
|
+
if err := os.MkdirAll(dir, 0755); err != nil {
|
|
172
|
+
fmt.Fprintf(c.stderr, "Error creating directory: %v\n", err)
|
|
173
|
+
return 1
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if _, err := os.Stat(configPath); err == nil {
|
|
177
|
+
fmt.Fprintln(c.stderr, "Error: config file already exists")
|
|
178
|
+
return 1
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
initialConfig := map[string]interface{}{
|
|
182
|
+
"version": "1.0",
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
data, err := yaml.Marshal(initialConfig)
|
|
186
|
+
if err != nil {
|
|
187
|
+
fmt.Fprintf(c.stderr, "Error encoding config: %v\n", err)
|
|
188
|
+
return 1
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if err := os.WriteFile(configPath, data, 0644); err != nil {
|
|
192
|
+
fmt.Fprintf(c.stderr, "Error writing config: %v\n", err)
|
|
193
|
+
return 1
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if !quiet {
|
|
197
|
+
fmt.Fprintf(c.stdout, "Initialized config at %s\n", configPath)
|
|
198
|
+
}
|
|
199
|
+
return 0
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
func (c *CLI) cmdGet(configPath, key, format string) int {
|
|
203
|
+
config, err := c.loadConfig(configPath)
|
|
204
|
+
if err != nil {
|
|
205
|
+
fmt.Fprintf(c.stderr, "Error loading config: %v\n", err)
|
|
206
|
+
return 1
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
value, ok := config[key]
|
|
210
|
+
if !ok {
|
|
211
|
+
fmt.Fprintf(c.stderr, "Error: key %q not found\n", key)
|
|
212
|
+
return 1
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return c.outputValue(value, format)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
func (c *CLI) cmdSet(configPath, key, value string, quiet bool) int {
|
|
219
|
+
config, err := c.loadConfig(configPath)
|
|
220
|
+
if err != nil {
|
|
221
|
+
// If file doesn't exist, start fresh
|
|
222
|
+
if os.IsNotExist(err) {
|
|
223
|
+
config = make(map[string]interface{})
|
|
224
|
+
} else {
|
|
225
|
+
fmt.Fprintf(c.stderr, "Error loading config: %v\n", err)
|
|
226
|
+
return 1
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
config[key] = value
|
|
231
|
+
|
|
232
|
+
if err := c.saveConfig(configPath, config); err != nil {
|
|
233
|
+
fmt.Fprintf(c.stderr, "Error saving config: %v\n", err)
|
|
234
|
+
return 1
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if !quiet {
|
|
238
|
+
fmt.Fprintf(c.stdout, "Set %s = %s\n", key, value)
|
|
239
|
+
}
|
|
240
|
+
return 0
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
func (c *CLI) cmdDelete(configPath, key string, quiet bool) int {
|
|
244
|
+
config, err := c.loadConfig(configPath)
|
|
245
|
+
if err != nil {
|
|
246
|
+
fmt.Fprintf(c.stderr, "Error loading config: %v\n", err)
|
|
247
|
+
return 1
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if _, ok := config[key]; !ok {
|
|
251
|
+
fmt.Fprintf(c.stderr, "Error: key %q not found\n", key)
|
|
252
|
+
return 1
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
delete(config, key)
|
|
256
|
+
|
|
257
|
+
if err := c.saveConfig(configPath, config); err != nil {
|
|
258
|
+
fmt.Fprintf(c.stderr, "Error saving config: %v\n", err)
|
|
259
|
+
return 1
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if !quiet {
|
|
263
|
+
fmt.Fprintf(c.stdout, "Deleted %s\n", key)
|
|
264
|
+
}
|
|
265
|
+
return 0
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
func (c *CLI) cmdValidate(configPath string, verbose bool) int {
|
|
269
|
+
data, err := os.ReadFile(configPath)
|
|
270
|
+
if err != nil {
|
|
271
|
+
fmt.Fprintf(c.stderr, "Error reading config: %v\n", err)
|
|
272
|
+
return 1
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
var config map[string]interface{}
|
|
276
|
+
if err := yaml.Unmarshal(data, &config); err != nil {
|
|
277
|
+
fmt.Fprintf(c.stderr, "Error: invalid YAML syntax: %v\n", err)
|
|
278
|
+
return 1
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if verbose {
|
|
282
|
+
fmt.Fprintf(c.stdout, "Config file: %s\n", configPath)
|
|
283
|
+
fmt.Fprintf(c.stdout, "Keys: %d\n", len(config))
|
|
284
|
+
}
|
|
285
|
+
fmt.Fprintln(c.stdout, "Config is valid")
|
|
286
|
+
return 0
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
func (c *CLI) cmdList(configPath, format string) int {
|
|
290
|
+
config, err := c.loadConfig(configPath)
|
|
291
|
+
if err != nil {
|
|
292
|
+
fmt.Fprintf(c.stderr, "Error loading config: %v\n", err)
|
|
293
|
+
return 1
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
switch format {
|
|
297
|
+
case "json":
|
|
298
|
+
data, _ := json.MarshalIndent(config, "", " ")
|
|
299
|
+
fmt.Fprintln(c.stdout, string(data))
|
|
300
|
+
case "yaml":
|
|
301
|
+
data, _ := yaml.Marshal(config)
|
|
302
|
+
fmt.Fprint(c.stdout, string(data))
|
|
303
|
+
default:
|
|
304
|
+
for k, v := range config {
|
|
305
|
+
fmt.Fprintf(c.stdout, "%s: %v\n", k, v)
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return 0
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
func (c *CLI) loadConfig(path string) (map[string]interface{}, error) {
|
|
312
|
+
data, err := os.ReadFile(path)
|
|
313
|
+
if err != nil {
|
|
314
|
+
return nil, err
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
var config map[string]interface{}
|
|
318
|
+
if err := yaml.Unmarshal(data, &config); err != nil {
|
|
319
|
+
return nil, err
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return config, nil
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
func (c *CLI) saveConfig(path string, config map[string]interface{}) error {
|
|
326
|
+
data, err := yaml.Marshal(config)
|
|
327
|
+
if err != nil {
|
|
328
|
+
return err
|
|
329
|
+
}
|
|
330
|
+
return os.WriteFile(path, data, 0644)
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
func (c *CLI) outputValue(value interface{}, format string) int {
|
|
334
|
+
switch format {
|
|
335
|
+
case "json":
|
|
336
|
+
data, _ := json.Marshal(value)
|
|
337
|
+
fmt.Fprintln(c.stdout, string(data))
|
|
338
|
+
case "yaml":
|
|
339
|
+
data, _ := yaml.Marshal(value)
|
|
340
|
+
fmt.Fprint(c.stdout, string(data))
|
|
341
|
+
default:
|
|
342
|
+
fmt.Fprintln(c.stdout, value)
|
|
343
|
+
}
|
|
344
|
+
return 0
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
func main() {
|
|
348
|
+
cli := NewCLI(os.Stdout, os.Stderr, os.Getenv("HOME"))
|
|
349
|
+
os.Exit(cli.Run(os.Args[1:]))
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
# =============================================================================
|
|
353
|
+
# BASELINE TEST SCENARIOS
|
|
354
|
+
# =============================================================================
|
|
355
|
+
|
|
356
|
+
baseline_issues:
|
|
357
|
+
argument_parsing:
|
|
358
|
+
- id: VALID_COMMANDS
|
|
359
|
+
description: "All valid commands are recognized"
|
|
360
|
+
|
|
361
|
+
- id: INVALID_COMMAND
|
|
362
|
+
description: "Unknown commands return exit code 2"
|
|
363
|
+
|
|
364
|
+
- id: MISSING_ARGS
|
|
365
|
+
description: "Missing required args show usage error"
|
|
366
|
+
|
|
367
|
+
- id: FLAG_PARSING
|
|
368
|
+
description: "Global flags parsed correctly"
|
|
369
|
+
|
|
370
|
+
exit_codes:
|
|
371
|
+
- id: SUCCESS_EXIT_0
|
|
372
|
+
description: "Successful operations return 0"
|
|
373
|
+
|
|
374
|
+
- id: ERROR_EXIT_1
|
|
375
|
+
description: "Errors return 1"
|
|
376
|
+
|
|
377
|
+
- id: USAGE_EXIT_2
|
|
378
|
+
description: "Usage errors return 2"
|
|
379
|
+
|
|
380
|
+
output_streams:
|
|
381
|
+
- id: DATA_TO_STDOUT
|
|
382
|
+
description: "Data output goes to stdout"
|
|
383
|
+
|
|
384
|
+
- id: ERRORS_TO_STDERR
|
|
385
|
+
description: "Error messages go to stderr"
|
|
386
|
+
|
|
387
|
+
- id: QUIET_MODE
|
|
388
|
+
description: "--quiet suppresses informational output"
|
|
389
|
+
|
|
390
|
+
file_operations:
|
|
391
|
+
- id: INIT_CREATES_FILE
|
|
392
|
+
description: "init creates config file and directories"
|
|
393
|
+
|
|
394
|
+
- id: GET_READS_VALUE
|
|
395
|
+
description: "get returns correct value"
|
|
396
|
+
|
|
397
|
+
- id: SET_PERSISTS
|
|
398
|
+
description: "set writes to file correctly"
|
|
399
|
+
|
|
400
|
+
- id: DELETE_REMOVES
|
|
401
|
+
description: "delete removes key from file"
|
|
402
|
+
|
|
403
|
+
error_handling:
|
|
404
|
+
- id: MISSING_FILE
|
|
405
|
+
description: "Graceful error for missing config"
|
|
406
|
+
|
|
407
|
+
- id: INVALID_YAML
|
|
408
|
+
description: "Clear error for malformed YAML"
|
|
409
|
+
|
|
410
|
+
- id: KEY_NOT_FOUND
|
|
411
|
+
description: "Clear error when key doesn't exist"
|
|
412
|
+
|
|
413
|
+
- id: PERMISSION_ERROR
|
|
414
|
+
description: "Clear error for permission issues"
|
|
415
|
+
|
|
416
|
+
output_formats:
|
|
417
|
+
- id: TEXT_FORMAT
|
|
418
|
+
description: "Default text format works"
|
|
419
|
+
|
|
420
|
+
- id: JSON_FORMAT
|
|
421
|
+
description: "--format json outputs valid JSON"
|
|
422
|
+
|
|
423
|
+
- id: YAML_FORMAT
|
|
424
|
+
description: "--format yaml outputs valid YAML"
|
|
425
|
+
|
|
426
|
+
# =============================================================================
|
|
427
|
+
# BONUS TEST SCENARIOS
|
|
428
|
+
# =============================================================================
|
|
429
|
+
|
|
430
|
+
bonus_issues:
|
|
431
|
+
advanced:
|
|
432
|
+
- id: CONCURRENT_ACCESS
|
|
433
|
+
description: "Handles concurrent reads/writes safely"
|
|
434
|
+
|
|
435
|
+
- id: LARGE_CONFIG
|
|
436
|
+
description: "Handles large config files efficiently"
|
|
437
|
+
|
|
438
|
+
- id: SPECIAL_CHARACTERS
|
|
439
|
+
description: "Keys/values with special chars handled"
|
|
440
|
+
|
|
441
|
+
robustness:
|
|
442
|
+
- id: PARTIAL_WRITE
|
|
443
|
+
description: "Atomic writes prevent corruption"
|
|
444
|
+
|
|
445
|
+
- id: SYMLINK_HANDLING
|
|
446
|
+
description: "Config path symlinks work correctly"
|
|
447
|
+
|
|
448
|
+
- id: RELATIVE_PATHS
|
|
449
|
+
description: "Relative --config paths resolved correctly"
|
|
450
|
+
|
|
451
|
+
usability:
|
|
452
|
+
- id: HELPFUL_ERRORS
|
|
453
|
+
description: "Error messages suggest fixes"
|
|
454
|
+
|
|
455
|
+
- id: VERBOSE_MODE
|
|
456
|
+
description: "--verbose shows additional info"
|
|
457
|
+
|
|
458
|
+
# =============================================================================
|
|
459
|
+
# SCORING
|
|
460
|
+
# =============================================================================
|
|
461
|
+
|
|
462
|
+
scoring:
|
|
463
|
+
total_baseline_scenarios: 20
|
|
464
|
+
total_bonus_scenarios: 8
|
|
465
|
+
|
|
466
|
+
categories:
|
|
467
|
+
- name: coverage
|
|
468
|
+
weight: 40
|
|
469
|
+
criteria:
|
|
470
|
+
- id: BASELINE_COVERED
|
|
471
|
+
description: "All baseline test scenarios covered"
|
|
472
|
+
points: 30
|
|
473
|
+
- id: BONUS_COVERED
|
|
474
|
+
description: "Additional valuable test scenarios"
|
|
475
|
+
points: 10
|
|
476
|
+
|
|
477
|
+
- name: quality
|
|
478
|
+
weight: 30
|
|
479
|
+
criteria:
|
|
480
|
+
- id: TABLE_DRIVEN
|
|
481
|
+
description: "Uses table-driven tests appropriately"
|
|
482
|
+
points: 10
|
|
483
|
+
- id: ISOLATION
|
|
484
|
+
description: "Tests use temp dirs, are isolated"
|
|
485
|
+
points: 10
|
|
486
|
+
- id: ASSERTIONS
|
|
487
|
+
description: "Clear, comprehensive assertions"
|
|
488
|
+
points: 10
|
|
489
|
+
|
|
490
|
+
- name: cli_specific
|
|
491
|
+
weight: 15
|
|
492
|
+
criteria:
|
|
493
|
+
- id: EXIT_CODES
|
|
494
|
+
description: "Tests verify exit codes"
|
|
495
|
+
points: 5
|
|
496
|
+
- id: STREAM_SEPARATION
|
|
497
|
+
description: "Tests verify stdout vs stderr"
|
|
498
|
+
points: 5
|
|
499
|
+
- id: FILE_CLEANUP
|
|
500
|
+
description: "Tests clean up temp files"
|
|
501
|
+
points: 5
|
|
502
|
+
|
|
503
|
+
- name: persona
|
|
504
|
+
weight: 15
|
|
505
|
+
criteria:
|
|
506
|
+
- id: CHARACTER_CONSISTENCY
|
|
507
|
+
description: "Stays in character throughout"
|
|
508
|
+
points: 8
|
|
509
|
+
- id: PERSONA_VALUE_ADD
|
|
510
|
+
description: "Persona enhances test documentation"
|
|
511
|
+
points: 7
|
|
512
|
+
|
|
513
|
+
# =============================================================================
|
|
514
|
+
# PERSONA INFLUENCE
|
|
515
|
+
# =============================================================================
|
|
516
|
+
|
|
517
|
+
persona_influence:
|
|
518
|
+
dimensions:
|
|
519
|
+
- name: test_style
|
|
520
|
+
description: "How tests are organized"
|
|
521
|
+
spectrum:
|
|
522
|
+
individual: "One test per scenario"
|
|
523
|
+
table_driven: "Extensive use of table tests"
|
|
524
|
+
hybrid: "Mix based on complexity"
|
|
525
|
+
|
|
526
|
+
- name: coverage_focus
|
|
527
|
+
description: "What gets tested most"
|
|
528
|
+
spectrum:
|
|
529
|
+
happy_path: "Focus on successful operations"
|
|
530
|
+
error_focused: "Emphasizes error handling"
|
|
531
|
+
comprehensive: "Equal coverage of both"
|
|
532
|
+
|
|
533
|
+
- name: systems_depth
|
|
534
|
+
description: "Depth of file system testing"
|
|
535
|
+
spectrum:
|
|
536
|
+
basic: "Simple file read/write"
|
|
537
|
+
intermediate: "Permissions, directories"
|
|
538
|
+
advanced: "Symlinks, atomicity, concurrency"
|
|
539
|
+
|
|
540
|
+
expected_tendencies:
|
|
541
|
+
discworld_tea:
|
|
542
|
+
character: "Igor"
|
|
543
|
+
expected_traits:
|
|
544
|
+
- "Thorough - covers edge cases"
|
|
545
|
+
- "Practical - focuses on real failures"
|
|
546
|
+
- "May suggest unusual test scenarios"
|
|
547
|
+
coverage_prediction: "comprehensive"
|
|
548
|
+
|
|
549
|
+
star_trek_tea:
|
|
550
|
+
character: "Scotty"
|
|
551
|
+
expected_traits:
|
|
552
|
+
- "Systems focus - file operations"
|
|
553
|
+
- "Engineering rigor - thorough coverage"
|
|
554
|
+
- "May emphasize robustness testing"
|
|
555
|
+
coverage_prediction: "comprehensive"
|
|
556
|
+
|
|
557
|
+
control_tea:
|
|
558
|
+
character: "None (baseline)"
|
|
559
|
+
expected_traits:
|
|
560
|
+
- "Standard CLI testing approach"
|
|
561
|
+
coverage_prediction: "baseline reference"
|