cli-testing-specialist 1.0.10

Comprehensive testing framework for CLI tools - automated analysis, test generation, and security validation
Documentation
# backup-suite Implementation Guide

**Purpose**: Add `BACKUP_SUITE_YES` environment variable support for CI/CD compatibility

**Effort**: ~10 minutes
**Files to modify**: 1 file (`src/main.rs` or `src/ui.rs`)

---

## Implementation

### Step 1: Add helper function

Add this function to `src/main.rs` or a new `src/ui.rs`:

```rust
/// Check if auto-confirmation is enabled via environment variable
///
/// This allows running backup-suite in CI/CD environments without TTY.
///
/// # Environment Variables
/// - `BACKUP_SUITE_YES`: Set to "true" or "1" to auto-confirm all prompts
/// - `CI`: Detected automatically (GitHub Actions, GitLab CI, etc.)
///
/// # Examples
/// ```bash
/// # CI environment
/// BACKUP_SUITE_YES=true backup-suite remove target1
///
/// # Or use CI detection
/// CI=true backup-suite cleanup
/// ```
fn should_auto_confirm() -> bool {
    // Check BACKUP_SUITE_YES environment variable
    if let Ok(val) = std::env::var("BACKUP_SUITE_YES") {
        return val == "true" || val == "1" || val.to_lowercase() == "yes";
    }

    // Check CI environment variable (common in CI/CD systems)
    if let Ok(val) = std::env::var("CI") {
        return val == "true" || val == "1";
    }

    false
}
```

### Step 2: Update confirmation prompts

**Before** (interactive only):
```rust
use dialoguer::Confirm;

fn confirm_remove(target: &str) -> Result<bool> {
    let confirmed = Confirm::new()
        .with_prompt(format!("本当に {} を削除しますか?", target))
        .interact()?;

    Ok(confirmed)
}
```

**After** (CI-compatible):
```rust
use dialoguer::Confirm;

fn confirm_remove(target: &str) -> Result<bool> {
    // Auto-confirm in CI environment
    if should_auto_confirm() {
        eprintln!("本当に {} を削除しますか? (auto-confirmed in CI)", target);
        return Ok(true);
    }

    // Interactive prompt in normal environment
    let confirmed = Confirm::new()
        .with_prompt(format!("本当に {} を削除しますか?", target))
        .interact()?;

    Ok(confirmed)
}
```

### Step 3: Update all confirmation points

Apply the pattern to all interactive confirmations:

1. **Remove command** (`src/commands/remove.rs`):
```rust
fn execute_remove(target: &str) -> Result<()> {
    if should_auto_confirm() {
        eprintln!("Removing {} (auto-confirmed)", target);
    } else {
        if !confirm_remove(target)? {
            return Err(Error::Cancelled);
        }
    }

    // Perform removal
    // ...
}
```

2. **Cleanup command** (`src/commands/cleanup.rs`):
```rust
fn execute_cleanup() -> Result<()> {
    if should_auto_confirm() {
        eprintln!("Cleanup all backups (auto-confirmed)");
    } else {
        if !confirm_cleanup()? {
            return Err(Error::Cancelled);
        }
    }

    // Perform cleanup
    // ...
}
```

---

## Testing

### Manual Test

```bash
# Test 1: Auto-confirm with BACKUP_SUITE_YES
BACKUP_SUITE_YES=true cargo run -- remove test-target
# Expected: No prompt, operation proceeds

# Test 2: Auto-confirm with CI variable
CI=true cargo run -- cleanup
# Expected: No prompt, operation proceeds

# Test 3: Normal interactive mode
cargo run -- remove test-target
# Expected: Interactive prompt appears
```

### Integration Test

```bash
# Run cli-testing-specialist tests
cd /path/to/backup-suite
cp /path/to/cli-testing-specialist/examples/backup-suite.cli-test-config.yml .cli-test-config.yml

# Generate and run tests
cli-testing-specialist analyze ./target/debug/backup-suite -o analysis.json
cli-testing-specialist generate analysis.json -o tests -c all
cli-testing-specialist run tests -f all -o reports

# Expected: 19/19 tests passing (100%)
```

---

## Error Handling

### Cancelled Operation

Update error type to handle cancellation:

```rust
// src/error.rs
#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("Operation cancelled by user")]
    Cancelled,
    // ... other errors
}

// Exit code for cancelled operations
impl Error {
    pub fn exit_code(&self) -> i32 {
        match self {
            Error::Cancelled => 2,  // Matches .cli-test-config.yml
            _ => 1,
        }
    }
}

// src/main.rs
fn main() {
    if let Err(e) = run() {
        eprintln!("Error: {}", e);
        std::process::exit(e.exit_code());
    }
}
```

---

## Configuration File Location

Place `.cli-test-config.yml` in backup-suite project root:

```
backup-suite/
├── .cli-test-config.yml  ← Here
├── Cargo.toml
├── src/
│   ├── main.rs
│   ├── commands/
│   │   ├── remove.rs
│   │   └── cleanup.rs
│   └── ...
└── tests/
```

---

## Verification Checklist

- [ ] `should_auto_confirm()` function added
- [ ] All confirmation prompts updated
- [ ] `BACKUP_SUITE_YES=true` tested
- [ ] `CI=true` tested
- [ ] Exit code 2 for cancelled operations
- [ ] `.cli-test-config.yml` placed in project root
- [ ] Integration tests run: 19/19 passing

---

## Expected Test Results

### Before Implementation
```
Total: 17 tests
Passed: 9 (52.9%)
Failed: 8 (47.1%)

Failed Tests:
- Security: 0/3 (command injection tests)
- Directory Traversal: 0/3 (missing test directories)
- Destructive Ops: 0/2 (TTY required)
```

### After Implementation
```
Total: 19 tests (2 custom security tests added)
Passed: 19 (100%)
Failed: 0 (0%)

Test Categories:
- Security: 5/5 ✅ (3 default + 2 custom)
- Directory Traversal: 3/3 ✅ (auto-created)
- Destructive Ops: 2/2 ✅ (BACKUP_SUITE_YES)
- Other: 9/9 ✅ (unchanged)
```

---

## CI/CD Integration

### GitHub Actions

```yaml
# .github/workflows/test.yml
name: Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Run backup-suite tests
        run: |
          cargo build --release
          cli-testing-specialist analyze ./target/release/backup-suite -o analysis.json
          cli-testing-specialist run tests -f all
        env:
          BACKUP_SUITE_YES: "true"  # Auto-confirm in CI
```

### GitLab CI

```yaml
# .gitlab-ci.yml
test:
  script:
    - cargo build --release
    - cli-testing-specialist analyze ./target/release/backup-suite
    - cli-testing-specialist run tests -f all
  variables:
    BACKUP_SUITE_YES: "true"
```

---

## Troubleshooting

### Issue: Tests still fail with "not a terminal"

**Solution**: Ensure `should_auto_confirm()` is called BEFORE `dialoguer::Confirm`:

```rust
// WRONG: dialoguer called first
let confirmed = Confirm::new().interact()?;  // Error in CI

// CORRECT: Check environment first
if should_auto_confirm() {
    return Ok(true);
}
let confirmed = Confirm::new().interact()?;
```

### Issue: Exit code is 1 instead of 2 for cancellation

**Solution**: Update error handling to return exit code 2:

```rust
impl Error {
    pub fn exit_code(&self) -> i32 {
        match self {
            Error::Cancelled => 2,  // Must match .cli-test-config.yml
            _ => 1,
        }
    }
}
```

---

## Summary

- **Effort**: ~10 minutes
- **Files modified**: 1-2 files
- **Lines of code**: ~20 lines
- **Test improvement**: 52.9% → 100%
- **Benefits**: CI/CD compatible, better test coverage, production-ready