botbook/src/17-testing/e2e-testing.md

447 lines
10 KiB
Markdown
Raw Normal View History

# End-to-End Testing
End-to-end (E2E) testing validates complete user workflows from platform loading through authentication, interaction, and logout.
## Overview
E2E tests simulate real user interactions:
1. **Platform Loading** - UI and API infrastructure operational
2. **BotServer Initialization** - Backend service running and ready
3. **User Authentication** - Login workflow functional
4. **Chat Interaction** - Message sending and receiving
5. **Logout** - Session management and access control
## Complete Platform Flow Test
The main E2E test validates the entire user journey:
```rust
#[tokio::test]
async fn test_complete_platform_flow_login_chat_logout() {
// Setup
let ctx = E2ETestContext::setup_with_browser().await?;
let browser = ctx.browser.as_ref().unwrap();
// Phase 1: Platform Loading
verify_platform_loading(&ctx).await?;
// Phase 2: BotServer Running
verify_botserver_running(&ctx).await?;
// Phase 3: User Login
test_user_login(browser, &ctx).await?;
// Phase 4: Chat Interaction
test_chat_interaction(browser, &ctx).await?;
// Phase 5: Logout
test_user_logout(browser, &ctx).await?;
ctx.close().await;
}
```
## Test Phases
### Phase 1: Platform Loading
Verifies UI and API infrastructure:
```rust
verify_platform_loading(&ctx).await?
```
Checks:
- Health endpoint responds with 2xx status
- API endpoints are accessible
- Database migrations completed
- Services are initialized
### Phase 2: BotServer Initialization
Verifies the backend service is operational:
```rust
verify_botserver_running(&ctx).await?
```
Checks:
- Process is alive and responding
- Configuration properly loaded
- Dependencies connected (DB, cache, storage)
- Health checks pass
### Phase 3: User Authentication
Tests the login workflow:
```rust
test_user_login(browser, &ctx).await?
```
Tests:
- Navigate to login page
- Form elements present and functional
- Accept valid test credentials (test@example.com / TestPassword123!)
- Create session and authentication token
- Redirect to dashboard/chat interface
### Phase 4: Chat Interaction
Tests messaging functionality:
```rust
test_chat_interaction(browser, &ctx).await?
```
Tests:
- Chat interface loads correctly
- User can type and send messages
- Bot responds with valid output
- Message history persists
- Multiple exchanges work correctly
### Phase 5: Logout & Session Management
Tests secure session handling:
```rust
test_user_logout(browser, &ctx).await?
```
Tests:
- Logout button/action works
- Session is invalidated
- User redirected to login page
- Protected routes block unauthenticated access
- Cannot access chat after logout
## Running E2E Tests
### HTTP-Only Tests (No Browser Required)
These tests verify API and infrastructure without browser automation:
```bash
cd gb/bottest
# Platform loading verification
cargo test --test e2e test_platform_loading_http_only -- --nocapture
# BotServer startup verification
cargo test --test e2e test_botserver_startup -- --nocapture
```
Execution time: ~2-5 seconds
### Complete Flow Tests (Requires WebDriver)
Full browser-based tests with user interactions:
```bash
# Start WebDriver first
chromedriver --port=4444 &
# Run complete platform flow
cargo test --test e2e test_complete_platform_flow_login_chat_logout -- --nocapture
# Run simplified flow
cargo test --test e2e test_login_and_chat_flow -- --nocapture
```
Execution time: ~30-60 seconds
## WebDriver Setup
### Option 1: Local Installation
```bash
# Download chromedriver from https://chromedriver.chromium.org/
# Place in PATH, then start:
chromedriver --port=4444
```
### Option 2: Docker
```bash
docker run -d -p 4444:4444 selenium/standalone-chrome
```
### Option 3: Docker Compose
```bash
docker-compose up -d webdriver
```
## Environment Variables
Control test behavior:
| Variable | Default | Purpose |
|----------|---------|---------|
| `HEADED` | unset | Show browser window instead of headless |
| `WEBDRIVER_URL` | `http://localhost:4444` | WebDriver server endpoint |
| `SKIP_E2E_TESTS` | unset | Skip E2E tests if set |
| `RUST_LOG` | info | Logging level: debug, info, warn, error |
| `KEEP_TEMP_STACK_ON_ERROR` | unset | Preserve temp directory on failure |
### Examples
```bash
# Show browser UI for debugging
HEADED=1 cargo test --test e2e -- --nocapture
# Use custom WebDriver
WEBDRIVER_URL=http://localhost:4445 cargo test --test e2e -- --nocapture
# Verbose logging
RUST_LOG=debug cargo test --test e2e -- --nocapture
# Run single-threaded with output
cargo test --test e2e -- --nocapture --test-threads=1
```
## Test Helpers
Reusable helper functions for custom tests:
```rust
// Verify platform is operational
verify_platform_loading(&ctx) -> Result<()>
// Verify BotServer is running
verify_botserver_running(&ctx) -> Result<()>
// Perform login with credentials
test_user_login(browser, &ctx) -> Result<()>
// Send message and wait for response
test_chat_interaction(browser, &ctx) -> Result<()>
// Logout and verify session invalidation
test_user_logout(browser, &ctx) -> Result<()>
```
## Test Context
Setup a test context for E2E testing:
```rust
use bottest::prelude::*;
use bottest::web::{Browser, BrowserConfig};
// HTTP-only context
let ctx = E2ETestContext::setup().await?;
// With browser automation
let ctx = E2ETestContext::setup_with_browser().await?;
let browser = ctx.browser.as_ref().unwrap();
// Access base URL
let url = ctx.base_url();
// Access running server
let is_running = ctx.server.is_running();
// Cleanup
ctx.close().await;
```
## Common Issues
### WebDriver Not Available
**Problem**: Test fails with "WebDriver not available"
**Solution**:
```bash
# Start WebDriver
chromedriver --port=4444
# or
docker run -d -p 4444:4444 selenium/standalone-chrome
```
### Port Already in Use
**Problem**: Services fail to start due to port conflicts
**Solution**:
```bash
# Kill existing services
pkill -f chromedriver
pkill -f botserver
pkill -f postgres
pkill -f redis-server
```
### Test Hangs or Timeout
**Problem**: Test appears to hang or timeout
**Solution**:
```bash
# Run with timeout and verbose output
timeout 120s RUST_LOG=debug cargo test --test e2e test_name -- --nocapture --test-threads=1
```
### Browser Connection Issues
**Problem**: Browser fails to connect to WebDriver
**Solution**:
```bash
# Use different WebDriver port
WEBDRIVER_URL=http://localhost:4445 cargo test --test e2e -- --nocapture
```
## Debugging
### View Test Output
```bash
# Show all output
cargo test --test e2e test_name -- --nocapture
# With timestamps
RUST_LOG=debug cargo test --test e2e test_name -- --nocapture
# Save to file
cargo test --test e2e test_name -- --nocapture 2>&1 | tee test.log
```
### Watch Browser in Action
```bash
# Run with visible browser
HEADED=1 cargo test --test e2e test_name -- --nocapture --test-threads=1
```
### Check Server Logs
```bash
# Monitor logs while tests run
tail -f /tmp/bottest-*/botserver.log
# In another terminal:
cargo test --test e2e test_name -- --nocapture
```
## Performance
Typical execution times:
| Test | Time | Resources |
|------|------|-----------|
| Platform loading (HTTP-only) | ~2s | Minimal |
| BotServer startup (HTTP-only) | ~5s | Minimal |
| Login and chat flow | ~20s | Browser + Memory |
| Complete flow with all phases | ~45s | Browser + Memory |
| Full E2E test suite | ~2-3 min | High |
Use release mode for faster execution:
```bash
cargo test --test e2e --release -- --nocapture
```
## CI/CD Integration
### GitHub Actions Example
```yaml
name: E2E Tests
on: [push, pull_request]
jobs:
e2e:
runs-on: ubuntu-latest
services:
chromedriver:
image: selenium/standalone-chrome
options: --shm-size=2gb
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
- run: cd gb/bottest && cargo test --test e2e -- --nocapture
```
## Temporary Stack Architecture (Future)
When BotServer implements `--temp-stack`, E2E tests will run in isolated environments:
```bash
botserver --temp-stack
# Creates: /tmp/botserver-test-{timestamp}-{random}/
# With isolated: PostgreSQL, Redis, MinIO, Mock LLM
# Auto-cleanup after test completion
```
Benefits:
- ✓ Isolation - Each test in separate environment
- ✓ Reproducibility - Consistent setup every time
- ✓ Automation - No manual configuration
- ✓ Safety - Won't interfere with development
- ✓ Cleanup - Automatic resource management
- ✓ Parallel - Multiple tests simultaneously
- ✓ CI/CD Ready - Perfect for automated pipelines
## Writing Custom E2E Tests
Create new test files in `gb/bottest/tests/e2e/`:
```rust
#[tokio::test]
async fn test_my_feature() {
// Setup context
let ctx = E2ETestContext::setup_with_browser().await?;
let browser = ctx.browser.as_ref().unwrap();
// Navigate to feature
browser.navigate(&format!("{}/my-feature", ctx.base_url())).await?;
// Interact with UI
browser.click("button.action").await?;
browser.wait_for_element(".result", Duration::from_secs(10)).await?;
// Verify results
let text = browser.get_text(".result").await?;
assert_eq!(text, "Expected result");
// Cleanup
ctx.close().await;
}
```
Register in `tests/e2e/mod.rs`:
```rust
mod my_feature;
```
## Best Practices
1. **Keep tests focused** - Test one user workflow per test
2. **Use meaningful names** - `test_complete_platform_flow` not `test_1`
3. **Explicit waits** - Use `wait_for_element` instead of `sleep`
4. **Test realistic flows** - Use actual test credentials
5. **Verify results explicitly** - Check status codes, UI elements, and state
6. **Clean up properly** - Always call `ctx.close().await`
7. **Handle errors gracefully** - Use `?` operator for error propagation
8. **Make tests independent** - Don't rely on test execution order
## Test Success Criteria
✓ Platform fully loads without errors
✓ BotServer starts and becomes ready
✓ User can login with credentials
✓ Chat messages are sent and responses received
✓ User can logout and session is invalidated
✓ Protected routes block unauthenticated access
✓ Tests run consistently multiple times
✓ Tests complete within acceptable time (~60 seconds)
## See Also
- [Testing Overview](./README.md) - Testing strategy and structure
- [Performance Testing](./performance.md) - Benchmarks and load tests
- [Test Architecture](./architecture.md) - Design patterns and best practices
- [Integration Testing](./integration.md) - Multi-component testing