bddrunner

command module
v0.0.0-...-af520c7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 19, 2025 License: MIT Imports: 26 Imported by: 0

README

BDD Runner

Go Version License Go Report Card

A lightweight, configuration-driven BDD (Behavior-Driven Development) testing engine written in Go. BDD Runner focuses on "zero business coupling, pure configuration-driven" testing with powerful expression evaluation and macro systems.

🎯 Features

  • BDD Standard: Strict Given / When / Then structure (exactly 1 when per scenario)
  • Zero Coupling: HTTP uses only generic fields status/headers/body/body_raw; WS has no field restrictions
  • Expression Evaluation: Powerful expression system based on expr library, supporting variables, functions, operators
  • Macro System: Recursive expansion at configuration stage, no macro concepts at runtime
  • Optional Signing: http_api supports optional internal signing (sign.use: api_sign)
  • HTML Reports: Clear display of scenarios/steps/duration
  • Control Flow: Supports control flow steps like if/fail/skip
  • Synchronous Waiting: Supports WebSocket push and HTTP callback waiting mechanisms
  • Inline Functions: Built-in functions for time, encoding, hashing, and more
  • Import System: Support for importing external configuration files
  • Concurrent Execution: Multiple scenarios run concurrently for better performance

🚀 Quick Start

Installation
# Clone the repository
git clone https://github.com/magnaflowlabs/bddrunner.git
cd bddrunner

# Build the binary
make build

# Or install directly from GitHub
go install github.com/magnaflowlabs/bddrunner@latest
Version Information
# Show version information
./bddrunner -version

# Show build information
make version
Basic Usage
# Run a test configuration
./bddrunner -config example/basic_example.yaml

# Run with debug mode
./bddrunner -config example/basic_example.yaml -debug

# Run specific scenarios
./bddrunner -config example/macro_example.yaml -scenarios "user_management_test"

📖 Documentation

Configuration Structure
# Import external configuration files
imports:
  - macros_presets.yaml

# Global variables
vars:
  api_url: "https://api.example.com"
  test_user: "testuser"
  ws_url: "wss://ws.example.com/websocket"

# Test scenarios
scenarios:
  - name: "api_test"
    steps:
      - given: "set_var"
        key: "user_id"
        value: "uuid_v4()"
      
      - when: "http_api"
        url: api_url + "/users"
        method: "POST"
        body_obj:
          username: test_user
        out_var: "result"
      
      - then: "expect"
        condition: "result.status == 201"

# Reusable macros
macros:
  create_user:
    params: ["username", "email"]
    steps:
      - given: "http_api"
        url: api_url + "/users"
        method: "POST"
        body_obj:
          username: "${username}"
          email: "${email}"
        out_var: "create_result"
Built-in Steps
Setup Steps (Given)
  • set_var - Set variables (supports both key and name parameters)
  • http_server - Start HTTP server for callbacks
  • ws_connect - Connect to WebSocket
Operation Steps (Given/When)
  • http_api - HTTP API calls with optional signing
  • ws_api - WebSocket API calls
  • wait_push - Wait for WebSocket push messages
  • wait_callback - Wait for HTTP callback notifications
Common Steps (Given/When/Then)
  • sleep_ms - Sleep for milliseconds
  • log - Log messages with variable expansion
Assertion Steps (Then)
  • expect - Assert conditions with custom error messages
  • if - Conditional execution with then/else branches
  • fail - Force scenario failure
  • skip - Skip scenario execution
Expression System

BDD Runner uses the expr library for powerful expression evaluation:

# Variable references (no quotes)
value: "user_name"           # References variable user_name
value: "user_age"            # References variable user_age

# String literals (with quotes)
value: '"hello world"'       # String literal
method: '"POST"'             # HTTP method string

# Complex expressions
condition: "user_age > 18 && user_status == 'active'"
message: '"User: " + user_name + " is " + string(user_age) + " years old"'

# Function calls
value: "uuid_v4()"           # Generate UUID
value: "now_ms()"           # Current timestamp
value: "base64_encode('hello')"  # Base64 encoding
Macro System

Macros provide reusable test components with parameter substitution:

macros:
  auth_login:
    params: ["username", "password"]
    steps:
      - given: "ws_api"
        conn: "ws"
        method: '"auth_login"'
        params:
          username: "${username}"
          password: "${password}"
        out_var: "login_result"
      
      - given: "expect"
        condition: "login_result.code == 200"

# Usage
- call: "auth_login"
  args: ['"admin"', '"password123"']
Inline Functions

Built-in functions for common operations:

Time & ID Functions
  • now_ms() - Current timestamp in milliseconds
  • now_ts() - Current timestamp in seconds
  • uuid_v4() - Generate UUID v4
String Functions
  • random_string(length) - Generate random string
  • base64_encode(text) - Base64 encoding
  • base64_decode(text) - Base64 decoding
  • json_encode(obj) - JSON encoding
  • json_decode(json) - JSON decoding
Hash Functions
  • md5_hash(text) - MD5 hash
  • sha256_hash(text) - SHA256 hash
  • hmac_sha256(text, key) - HMAC-SHA256
Passkey Functions (WebAuthn)
  • passkey_generate_keypair() - Generate Ed25519 keypair
  • passkey_client_data(challenge, origin, crossOrigin) - Generate client data
  • passkey_authenticator_data(rp_id) - Generate authenticator data
  • passkey_signature(challenge, private_key, origin, crossOrigin, rp_id) - Generate signature
  • passkey_attestation_object(public_key, auth_data) - Generate attestation object
Import System

Support for importing external configuration files:

imports:
  - macros_presets.yaml
  - common_variables.yaml
  - auth_macros.yaml

Imported files can contain:

  • Global variables (later imports override earlier ones)
  • Macro definitions (later imports override earlier ones)
  • Additional scenarios (all scenarios are merged)
Control Flow

Conditional execution with if steps:

- then: "if"
  condition: "user_role == 'admin'"
  then_steps:
    - then: "set_var"
      key: "permissions"
      value: '"full_access"'
  else_steps:
    - then: "set_var"
      key: "permissions"
      value: '"limited_access"'

📁 Project Structure

bddrunner/
├── main.go                    # Entry point
├── engine.go                  # Core engine and execution
├── config.go                  # Configuration loading and imports
├── context.go                 # Runtime context and variables
├── registry.go                # Step and macro registry
├── steps.go                   # Built-in steps (set_var, log, sleep_ms)
├── expr.go                    # Expression evaluation system
├── functions.go               # Inline functions implementation
├── macro_expander.go          # Macro expansion system
├── transport_http.go           # HTTP transport and API signing
├── transport_ws.go            # WebSocket transport
├── api_sign.go                # API signature implementation
├── control.go                 # Control flow steps (if, fail, skip)
├── report.go                  # Test reporting and HTML generation
├── scenario_executor.go       # Scenario execution engine
├── docs/                      # Documentation
│   ├── ARCHITECTURE.md        # System architecture
│   ├── EXPRESSION_SYSTEM.md   # Expression evaluation details
│   ├── MACRO_SYSTEM.md        # Macro system design
│   └── API_REFERENCE.md       # Complete API reference
├── example/                   # Example configurations
│   ├── basic_example.yaml
│   ├── macro_example.yaml
│   ├── control_flow_example.yaml
│   ├── inline_functions_example.yaml
│   └── README.md
├── testdata/                  # Test configurations
│   ├── basic_expr_test.yaml
│   ├── condition_message_expand_test.yaml
│   ├── function_call_test.yaml
│   ├── test_basic_steps.yaml
│   ├── test_control_flow.yaml
│   ├── test_inline_functions.yaml
│   ├── test_macro_system.yaml
│   ├── ws_api_test.yaml
│   └── README.md
├── Makefile                   # Build and test automation
├── test.sh                    # Test runner script
├── .gitignore                 # Git ignore rules
├── LICENSE                    # MIT License
├── go.mod                     # Go module file
├── go.sum                     # Go dependencies
└── README.md                  # This file

🧪 Examples

Check the example/ directory for comprehensive examples:

  • basic_example.yaml - Basic HTTP and WebSocket testing
  • macro_example.yaml - Reusable macro components
  • control_flow_example.yaml - Conditional logic and error handling
  • inline_functions_example.yaml - Built-in function usage

🔧 Development

Building
# Build binary
make build

# Build for Linux
make build-linux

# Show version information
make version

# Clean build artifacts
make clean
Testing
# Run unit tests
make test

# Run example tests
make test-examples

# Run testdata tests
make test-testdata

# Run all tests
make test-all

# Run comprehensive test suite
./test.sh

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • expr - Expression evaluation library
  • godog - BDD framework inspiration
  • gorilla/websocket - WebSocket implementation
  • Go community for excellent tooling and libraries

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL