An open API service indexing awesome lists of open source software.

https://github.com/jianloong/robogo

A modern, developer-friendly test automation framework with clean YAML syntax for comprehensive end-to-end testing written in Go.
https://github.com/jianloong/robogo

api-rest banking finance go kafka spanner-database swift-messages test-automation

Last synced: about 2 months ago
JSON representation

A modern, developer-friendly test automation framework with clean YAML syntax for comprehensive end-to-end testing written in Go.

Awesome Lists containing this project

README

          

# ๐Ÿค– Robogo

**A multi-service automation tool written in Go**

*Clean YAML-based workflows for HTTP APIs, databases, messaging systems, file operations, and more*

---

### ๐Ÿš€ Quick Links

| **Getting Started** | **Examples** | **Documentation** | **Architecture** |
|:---:|:---:|:---:|:---:|
| [Installation](#installation) | [Your First Test](#your-first-test) | [Complete Examples](examples/README.md) | [KISS Principles](#kiss-principles) |
| [Basic Usage](#basic-usage) | [Test Categories](#example-tests) | [Action Reference](#action-categories) | [Execution Flow](docs/execution-flow-diagram.md) |
| [Quick Start](#quick-start) | [Security Examples](#security-examples) | [Error Handling](docs/error-failure-states-diagram.md) | [Development Guide](internal/README.md) |

---

**Multi-Service Automation**: Robogo enables developers to automate workflows across HTTP APIs, databases, messaging systems, and file operations with clear, readable YAML definitions that improve productivity and reduce manual work.

## Features

### Core Capabilities
- **Developer-Friendly**: Clear, readable YAML workflows that developers can easily understand and maintain
- **Multi-Service Integration**: Automate workflows across HTTP APIs, databases, messaging systems, and file operations
- **Simple YAML Workflows**: Write automation in clean, readable YAML format with powerful features
- **KISS Architecture**: Keep It Simple and Straightforward - no over-engineering or complex abstractions

### Actions & Integrations
- **HTTP Automation**: Full HTTP client with all methods, authentication, and response processing
- **Database Operations**: PostgreSQL, MongoDB, and Google Cloud Spanner with secure credential management
- **Messaging Systems**: Kafka and RabbitMQ operations with producer/consumer support
- **File Operations**: Local file reading and secure SCP file transfers via SSH/SFTP
- **Financial Messaging**: SWIFT message generation for banking and financial workflows
- **Data Processing**: JSON/XML parsing, construction, and extraction with jq/xpath support
- **String Operations**: Random generation, formatting, encoding/decoding, and manipulation
- **Utility Actions**: UUID generation, time operations, sleep/timing, assertions, and logging

### Advanced Features
- **Variable Substitution**: Dynamic variables with `${variable}` and `${ENV:VARIABLE}` syntax
- **Security-First**: Automatic sensitive data masking, no-log mode, and environment variable support
- **Control Flow**: Conditional execution (`if`), retry logic with backoff, and nested step collections
- **Data Extraction**: Extract data from responses using jq, xpath, or regex patterns
- **Error Handling**: Comprehensive error categorization with user-friendly messages
- **Clean CLI Tool**: Immediate connection handling - no hanging processes

### Recent Improvements (2024)
- **Architecture Simplification**: Removed 6+ abstraction layers, eliminated dependency injection
- **SCP File Transfer**: Secure SSH/SFTP support with password and key authentication
- **Enhanced Security**: Step-level security controls, comprehensive data masking
- **File Organization**: Split large files into focused, maintainable modules
- **Comprehensive Documentation**: README files throughout codebase for better navigation

## Quick Start

### Installation

```bash
# Build for your platform
go build -o robogo ./cmd/robogo
```

### Basic Usage

```bash
# Run a single test
./robogo run my-test.yaml

# Run test with custom .env file
./robogo --env production.env run my-test.yaml

# List available actions
./robogo list

# Show version
./robogo version
```

### Output Formats

Robogo supports multiple output formats for different use cases:

```bash
# Console output (default) - human-readable table format
./robogo run test.yaml

# JUnit XML output - for CI/CD integration
./robogo run test.yaml --output junit --output-file results.xml

# JSON output - for programmatic processing
./robogo run test.yaml --output json --output-file results.json

# Quiet mode - suppress console output when writing to file
./robogo run test.yaml --output junit --output-file results.xml --quiet
```

**CI/CD Integration Examples:**
```bash
# GitHub Actions / Jenkins / GitLab CI
./robogo run tests/integration.yaml --output junit --output-file test-results.xml

# Generate both XML and JSON reports
./robogo run test.yaml --output junit --output-file results.xml
./robogo run test.yaml --output json --output-file results.json
```

๐Ÿ“– **Complete Documentation**: See **[docs/junit-xml-output.md](docs/junit-xml-output.md)** for detailed JUnit XML structure, mapping, and CI/CD integration examples.

### Your First Workflow

The quickest way to get started is with our showcase HTTP example:

```bash
# Run the main showcase workflow (no setup needed)
./robogo run examples/02-http/01-http-get.yaml
```

**Main Showcase Example:**
```yaml
testcase: "TC-HTTP-001"
description: "Workflow to demonstrate HTTP response processing"

variables:
vars:
base_url: "http://localhost:8000/base64/SFRUUEJJTiBpcyBhd2Vzb21l"
expected_value: "HTTPBIN is awesome"

steps:
- name: "Make HTTP request"
action: http
args: ["GET", "${base_url}"]
result: "http_response"

- name: "Extract status code"
action: jq
args: ["${http_response}", ".status_code"]
result: "status_code"

- name: "Verify status code"
action: assert
args: ["${status_code}", "==", "200"]

- name: "Extract response body"
action: jq
args: ["${http_response}", ".body"]
result: "response_body"

- name: "Verify expected content"
action: assert
args: ["${response_body}", "==", "${expected_value}"]
```

**Expected output:**
```
Running test case: TC-HTTP-001
Description: Workflow to demonstrate HTTP response processing
Setup: 0, Steps: 7, Teardown: 0

Step 1: Make HTTP request
Action: http
Args: [GET http://localhost:8000/base64/SFRUUEJJTiBpcyBhd2Vzb21l]
Options: map[timeout:5s]
Result Variable: http_response
Executing...
โœ“ PASSED (10.959687ms)

Step 2: Extract status code
Action: jq
Args: [.status_code]
Result Variable: status_code
Executing...
โœ“ PASSED (973.434ยตs)
Data: 200

Step 3: Verify status code
Action: assert
Args: [200 == 200]
Executing...
โœ“ PASSED (306.971ยตs)

Step 4: Extract response body
Action: jq
Args: [.body]
Result Variable: response_body
Executing...
โœ“ PASSED (151.688ยตs)
Data: HTTPBIN is awesome

Step 5: Verify expected content
Action: assert
Args: [HTTPBIN is awesome == HTTPBIN is awesome]
Executing...
โœ“ PASSED (475.234ยตs)

Test Summary:
Name: TC-HTTP-001
Status: PASS
Duration: 13.589684ms

| # | Step Name | Status | Duration |
|-----|------------------------------------------|----------|--------------|
| 1 | Make HTTP request | PASS | 10.959687ms |
| 2 | Extract status code | PASS | 973.434ยตs |
| 3 | Verify status code | PASS | 306.971ยตs |
| 4 | Extract response body | PASS | 151.688ยตs |
| 5 | Verify expected content | PASS | 475.234ยตs |
```

**What this demonstrates:**
- HTTP requests with response capture (`result: "http_response"`)
- JSON data extraction using `jq` action (`.status_code`, `.body`)
- Variable substitution and storage (`${http_response}`, `${status_code}`)
- Assertions for validation (`assert` action)
- Clean workflow structure with clear step-by-step execution
- Performance timing for each step

## Documentation

### ๐Ÿ“š **Getting Started**
- **[examples/README.md](examples/README.md)** - Comprehensive test examples from beginner to expert
- **[docs/execution-flow-diagram.md](docs/execution-flow-diagram.md)** - Visual architecture flow diagram
- **[docs/error-failure-states-diagram.md](docs/error-failure-states-diagram.md)** - Error handling and state management flow

### ๐Ÿ—๏ธ **Architecture**
- **[internal/README.md](internal/README.md)** - Core architecture principles and KISS design
- **[internal/execution/README.md](internal/execution/README.md)** - Execution strategy pattern system
- **[internal/actions/README.md](internal/actions/README.md)** - Complete action system documentation

### ๐Ÿ“– **Reference**
- **[docs/README.md](docs/README.md)** - Documentation overview and navigation guide
- **[docs/junit-xml-output.md](docs/junit-xml-output.md)** - JUnit XML output format and CI/CD integration
- **[examples/13-output-formats/README.md](examples/13-output-formats/README.md)** - Output format examples and usage patterns
- **[CLAUDE.md](CLAUDE.md)** - Development instructions and project context

## Action Categories

### Core Actions
- **`assert`** - Test assertions and validations
- **`log`** - Logging and output messages
- **`variable`** - Variable manipulation and setting

### HTTP & API Testing
- **`http`** - HTTP requests (GET, POST, PUT, DELETE, etc.) with full header and authentication support

### Database Operations
- **`postgres`** - PostgreSQL database queries and operations
- **`spanner`** - Google Cloud Spanner distributed database support

### File Operations
- **`file_read`** - Local file reading with format detection
- **`scp`** - Secure file transfer via SSH/SFTP (upload/download)

### Messaging Systems
- **`kafka`** - Apache Kafka producer/consumer operations
- **`rabbitmq`** - RabbitMQ message operations
- **`swift_message`** - SWIFT financial messaging (MT103)

### Data Processing
- **`jq`** - JSON data processing and extraction
- **`xpath`** - XML data processing and queries
- **`json_parse`/`json_build`** - JSON parsing and construction
- **`xml_parse`/`xml_build`** - XML parsing and construction
- **`csv_parse`** - CSV file and string parsing with configurable delimiters, headers, and row limits

### String & Encoding
- **`string_random`** - Random string generation
- **`string_replace`/`string_format`** - String manipulation
- **`base64_encode`/`base64_decode`** - Base64 operations
- **`url_encode`/`url_decode`** - URL encoding
- **`hash`** - Cryptographic hashing (MD5, SHA1, SHA256)

### Utilities
- **`uuid`** - UUID v4 generation
- **`time`** - Time operations and formatting
- **`sleep`** - Delays and timing control
- **`ping`** - Network connectivity testing with ICMP ping

### Security & Validation
- **`ssl_cert_check`** - SSL certificate validation, expiry checking, chain verification, and hostname validation

## Test Structure

### Example Tests

Robogo includes 56 comprehensive test examples organized into 12 categories. Here are the key examples:

| Category | Example | Features Demonstrated | Command |
|----------|---------|----------------------|---------|
| **HTTP Basics** | [01-http-get.yaml](examples/02-http/01-http-get.yaml) | GET requests, jq extraction, assertions | `./robogo run examples/02-http/01-http-get.yaml` |
| **HTTP POST** | [02-http-post.yaml](examples/02-http/02-http-post.yaml) | POST with JSON, nested data extraction | `./robogo run examples/02-http/02-http-post.yaml` |
| **Utilities** | [00-util.yaml](examples/01-basics/00-util.yaml) | UUID generation, basic logging | `./robogo run examples/01-basics/00-util.yaml` |
| **Environment Variables** | [17-env-var-test.yaml](examples/10-security/17-env-var-test.yaml) | ${ENV:VAR} syntax, credential management | `./robogo run examples/10-security/17-env-var-test.yaml` |
| **Security** | [19-no-log-security.yaml](examples/10-security/19-no-log-security.yaml) | no_log, sensitive_fields, data masking | `./robogo run examples/10-security/19-no-log-security.yaml` |
| **Database** | [03-postgres-basic.yaml](examples/03-database/03-postgres-basic.yaml) | PostgreSQL operations, queries | `./robogo run examples/03-database/03-postgres-basic.yaml` |
| **MongoDB** | [40-mongodb-basic.yaml](examples/03-database/40-mongodb-basic.yaml) | MongoDB document operations, aggregations | `./robogo run examples/03-database/40-mongodb-basic.yaml` |
| **Conditional Logic** | [08-control-flow.yaml](examples/09-advanced/08-control-flow.yaml) | Conditional execution with if statements | `./robogo run examples/09-advanced/08-control-flow.yaml` |
| **Retry Logic** | [13-retry-demo.yaml](examples/09-advanced/13-retry-demo.yaml) | Retry with backoff, error handling | `./robogo run examples/09-advanced/13-retry-demo.yaml` |
| **Nested Steps** | [21-simple-nested-test.yaml](examples/09-advanced/21-simple-nested-test.yaml) | Grouped operations, continue-on-error | `./robogo run examples/09-advanced/21-simple-nested-test.yaml` |
| **File Transfer** | [23-scp-simple-test.yaml](examples/05-files/23-scp-simple-test.yaml) | SSH/SFTP file operations | `./robogo run examples/05-files/23-scp-simple-test.yaml` |
| **Network Testing** | [26-ping-network-test.yaml](examples/11-network/26-ping-network-test.yaml) | ICMP ping connectivity testing | `./robogo run examples/11-network/26-ping-network-test.yaml` |
| **SSL Certificate** | [34-ssl-cert-check.yaml](examples/11-network/34-ssl-cert-check.yaml) | Certificate validation, expiry checks | `./robogo run examples/11-network/34-ssl-cert-check.yaml` |
| **CSV Processing** | [35-csv-parsing.yaml](examples/06-data-processing/35-csv-parsing.yaml) | CSV parsing, extraction, filtering | `./robogo run examples/06-data-processing/35-csv-parsing.yaml` |

**๐Ÿ“ Browse all examples:** See **[examples/README.md](examples/README.md)** for the complete catalog with beginner to expert examples.

### Key Test Structure Elements
All Robogo tests follow this pattern:
```yaml
testcase: "Test Name"
description: "What this test does"

variables:
vars:
variable_name: "value"
api_url: "${ENV:API_URL}" # Environment variables

steps:
- name: "Make HTTP request with built-in extraction"
action: http
args: ["GET", "${api_url}"]
extract:
type: "jq"
path: ".status_code"
result: status_code

- name: "Verify result"
action: assert
args: ["${status_code}", "==", "200"]
```

**Important:** Use `jq` action to extract data from HTTP responses - simple `${response.field}` syntax doesn't work for complex objects. You can either:
1. **Use built-in `extract`** (modern approach): Add `extract` block to any step for automatic data extraction
2. **Use separate `jq` step** (traditional approach): Extract in a separate step, then use the extracted value

**Extract Types:** Robogo supports multiple built-in extract types:
- `jq` - JSON path queries (`.field`, `.array[0]`, etc.)
- `xpath` - XML path queries for XML data
- `regex` - Regular expression pattern matching with capture groups
- `csv` - CSV data extraction with row/column/cell extraction and filtering support

**Advanced Features:** The examples table above includes advanced patterns like retry logic, control flow, nested steps, and security features. For the complete catalog with complexity levels, see **[examples/README.md](examples/README.md)**.

## Security Features

### Security Examples

Robogo provides comprehensive security features for sensitive data handling:

| Security Feature | Example | What It Demonstrates | Command |
|-----------------|---------|---------------------|---------|
| **Environment Variables** | [17-env-var-test.yaml](examples/10-security/17-env-var-test.yaml) | `${ENV:VAR}` syntax, credential management | `export TEST_ENV_VAR="test_value" && ./robogo run examples/10-security/17-env-var-test.yaml` |
| **Database Security** | [03-postgres-secure.yaml](examples/03-database/03-postgres-secure.yaml) | .env file usage, secure DB connections | `./robogo run examples/03-database/03-postgres-secure.yaml` |
| **No-Log Mode** | [19-no-log-security.yaml](examples/10-security/19-no-log-security.yaml) | Complete logging suppression, sensitive fields | `./robogo run examples/10-security/19-no-log-security.yaml` |
| **Step-Level Masking** | [20-step-level-masking.yaml](examples/10-security/20-step-level-masking.yaml) | Custom field masking, fine-grained controls | `./robogo run examples/10-security/20-step-level-masking.yaml` |

**Key Security Features:**
- **Automatic masking**: Password, token, key fields automatically hidden
- **Custom masking**: Use `sensitive_fields: ["field_name"]` for custom fields
- **No-log mode**: Use `no_log: true` to suppress all step logging
- **Environment variables**: Use `${ENV:VARIABLE}` for secure credential access

### Secret Management Philosophy

**Robogo follows the principle of external secret management:**

- **๐Ÿ” Pipeline Responsibility**: CI/CD pipelines and deployment systems should retrieve secrets from proper secret stores (HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, etc.)
- **๐Ÿ“‹ Environment Variable Injection**: Secrets are injected as environment variables using `${ENV:SECRET}` syntax
- **๐Ÿšซ No Built-in Secret Stores**: Robogo intentionally doesn't implement secret management to avoid reinventing security infrastructure
- **๐Ÿ”Œ Integration via Standards**: Uses standard environment variable patterns that work with any secret management system
- **๐Ÿ—๏ธ Infrastructure Separation**: Secret management is an infrastructure concern, not an automation tool concern

**Example Integration Patterns:**
```bash
# HashiCorp Vault
export API_TOKEN="$(vault kv get -field=token secret/api)"

# AWS Secrets Manager
export DB_PASSWORD="$(aws secretsmanager get-secret-value --secret-id prod/db/password --query SecretString --output text)"

# Kubernetes Secrets (in pod)
export API_KEY="$(cat /var/secrets/api-key)"

# CI/CD Pipeline (GitHub Actions)
export DATABASE_URL="${{ secrets.DATABASE_URL }}"
```

**Why This Approach:**
- โœ… **Security Best Practice**: Leverages proven, audited secret management systems
- โœ… **Flexibility**: Works with any secret store or deployment pattern
- โœ… **Separation of Concerns**: Automation logic separate from credential management
- โœ… **Compliance Ready**: Integrates with enterprise security policies
- โœ… **No Vendor Lock-in**: Not tied to specific secret management solutions

## Development Environment

### Prerequisites
- Go 1.24+
- Docker & Docker Compose (for services)

### Development Services

```bash
# Start all services
docker-compose up -d

# Services available:
# - PostgreSQL: localhost:5432 (user: robogo_testuser, pass: robogo_testpass, db: robogo_testdb)
# - Kafka: localhost:9092
# - Spanner Emulator: localhost:9010
# - HTTPBin: localhost:8000
# - SSH Server: localhost:2222 (user: testuser, pass: testpass)
```

### Environment Configuration

Create `.env` file for secure credential management:
```bash
# Database credentials
DB_HOST=localhost
DB_PORT=5432
DB_USER=robogo_testuser
DB_PASSWORD=robogo_testpass
DB_NAME=robogo_testdb

# API credentials
API_BASE_URL=https://api.example.com
API_TOKEN=your_secret_token_here

# SSH credentials for SCP testing
SSH_PASSWORD=testpass
```

### Database Setup

**PostgreSQL** - Use environment variables for credentials:
```yaml
variables:
vars:
db_url: "postgres://${ENV:DB_USER}:${ENV:DB_PASSWORD}@${ENV:DB_HOST}:${ENV:DB_PORT}/${ENV:DB_NAME}?sslmode=disable"

steps:
- name: "Test database connection"
action: postgres
args: ["query", "${db_url}", "SELECT version()"]
result: db_version
```

**Google Cloud Spanner** - Set up emulator:
```bash
# After starting docker-compose
# Linux/Mac:
SPANNER_EMULATOR_HOST=localhost:9010 ./setup-spanner.sh
# Windows:
.\setup-spanner.ps1
```

## Example Tests

The **[examples/](examples/)** directory contains 56 comprehensive test examples organized into 12 categories by feature and complexity:

### Quick Examples
```bash
# HTTP testing (no services required)
./robogo run examples/02-http/01-http-get.yaml

# Database testing (requires docker-compose up -d)
./robogo run examples/03-database/03-postgres-basic.yaml

# SCP file transfer testing
./robogo run examples/05-files/23-scp-simple-test.yaml

# Messaging systems
./robogo run examples/04-messaging/05-kafka-basic.yaml

# Security features
./robogo run examples/10-security/19-no-log-security.yaml
```

### Example Categories
- **Beginner**: Basic HTTP, database, and file operations
- **Intermediate**: Multi-step workflows, environment variables, data extraction
- **Advanced**: Complex control flow, retry logic, nested operations
- **Expert**: Security-aware testing, production-ready patterns

## Architecture

### KISS Principles
Robogo follows **Keep It Simple and Straightforward** architecture:

- **No Dependency Injection**: Direct object construction throughout
- **No Over-abstraction**: Simple, direct implementations
- **Minimal Interfaces**: Only where absolutely necessary
- **Strategy Pattern**: Clean execution routing for different step types

### Design Philosophy: Explicit Tests Over Loops

Robogo intentionally **does not support `for` and `while` loops** in test definitions. This design decision prioritizes **test clarity and maintainability** over code brevity.

**Why no loops?**
- **Test purpose matters**: Behavioral tests should be explicit about what they're testing
- **Debugging clarity**: `test_user_creation_with_missing_email()` is clearer than "step 7 failed in user creation loop"
- **Living documentation**: Tests serve as executable specifications - loops obscure intent
- **Industry alignment**: Most YAML-based testing frameworks avoid complex control flow

**When to use explicit tests vs loops:**
- โœ… **Explicit tests for**: Business logic validation, user workflows, API contract testing
- โŒ **Avoid loops for**: Individual test scenarios, specific edge cases, acceptance criteria
- โš ๏ธ **Loops might be appropriate for**: Framework testing, property-based testing, infrastructure validation

**Example of preferred explicit approach:**
```yaml
# โœ… Clear and maintainable
steps:
- name: "User registration accepts valid email"
action: http
args: ["POST", "/users", '{"email": "user@example.com"}']

- name: "User registration rejects email without @"
action: http
args: ["POST", "/users", '{"email": "invalid-email"}']
```

Instead of:
```yaml
# โŒ Obscures test intent
steps:
- name: "Test email validation"
for: "[user@example.com, invalid-email]"
action: http
args: ["POST", "/users", '{"email": "${item}"}']
```

This philosophy aligns with industry best practices where test automation frameworks either avoid loops entirely (GitHub Actions) or use specialized syntax (Robot Framework) rather than general-purpose loops.

### Execution Flow
1. **CLI** receives command and parses YAML test file
2. **TestRunner** creates execution environment with variables and strategy router
3. **ExecutionStrategyRouter** routes steps based on priority:
- **ConditionalExecutionStrategy** (Priority 4): Handles `if` conditions
- **RetryExecutionStrategy** (Priority 3): Handles `retry` configuration
- **NestedStepsExecutionStrategy** (Priority 2): Handles `steps` arrays
- **BasicExecutionStrategy** (Priority 1): Handles simple actions
4. **Actions** perform actual operations and return structured results
5. **Results** are processed, masked for security, and displayed

For detailed architecture documentation, see **[internal/README.md](internal/README.md)** and **[docs/execution-flow-diagram.md](docs/execution-flow-diagram.md)**.

## Error Handling

### Dual Error System
- **ErrorInfo**: Technical problems (network failures, syntax errors, etc.)
- **FailureInfo**: Logical test failures (assertion failures, unexpected responses)

### Visual Error Flow Diagram
For a comprehensive visual explanation of Robogo's error handling, execution flow, and state management, see:
**[docs/error-failure-states-diagram.md](docs/error-failure-states-diagram.md)** - Complete mermaid diagram showing execution strategies, error classification, and result processing.

### Structured Error Messages
```yaml
# Technical error example
steps:
- name: "Invalid database query"
action: postgres
args: ["query", "invalid://connection", "SELECT 1"]
# Results in ErrorInfo with connection details and suggestions

# Logical failure example
- name: "Assertion failure"
action: assert
args: ["${status_code}", "==", "200"] # After extracting with jq
# Results in FailureInfo showing expected vs actual values
```

## Shift-Left Testing Benefits

Robogo enables **true shift-left testing** by allowing developers to:

### For Developers
- **Run Full E2E Tests Locally**: Complete integration tests with databases, messaging, and external APIs
- **Clear Test Intent**: YAML format makes test logic immediately visible and understandable
- **Fast Feedback**: Quick test execution with immediate connection handling
- **Easy Setup**: Simple environment setup for comprehensive testing

### For Teams
- **Improved Collaboration**: QA and developers can read and modify the same test definitions
- **Living Documentation**: Tests serve as executable specifications of system behavior
- **Early Bug Detection**: Catch integration issues before they reach staging environments
- **Reduced Testing Debt**: E2E tests written during development, not as an afterthought

### Example: Developer Workflow
```bash
# 1. Run relevant tests during development
./robogo run tests/user-registration-flow.yaml
./robogo run tests/payment-processing.yaml

# 2. Validate changes before commit
./robogo run tests/critical-paths.yaml

# 3. Run in CI/CD pipeline
./robogo run tests/smoke-tests.yaml
```

## Parallel Execution

Robogo is designed for **test-level parallelism** (multiple test files) rather than **step-level parallelism** (steps within a test).

### โš ๏ธ Output Mixing Issue

When running tests in parallel **without output redirection**, the stdout will be mixed and confusing:

```bash
# โŒ This will create mixed, unreadable output
./robogo run test1.yaml & \
./robogo run test2.yaml & \
./robogo run test3.yaml & \
wait
```

### โœ… Recommended Parallel Approaches

**Option 1: Redirect to separate files**
```bash
# Each test outputs to its own file
./robogo run test1.yaml > test1.log 2>&1 & \
./robogo run test2.yaml > test2.log 2>&1 & \
./robogo run test3.yaml > test3.log 2>&1 & \
wait

# View results separately
cat test1.log test2.log test3.log
```

**Option 2: Run sequentially with timing**
```bash
# Fast sequential execution, readable output
time ./robogo run test1.yaml
time ./robogo run test2.yaml
time ./robogo run test3.yaml
```

**Option 3: Use CI/CD parallelism**
```yaml
# GitHub Actions example
jobs:
test:
strategy:
matrix:
test: [test1.yaml, test2.yaml, test3.yaml]
runs-on: ubuntu-latest
steps:
- run: ./robogo run ${{ matrix.test }}
```

### Why Sequential Steps?
Steps within a test are intentionally sequential because they represent a logical flow where later steps depend on earlier results:

```yaml
steps:
- name: "Create user"
action: http
args: ["POST", "/users", "..."]
result: response

- name: "Verify user created" # This DEPENDS on the above step
action: assert
args: ["${status_code}", "==", "201"] # After extracting with jq
```

## Test Data Management

Robogo **does not include built-in test data management** (fixtures, factories, seeding utilities) and is intentionally designed this way following KISS principles.

### Design Philosophy

- **No Over-abstraction**: Use actual database/API operations instead of data management frameworks
- **Direct Operations**: Tests perform real operations that mirror production workflows
- **External Integration**: Leverage existing data tools rather than reinventing them
- **Transparency**: Clear visibility into what data operations are happening

### Recommended Approaches

**Setup/Teardown with Database Actions:**
```yaml
setup:
- name: "Create test data"
action: postgres
args: ["execute", "${db_url}", "INSERT INTO users (name, email) VALUES ('Test User', 'test@example.com')"]

teardown:
- name: "Clean up test data"
action: postgres
args: ["execute", "${db_url}", "DELETE FROM users WHERE email = 'test@example.com'"]
```

**API-Based Data Management:**
```yaml
setup:
- name: "Create test user via API"
action: http
args: ["POST", "${api_url}/users", "${user_data}"]
extract:
type: "jq"
path: ".body.id"
result: user_id

teardown:
- name: "Delete test user"
action: http
args: ["DELETE", "${api_url}/users/${user_id}"]
```

**External Scripts Integration:**
```yaml
setup:
- name: "Seed test database"
action: bash
args: ["./scripts/seed-test-data.sh", "${ENV:TEST_ENVIRONMENT}"]
```

**Dynamic Data Generation:**
```yaml
- name: "Generate unique test data"
action: time
args: ["20060102150405"]
result: timestamp

- name: "Create unique user email"
action: string_format
args: ["test-user-{}@example.com", "${timestamp}"]
extract:
type: "jq"
path: ".result"
result: unique_email
```

This approach maintains test clarity while allowing flexible integration with existing data management tools and practices.

## Test Scheduling

Robogo is designed as a **single-execution CLI tool** that runs individual tests on-demand and exits cleanly. It **does not have built-in scheduling capabilities** and is intentionally architected this way following KISS principles.

### Design Philosophy
- **No Built-in Scheduling**: No cron, timers, or background job processing
- **CLI-First Design**: Meant to be invoked manually or by external schedulers
- **Immediate Execution Model**: Runs test โ†’ exits (no persistent processes)
- **External Integration**: Designed to work with existing scheduling infrastructure

### Scheduling Options

**Cron (Linux/Mac)**
```bash
# Run test every hour
0 * * * * /path/to/robogo run /path/to/test.yaml

# Run test every 5 minutes
*/5 * * * * /path/to/robogo run /path/to/test.yaml >> /var/log/robogo.log 2>&1

# Run test daily at 2 AM
0 2 * * * /path/to/robogo run /path/to/nightly-test.yaml
```

**Windows Task Scheduler**
```powershell
# Create scheduled task that runs robogo
schtasks /create /tn "RobogoTest" /tr "C:\path\to\robogo.exe run test.yaml" /sc hourly
```

**CI/CD Pipeline Scheduling**
```yaml
# GitHub Actions example
name: Scheduled Tests
on:
schedule:
- cron: '0 */6 * * *' # Every 6 hours
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run Integration Tests
run: ./robogo run examples/12-integration/09-e2e-integration.yaml
```

**Docker with Cron**
```dockerfile
FROM golang:1.21-alpine
COPY robogo /usr/local/bin/robogo
COPY tests/ /tests/
# Add cron job
RUN echo "0 */2 * * * /usr/local/bin/robogo run /tests/health-check.yaml" | crontab -
CMD ["crond", "-f"]
```

**Kubernetes CronJob**
```yaml
apiVersion: batch/v1
kind: CronJob
metadata:
name: robogo-tests
spec:
schedule: "0 */4 * * *" # Every 4 hours
jobTemplate:
spec:
template:
spec:
containers:
- name: robogo
image: robogo:latest
command: ["./robogo", "run", "tests/smoke-test.yaml"]
restartPolicy: OnFailure
```

### Why External Scheduling?

This design aligns with robogo's **KISS architecture** principles:
- **Simple & Direct**: Focus on reliable test execution, not infrastructure concerns
- **CLI Tool Design**: Clean exit, no hanging processes, easy integration
- **Immediate Connections**: Open/close per operation, no persistent state to manage
- **Minimal Dependencies**: Let existing tools handle scheduling rather than reinventing

**Benefits:**
- **Reliability**: Use proven scheduling systems (cron, K8s, CI/CD)
- **Flexibility**: Any scheduling system can invoke robogo
- **Simplicity**: No complex scheduling logic to maintain or debug
- **Integration**: Works seamlessly with existing infrastructure

## Troubleshooting

### Common Issues

1. **Service connection errors**: Ensure Docker services are running (`docker-compose ps`)
2. **Environment variable issues**: Check `.env` file exists and variables are properly formatted
3. **SCP/SSH connection issues**: Verify SSH server is running and credentials are correct
4. **Variable resolution errors**: Check `${variable}` syntax and variable names
5. **Database connection errors**: Verify Docker services are healthy

### Debug Tips

- Use `log` actions to inspect variable values
- Check Docker service logs: `docker-compose logs `
- Use shorter timeouts for faster feedback during development
- Enable verbose logging for debugging complex variable substitution

### Getting Help

- **Documentation**: Start with **[examples/README.md](examples/README.md)** for practical examples
- **Architecture**: See **[internal/README.md](internal/README.md)** for understanding the codebase
- **Issues**: Report bugs or feature requests on the project repository

## Contributing

1. **Follow KISS principles**: Avoid over-engineering and complex abstractions
2. **Add examples**: Every new feature should include working test examples
3. **Update documentation**: Keep README files current with code changes
4. **Security-first**: Ensure sensitive data is properly masked
5. **Test thoroughly**: Verify examples work with standard Docker setup

## License

MIT License - see LICENSE file for details.