# Scope Testing Guide Comprehensive guide for testing Scope configurations before deployment. ## Testing Philosophy 1. **Test patterns in isolation** before adding to YAML 2. **Validate schema** before testing functionality 3. **Test with real errors** using `.txt` files 4. **Test incrementally** (pattern → YAML → integration) 5. **Automate regression tests** for known errors ## Known Error Testing ### 1. Test Regex Pattern in Isolation ```bash # Test pattern matches expected text echo "error: cannot lock ref 'refs/heads/main'" | rg "cannot lock ref" # Output: error: cannot lock ref 'refs/heads/main' # Test pattern doesn't match unrelated text echo "error: something else" | rg "cannot lock ref" # Output: (nothing - no match) # Test with actual error file rg "pattern" path/to/error-output.log ``` **Common Issues**: - Pattern too broad: matches too many things - Pattern too specific: misses variations - Missing escapes: special chars break regex - Wrong quantifiers: `*` vs `+` vs `?` ### 2. Create Test File ```bash # Create directory mkdir -p {config-root}/known-errors/category # Create test file with ACTUAL error output cat > {config-root}/known-errors/category/error-name.txt << 'EOF' [Paste actual error output here] This should be the real error text that users see Including all the context around it EOF ``` **Best Practices**: - Use real error output, not synthetic examples - Include surrounding context (lines before/after) - Test multiple variations if error has variants - Keep file size reasonable (< 100 lines) ### 3. Create YAML Definition ```bash cat > {config-root}/known-errors/category/error-name.yaml << 'EOF' apiVersion: scope.github.com/v1alpha kind: ScopeKnownError metadata: name: error-name description: Brief description spec: pattern: "your pattern here" help: | How to fix this error EOF ``` ### 4. Test Pattern Matching ```bash # Test that pattern matches the test file scope analyze logs \ --extra-config {config-root} \ {config-root}/known-errors/category/error-name.txt ``` **Expected Output** (pattern matches): ``` Known Error: error-name Brief description How to fix this error ``` **Expected Output** (pattern doesn't match): ``` No known errors found ``` ### 5. Validate Schema ```bash # Install validator brew install sourcemeta/apps/jsonschema # Get schema (one-time setup) curl -o /tmp/ScopeKnownError.json \ https://github.com/oscope-dev/scope/raw/main/scope/schema/v1alpha.com.github.scope.ScopeKnownError.json # Validate jsonschema validate \ /tmp/ScopeKnownError.json \ {config-root}/known-errors/category/error-name.yaml ``` **Expected Output** (valid): ``` ok: {config-root}/known-errors/category/error-name.yaml ``` ### 6. Test in Real Scenario ```bash # Run the actual failing command and pipe to scope failing-command 2>&1 | scope analyze command # Or analyze existing log file scope analyze logs /path/to/error.log ``` ## Doctor Group Testing ### 1. Test Check Script Standalone ```bash # Create test script cat > .scope/bin/test-check.sh << 'EOF' #!/usr/bin/env bash set -euo pipefail # Your check logic here if [[ -f .required-file ]]; then echo "Check passed" exit 0 else echo "Check failed: .required-file missing" >&2 exit 1 fi EOF chmod +x .scope/bin/test-check.sh # Test success case touch .required-file ./.scope/bin/test-check.sh echo "Exit code: $?" # Expected: Check passed, Exit code: 0 # Test failure case rm .required-file ./.scope/bin/test-check.sh echo "Exit code: $?" # Expected: Check failed: .required-file missing, Exit code: 1 ``` ### 2. Test Fix Script Standalone ```bash # Create fix script cat > .scope/bin/test-fix.sh << 'EOF' #!/usr/bin/env bash set -euo pipefail echo "Creating .required-file..." touch .required-file echo "Done" EOF chmod +x .scope/bin/test-fix.sh # Test fix rm -f .required-file ./.scope/bin/test-fix.sh ls -la .required-file # Expected: File created ``` ### 3. Create Doctor Group YAML ```bash cat > .scope/test-group.yaml << 'EOF' apiVersion: scope.github.com/v1alpha kind: ScopeDoctorGroup metadata: name: test-group description: Test group for validation spec: include: when-required needs: [] actions: - name: test-action description: Test action check: commands: - ./bin/test-check.sh fix: commands: - ./bin/test-fix.sh EOF ``` ### 4. Verify Group is Detected ```bash # List all groups scope doctor list | grep test-group # Expected output includes: # ScopeDoctorGroup/test-group Test group for validation .scope/test-group.yaml ``` ### 5. Test Check-Only Mode ```bash # Remove file to trigger check failure rm -f .required-file # Run in check-only mode scope doctor run --only test-group --fix=false # Expected: Shows check failed, but doesn't run fix ``` ### 6. Test With Fix ```bash # Remove file to trigger check failure rm -f .required-file # Run with fix enabled scope doctor run --only test-group # Expected: Check fails, fix runs, file created ls -la .required-file ``` ### 7. Test Caching ```bash # First run (should execute check) scope doctor run --only test-group # Expected: Runs check and fix if needed # Second run (should use cache if file-based) scope doctor run --only test-group # Expected: Skips if using path-based checks # Force re-run scope doctor run --only test-group --no-cache # Expected: Runs check again ``` ### 8. Test Dependencies ```bash # Create dependency group cat > .scope/dependency.yaml << 'EOF' apiVersion: scope.github.com/v1alpha kind: ScopeDoctorGroup metadata: name: dependency spec: include: when-required needs: [] actions: - name: setup check: commands: - test -f .dependency-marker fix: commands: - touch .dependency-marker EOF # Update test group to depend on it # Add to test-group.yaml: # needs: # - dependency # Test dependency resolution rm -f .dependency-marker .required-file scope doctor run --only test-group # Expected: Runs dependency first, then test-group ls -la .dependency-marker .required-file ``` ### 9. Validate Schema ```bash # Get schema curl -o /tmp/ScopeDoctorGroup.json \ https://github.com/oscope-dev/scope/raw/main/scope/schema/v1alpha.com.github.scope.ScopeDoctorGroup.json # Validate jsonschema validate \ /tmp/ScopeDoctorGroup.json \ .scope/test-group.yaml ``` ## Integration Testing ### Test Complete Workflow ```bash # 1. Clean slate rm -rf /tmp/scope-test mkdir -p /tmp/scope-test/.scope/bin # 2. Create complete setup cd /tmp/scope-test # Create check script cat > .scope/bin/check.sh << 'EOF' #!/usr/bin/env bash test -f .setup-complete EOF chmod +x .scope/bin/check.sh # Create fix script cat > .scope/bin/fix.sh << 'EOF' #!/usr/bin/env bash echo "Setting up..." sleep 1 touch .setup-complete echo "Done" EOF chmod +x .scope/bin/fix.sh # Create doctor group cat > .scope/setup.yaml << 'EOF' apiVersion: scope.github.com/v1alpha kind: ScopeDoctorGroup metadata: name: setup spec: include: by-default needs: [] actions: - name: initialize description: Initialize project check: commands: - ./.scope/bin/check.sh fix: commands: - ./.scope/bin/fix.sh helpText: | Setup failed. Try running manually: ./.scope/bin/fix.sh EOF # 3. Test end-to-end scope doctor run # 4. Verify result test -f .setup-complete && echo "SUCCESS" || echo "FAILED" ``` ## Regression Testing ### Create Test Suite ```bash # Create test runner cat > test-scope.sh << 'EOF' #!/usr/bin/env bash set -euo pipefail PASSED=0 FAILED=0 test_known_error() { local name=$1 local yaml=$2 local test_file=$3 echo "Testing: $name" if scope analyze logs --extra-config {config-root} "$test_file" | grep -q "$name"; then echo " ✓ Pattern matches" ((PASSED++)) else echo " ✗ Pattern does not match" ((FAILED++)) fi } # Test all known errors for yaml in {config-root}/known-errors/*/*.yaml; do name=$(basename "$yaml" .yaml) txt="${yaml%.yaml}.txt" if [[ -f "$txt" ]]; then test_known_error "$name" "$yaml" "$txt" fi done echo "" echo "Results: $PASSED passed, $FAILED failed" exit $FAILED EOF chmod +x test-scope.sh # Run test suite ./test-scope.sh ``` ### Continuous Testing ```bash # Watch for changes and re-test while true; do inotifywait -r -e modify {config-root}/ ./test-scope.sh done ``` ## Performance Testing ### Measure Doctor Run Time ```bash # Time complete run time scope doctor run # Time specific group time scope doctor run --only group-name # Compare cached vs uncached time scope doctor run # With cache time scope doctor run --no-cache # Without cache ``` ### Profile Cache Effectiveness ```bash # First run (cold cache) scope doctor run > /tmp/run1.log 2>&1 # Second run (warm cache) scope doctor run > /tmp/run2.log 2>&1 # Compare diff /tmp/run1.log /tmp/run2.log ``` ## Debugging Tests ### Enable Verbose Output ```bash # Scope doesn't have --verbose, but you can debug scripts # Add to scripts: set -x # Print commands before execution # Example: #!/usr/bin/env bash set -euxo pipefail # Added 'x' for debug output ``` ### Capture Full Output ```bash # Capture stdout and stderr scope doctor run --only group-name > /tmp/stdout.log 2> /tmp/stderr.log # Capture combined scope doctor run --only group-name &> /tmp/combined.log # Capture and display scope doctor run --only group-name 2>&1 | tee /tmp/output.log ``` ### Test Specific Action ```bash # Doctor groups run all actions in sequence # To test just one action, you can run the script directly: ./.scope/bin/script.sh check ./.scope/bin/script.sh fix ``` ## Common Test Scenarios ### Test: Pattern with Special Characters ```bash # Pattern: "error: cannot lock ref 'refs/heads/main'" # Test: Does it escape properly? echo "error: cannot lock ref 'refs/heads/main'" > /tmp/test.txt # This should match: rg "cannot lock ref '[^']+'" /tmp/test.txt # This should NOT match (missing escape): rg "cannot lock ref 'refs/heads/main'" /tmp/test.txt # Literal string ``` ### Test: Path-Based Check Triggers on Change ```bash # Setup group with path check cat > .scope/path-test.yaml << 'EOF' spec: actions: - name: test check: paths: - config.yaml fix: commands: - echo "Config changed" EOF # First run - config doesn't exist, should trigger scope doctor run --only path-test # Create config echo "version: 1" > config.yaml # Second run - config exists, should trigger (first time seeing it) scope doctor run --only path-test # Third run - config unchanged, should NOT trigger scope doctor run --only path-test # Change config echo "version: 2" > config.yaml # Fourth run - config changed, should trigger scope doctor run --only path-test ``` ### Test: Dependency Order ```bash # Create test that verifies order cat > .scope/dep-order-test.yaml << 'EOF' spec: needs: - first - second actions: - name: verify check: commands: - test -f .first-ran - test -f .second-ran EOF # Run and check log order scope doctor run --only dep-order-test 2>&1 | grep -E "(first|second|verify)" ``` ## Best Practices ### DO ✓ Test regex patterns with `rg` before adding to YAML ✓ Create `.txt` test files with real error output ✓ Validate schema before testing functionality ✓ Test scripts standalone before integrating ✓ Use `--no-cache` when testing changes ✓ Test both success and failure paths ✓ Test dependency resolution ✓ Keep test files small and focused ✓ Use version control to track test changes ### DON'T ✗ Skip testing regex patterns in isolation ✗ Use synthetic error examples ✗ Assume patterns work without testing ✗ Test only the happy path ✗ Forget to make scripts executable ✗ Hard-code paths in tests ✗ Test in production first ✗ Commit without validation ## Troubleshooting Tests ### Pattern doesn't match test file ```bash # Debug steps: # 1. Check file encoding file -I test-file.txt # 2. Check for hidden characters cat -A test-file.txt # 3. Test pattern piece by piece rg "simple" test-file.txt rg "simple.*pattern" test-file.txt rg "full.*complex.*pattern" test-file.txt # 4. Check escaping rg "pattern with \. dot" test-file.txt ``` ### Check always fails ```bash # Debug steps: # 1. Run script manually ./.scope/bin/check.sh echo "Exit code: $?" # 2. Check for syntax errors bash -n ./.scope/bin/check.sh # 3. Add debug output set -x in script # 4. Check permissions ls -l ./.scope/bin/check.sh ``` ### Fix runs but doesn't work ```bash # Debug steps: # 1. Check fix script exit code ./.scope/bin/fix.sh echo "Exit code: $?" # 2. Check what fix actually does ./.scope/bin/fix.sh ls -la # Check if files created # 3. Run check after fix ./.scope/bin/fix.sh && ./.scope/bin/check.sh echo "Check exit code: $?" ``` ### Cache causes issues ```bash # Solutions: # 1. Always use --no-cache when testing scope doctor run --only test --no-cache # 2. Clear cache manually (implementation-specific) # Check scope docs for cache location # 3. Use command-based checks instead of path-based # Commands don't use cache ```