Back to Home

How It Works

Four simple steps to transform your API testing process

1

Initialize Project

Run bumblebee init with your OpenAPI specification. Flow files and MiniZinc data structures are automatically generated for all your endpoints.

2

Define Constraints

Write input and output constraints in the auto-generated MiniZinc files to specify valid test data and expected response validation rules.

3

Configure State Machine

Define your application's state transitions in JavaScript, specifying how API responses update the global system state.

4

Define Execution Graph

Create execution flows that specify the sequence of operations. Once defined, Bumblebee automatically tests all possible happy paths and all possible error paths. This eliminates the tedious manual work of specifying individual execution paths - a massive improvement over traditional testing approaches.

5

Run Automated Tests

Execute comprehensive test suites that automatically generate inputs, run operations, validate outputs, and maintain state consistency across your entire API.

Quick Start

Get up and running with Bumblebee in minutes

1. Initialize Your Project

# Install Bumblebee npm install -g @bumblebee/cli # Initialize project with your OpenAPI spec bumblebee init --spec ./api/openapi.yaml # This auto-generates: # - Flow definitions for each endpoint # - MiniZinc constraint templates # - State machine scaffolding

2. Define Your Constraints

Edit the auto-generated MiniZinc files to specify your test data constraints:

% flows/add_item_to_cart/input_constraints.mzn constraint request.body.quantity > 0; constraint request.body.quantity <= 100; constraint bumblebeeRegular(request.body.itemId, "[49-57 65-90 97-122]{4}1114112*"); % flows/add_item_to_cart/output_constraints.mzn constraint response.item.quantity = request.body.quantity; constraint response.item.price > 0.0;

3. Configure State Management

Define how your application state evolves:

// state-machine.js class CartFlowState { constructor() { this.cart = { items: [], total: 0 }; } onOutput(operationName, response) { if (operationName === 'add_item_to_cart') { this.cart.items.push(response.item); this.updateTotal(); } if (operationName === 'remove_item_from_cart') { this.cart.items = this.cart.items.filter( item => item.id !== response.removedId ); this.updateTotal(); } } getState() { return this.cart; } }

4. Run Your Tests

# Run comprehensive test suite bumblebee test --flow shopping-cart # Generate test report bumblebee test --report

✅ That's it! Bumblebee will automatically generate thousands of test cases, execute them against your API, and validate all responses using your constraints.

State-Aware Constraint Programming

Access global application state directly in your MiniZinc constraints for sophisticated validation rules

Global State Integration

Your JavaScript state machine automatically exposes state variables to MiniZinc constraints, enabling context-aware validation that understands your application's current state.

🔄 State Variables Available in MiniZinc:

  • global_state.cart.items - Current cart contents
  • global_state.cart.total - Running total value
  • global_state.user.preferences - User settings
  • global_state.inventory - Available stock levels

💡 Pro Tip: State-aware constraints catch bugs that traditional stateless testing misses!

output_constraints.mzn
% Validate cart total consistency constraint response.cart.total = sum(item in global_state.cart.items)( item.price * item.quantity ); % Ensure we don't exceed inventory constraint forall(item in response.cart.items)( item.quantity <= global_state.inventory[item.id].available ); % Respect user preferences constraint if global_state.user.preferences.max_items > 0 then length(response.cart.items) <= global_state.user.preferences.max_items endif; % Business rule: VIP users get priority constraint if global_state.user.tier = "VIP" then response.processing_priority = "high" else response.processing_priority = "normal" endif;

State-Driven Test Scenarios

🛒

Cart Consistency

Validates that cart totals, item counts, and pricing remain consistent across operations

📦

Inventory Bounds

Ensures operations respect real-time inventory limits and stock availability

👤

User Context

Applies user-specific business rules, preferences, and access controls

Smart Execution Control

Endpoint guards prevent invalid operations by checking global state before execution

State-Dependent Endpoint Guards

Each endpoint can have a guard function that depends on the global state. Bumblebee automatically evaluates these guards to determine whether the current system state allows for the endpoint to be called, ensuring realistic test execution flows.

🛡️ Guard Benefits:

  • Prevents invalid API calls in test sequences
  • Ensures realistic user journey simulation
  • Automatically skips impossible operations
  • Maintains logical execution flow integrity

💡 Smart Testing: Guards enable Bumblebee to automatically discover realistic execution paths without manual configuration!

endpoint-guards.js
// Guard for checkout endpoint function canCheckout(globalState) { return globalState.cart.items.length > 0 && globalState.user.isLoggedIn && globalState.cart.total > 0; } // Guard for remove item endpoint function canRemoveItem(globalState, itemId) { return globalState.cart.items.some( item => item.id === itemId ); } // Guard for VIP operations function canAccessVipFeatures(globalState) { return globalState.user.tier === "VIP" && globalState.user.subscription.active; } // Guard for payment processing function canProcessPayment(globalState) { return globalState.cart.total >= 0.01 && globalState.user.paymentMethod !== null && !globalState.user.account.suspended; }

Automatic Path Discovery

Traditional Approach

  • Manually define each test path
  • Hard-code valid operation sequences
  • Miss edge cases and state combinations
  • Brittle tests that break on state changes

Bumblebee's Smart Guards

  • Automatically discover valid paths
  • Skip impossible operations dynamically
  • Test all reachable state combinations
  • Adapt to state changes automatically
⚡ Result: Comprehensive testing with zero manual path specification

Beyond Happy Path Testing

Bumblebee actively breaks your constraints to ensure robust error handling and security

⚠️ Traditional Testing Problem

Most testing frameworks only validate that valid inputs produce expected outputs. They rarely test what happens when constraints are violated, invalid data is submitted, or systems are pushed beyond their limits.

⚡ Bumblebee's Approach

Bumblebee intentionally violates your constraints to verify that your API gracefully handles invalid inputs, enforces business rules, and fails securely when it should.

Constraint Violation Testing

Input Violations

Submit negative quantities, invalid IDs, oversized strings, malformed data

💥 Business Rule Violations

Exceed inventory limits, violate user permissions, break pricing rules

🔒 State Violations

Access unauthorized resources, manipulate protected state, race conditions

Example: Cart Constraint Violations

Watch Bumblebee systematically test constraint violations:

✅ Valid Constraint
quantity > 0 && quantity <= 100
🔥 Violations Tested
  • quantity = -5 (negative values)
  • quantity = 999 (exceeds maximum)
  • quantity = 0 (boundary violation)
  • quantity = "invalid" (type violation)

What Gets Verified

Proper Error Responses

API returns appropriate HTTP status codes and error messages

State Integrity

Invalid operations don't corrupt application state

Security Boundaries

System fails securely and doesn't expose sensitive information

🛡️ Result: Bulletproof APIs that handle any input gracefully

See It In Action

Example of state management and constraint-based validation in action

state-machine.js - JavaScript State Management
class ShoppingCartState { constructor() { this.cart = { items: [], total: 0 }; } // Update state based on API responses onOutput(operationName, response) { switch (operationName) { case 'add_item_to_cart': // Intelligent state updates preserve business logic this.addItemToCart(response.item); break; case 'remove_item_from_cart': this.removeItemFromCart(response.itemId); break; } } addItemToCart(item) { const existingItem = this.cart.items.find( i => i.id === item.id ); if (existingItem) { existingItem.quantity += item.quantity; } else { this.cart.items.push(item); } this.updateTotal(); } getState() { return this.cart; } }

90%

Reduction in Manual Test Creation

5x

Faster Bug Discovery

100%

State Consistency Validation

Edge Cases Generated