Testing Architecture 🟑 BETA

Overview

The General Bots testing framework is designed with a multi-layered, isolated approach to ensure comprehensive coverage from individual components to complete user workflows.

Architecture Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Test Execution Layer                     β”‚
β”‚  (GitHub Actions, CI/CD, Local Development)                β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚            β”‚            β”‚
        β–Ό            β–Ό            β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚  Unit   β”‚  β”‚ Integr. β”‚  β”‚   E2E    β”‚
   β”‚ Tests   β”‚  β”‚ Tests   β”‚  β”‚  Tests   β”‚
   β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
        β”‚            β”‚            β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚   Test Harness Layer    β”‚
        β”‚ (Context, Utils, Mocks) β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚            β”‚            β”‚
        β–Ό            β–Ό            β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚botserverβ”‚  β”‚  Browserβ”‚  β”‚ Services β”‚
   β”‚(Testing)β”‚  β”‚ (WebDrv)β”‚  β”‚(Mock/Iso)β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚            β”‚            β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚  Temporary Stack Layer  β”‚
        β”‚ (Isolated Environments) β”‚
        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚
        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
        β”‚                         β”‚
        β–Ό                         β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ PostgreSQL  β”‚          β”‚ Redis, MinIO β”‚
   β”‚ (Isolated)  β”‚          β”‚  (Isolated)  β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Test Layers

1. Unit Tests

Purpose: Test individual components in isolation

Scope:

  • Single functions or methods
  • Mocked external dependencies
  • No database or external services

Example:

#![allow(unused)]
fn main() {
#[test]
fn test_message_formatting() {
    let msg = format_message("Hello");
    assert_eq!(msg, "Hello!");
}
}

Location: bottest/tests/unit/

2. Integration Tests

Purpose: Test multiple components working together

Scope:

  • Multi-component interactions
  • Real database connections
  • Service integration
  • Error handling across components

Example:

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_message_storage_and_retrieval() {
    let db = setup_test_db().await;
    let msg = Message::new("Hello");
    db.save(&msg).await.unwrap();
    let retrieved = db.get(msg.id).await.unwrap();
    assert_eq!(retrieved.text, "Hello");
}
}

Location: bottest/tests/integration/

3. End-to-End Tests

Purpose: Test complete user workflows

Scope:

  • Complete user journeys
  • Browser interactions
  • Multi-phase workflows
  • Real-world scenarios

Phases:

  1. Platform Loading
  2. botserver Initialization
  3. User Authentication
  4. Chat Interaction
  5. Logout & Session Management

Example:

#![allow(unused)]
fn main() {
#[tokio::test]
async fn test_complete_platform_flow_login_chat_logout() {
    let ctx = E2ETestContext::setup_with_browser().await?;
    
    verify_platform_loading(&ctx).await?;
    verify_botserver_running(&ctx).await?;
    test_user_login(browser, &ctx).await?;
    test_chat_interaction(browser, &ctx).await?;
    test_user_logout(browser, &ctx).await?;
    
    ctx.close().await;
}
}

Location: bottest/tests/e2e/

Test Harness

The test harness provides utilities for test setup and context management:

TestHarness
β”œβ”€β”€ Setup utilities
β”‚   β”œβ”€β”€ Create test database
β”‚   β”œβ”€β”€ Start mock services
β”‚   β”œβ”€β”€ Initialize configurations
β”‚   └── Provision test data
β”œβ”€β”€ Context management
β”‚   β”œβ”€β”€ Resource tracking
β”‚   β”œβ”€β”€ Cleanup coordination
β”‚   └── Error handling
└── Helper functions
    β”œβ”€β”€ HTTP requests
    β”œβ”€β”€ Browser interactions
    └── Service mocking

E2ETestContext

Provides complete environment for E2E testing:

#![allow(unused)]
fn main() {
pub struct E2ETestContext {
    pub ctx: TestContext,
    pub server: botserverInstance,
    pub browser: Option<Browser>,
}

impl E2ETestContext {
    pub async fn setup() -> Result<Self>
    pub async fn setup_with_browser() -> Result<Self>
    pub fn base_url(&self) -> &str
    pub fn has_browser(&self) -> bool
    pub async fn close(self)
}
}

Temporary Stack Architecture

Isolated test environments for complete system integration:

/tmp/botserver-test-{timestamp}-{id}/
β”œβ”€β”€ postgres/
β”‚   β”œβ”€β”€ data/               ← PostgreSQL data files
β”‚   β”œβ”€β”€ postgresql.log      ← Database logs
β”‚   └── postgresql.conf     ← Configuration
β”œβ”€β”€ redis/
β”‚   β”œβ”€β”€ data/               ← Redis persistence
β”‚   └── redis.log
β”œβ”€β”€ minio/
β”‚   β”œβ”€β”€ data/               ← S3-compatible storage
β”‚   └── minio.log
β”œβ”€β”€ botserver/
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”œβ”€β”€ config.toml     ← Application config
β”‚   β”‚   └── .env            ← Environment variables
β”‚   β”œβ”€β”€ logs/
β”‚   β”‚   β”œβ”€β”€ botserver.log   ← Main application logs
β”‚   β”‚   β”œβ”€β”€ api.log         ← API logs
β”‚   β”‚   └── debug.log       ← Debug logs
β”‚   β”œβ”€β”€ cache/              ← Local cache
β”‚   └── state.json          ← Stack metadata
└── env.stack               ← Connection strings for tests

Isolation Strategy

Service Isolation

Each test gets dedicated service instances:

  • Database: Separate PostgreSQL cluster on port 5433
  • Cache: Separate Redis instance on port 6380
  • Storage: Separate MinIO instance on port 9001
  • API: Separate botserver on port 8000

Network Isolation

  • All services on localhost (127.0.0.1)
  • Non-standard ports to avoid conflicts
  • Docker containers for complete OS-level isolation

Data Isolation

  • Separate database schemas per test
  • Temporary file systems for storage
  • No shared configuration between tests
  • Automatic cleanup on completion

Test Execution Flow

1. Test Initialization
   β”œβ”€ Parse environment variables
   β”œβ”€ Check prerequisites (WebDriver, services)
   └─ Create test context

2. Stack Setup
   β”œβ”€ Create temporary directory
   β”œβ”€ Initialize databases
   β”œβ”€ Start services
   └─ Wait for readiness

3. Test Execution
   β”œβ”€ Setup phase
   β”œβ”€ Action phase
   β”œβ”€ Verification phase
   └─ Assertion phase

4. Cleanup
   β”œβ”€ Close browser connections
   β”œβ”€ Shutdown services gracefully
   β”œβ”€ Remove temporary directories
   └─ Report results

Browser Automation

Uses WebDriver (Selenium) protocol for browser testing:

Test Code
    ↓
Reqwest HTTP Client
    ↓
WebDriver Protocol (JSON-RPC)
    ↓
chromedriver / Selenium Server
    ↓
Chrome/Chromium Browser
    ↓
Test Verification

WebDriver Commands

  • Navigate to URL
  • Find elements by selector
  • Click buttons and links
  • Fill form inputs
  • Wait for elements
  • Execute JavaScript
  • Take screenshots
  • Get element text

Error Handling

Comprehensive error handling at all levels:

Test Execution
    β”‚
    β”œβ”€ Setup Error
    β”‚  └─ Fail fast, preserve environment
    β”‚
    β”œβ”€ Execution Error
    β”‚  β”œβ”€ Log detailed context
    β”‚  β”œβ”€ Capture screenshots
    β”‚  └─ Optionally preserve stack
    β”‚
    └─ Cleanup Error
       └─ Log warning, continue cleanup

Performance Considerations

Test Execution Times

  • Unit Tests: ~0.1-1 second
  • Integration Tests: ~1-10 seconds
  • E2E Tests: ~30-60 seconds
  • Full Suite: ~2-3 minutes

Optimization Strategies

  1. Parallel Execution: Run independent tests simultaneously
  2. Caching: Reuse expensive resources
  3. Lazy Loading: Initialize only needed components
  4. Release Mode: Use --release for faster compilation
  5. Selective Testing: Run only relevant tests during development

CI/CD Integration

GitHub Actions Workflow

Trigger (push/PR)
    ↓
Setup Environment
    β”œβ”€ Install Rust
    β”œβ”€ Start WebDriver
    └─ Setup test infrastructure
    ↓
Run Tests
    β”œβ”€ Unit tests
    β”œβ”€ Integration tests
    └─ E2E tests
    ↓
Collect Artifacts
    β”œβ”€ Test results
    β”œβ”€ Coverage reports
    β”œβ”€ Screenshots/logs
    └─ Performance metrics
    ↓
Report Results
    └─ Pass/fail status

Best Practices

1. Test Organization

  • Keep tests focused and single-purpose
  • Use descriptive names
  • Group related tests
  • Organize by layer (unit/integration/e2e)

2. Test Design

  • Make tests independent
  • Use realistic data
  • Test both happy and error paths
  • Avoid test interdependencies

3. Test Maintenance

  • Keep tests up to date with code
  • Remove obsolete tests
  • Refactor test helpers
  • Monitor test execution time

4. Test Documentation

  • Document complex test logic
  • Explain test prerequisites
  • Document setup/teardown
  • Include troubleshooting tips

Debugging

Debug Helpers

  • RUST_LOG=debug - Verbose logging
  • HEADED=1 - Show browser UI
  • --nocapture - Print test output
  • --test-threads=1 - Run sequentially

Debug Techniques

  • Check server logs
  • Review screenshots
  • Inspect HTTP requests
  • Step through code
  • Use REPL for experimentation

Future Enhancements

  1. Load Testing - Concurrent user scenarios
  2. Visual Regression - Screenshot comparison
  3. Accessibility Testing - WCAG compliance
  4. Security Testing - Vulnerability scanning
  5. Performance Profiling - Memory and CPU analysis
  6. Multi-region - Test across deployments
  7. Snapshot Testing - Compare outputs over time

References