mirror of
https://github.com/velocitatem/PHANTOM.git
synced 2026-05-31 16:43:36 +00:00
Implement comprehensive E2E tests to validate the surge pricing pipeline: - Test SimpleSurgePricer with configurable thresholds (high=3, surge=1.5x) - Verify discount pricing when demand is below low_threshold - Test multi-product differential pricing based on demand signals - Validate price propagation from pipeline through Redis to API Test infrastructure: - Playwright configuration with custom fixtures - Python pipeline worker for direct test execution (bypasses Airflow) - API client for event ingestion and price verification - Event generator for creating realistic interaction sequences - docker-compose.e2e.yml with minimal services for testing
9.1 KiB
9.1 KiB
PHANTOM Dynamic Pricing E2E Test Suite
End-to-end tests validating the dynamic pricing pipeline, including SimpleSurgePricer and SessionAwarePricer functionality.
System Under Test (SUT)
┌─────────────────────────────────────────────────────────────────────────┐
│ PHANTOM Pricing Pipeline │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │
│ │ Test Runner │───▶│ Backend API │───▶│ Kafka (user-interactions)│ │
│ │ (Playwright)│ │ POST /ingest │ │ │ │
│ └──────────────┘ └──────────────┘ └────────────┬─────────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────────────────────┐ │
│ │ │ Pipeline Worker │ │
│ │ │ - Fetch interactions │ │
│ │ │ - Compute demand │ │
│ │ │ - Apply surge pricing │ │
│ │ └────────────┬─────────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────────────────────┐ │
│ │ │ Redis (Model Registry) │ │
│ │ │ - prices:latest │ │
│ │ └────────────┬─────────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────────┐ ┌──────────────────────────┐ │
│ └────▶│ Pricing API │◀──────────│ Pricing Provider │ │
│ │ GET /price │ │ (serves from Redis) │ │
│ └──────────────┘ └──────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
Test Scenarios
| Scenario | Description | Expected Outcome |
|---|---|---|
| Baseline | No interactions for product | Price = base_price (markup = 1.0) |
| Surge | 5+ interactions (above threshold) | Price = base_price × 1.5 |
| Discount | 1 interaction (at threshold) | Price = base_price × 0.9 |
| Multi-Product | Different demand per product | Each product priced by its demand |
| Propagation | Pipeline → Redis → API | Prices visible via API |
| Event Types | Mix of view, click, cart | All events counted in demand |
| Multi-Session | Events from different sessions | Demand aggregated correctly |
Test Configuration
The tests use aggressive thresholds for fast feedback:
pricing: {
highThreshold: 3, // Surge after 3 interactions
lowThreshold: 1, // Discount at ≤1 interaction
surgeMultiplier: 1.5, // 50% price increase
discountMultiplier: 0.9, // 10% discount
windowSize: 10_000, // 10 second window
}
Quick Start
1. Start E2E Services
# Start minimal services for E2E testing
docker compose -f docker-compose.e2e.yml up -d
# Wait for services to be healthy
docker compose -f docker-compose.e2e.yml ps
# Optional: Start with Kafka UI for debugging
docker compose -f docker-compose.e2e.yml --profile debug up -d
2. Install Test Dependencies
cd e2e
npm install
npx playwright install
3. Run Tests
# Run all E2E tests
npm test
# Run with UI (interactive mode)
npm run test:ui
# Run specific test file
npm run test:pricing
# Run in debug mode
npm run test:debug
# View test report
npm run test:report
4. Cleanup
docker compose -f docker-compose.e2e.yml down -v
Environment Variables
| Variable | Default | Description |
|---|---|---|
BACKEND_URL |
http://localhost:5000 |
Backend API URL |
PROVIDER_URL |
http://localhost:5001 |
Pricing Provider URL |
REDIS_HOST |
localhost |
Redis host |
REDIS_PORT |
6378 |
Redis port |
KAFKA_HOST |
localhost |
Kafka host |
KAFKA_PORT |
9092 |
Kafka port |
Test Architecture
e2e/
├── playwright.config.ts # Playwright configuration
├── global-setup.ts # Service health checks
├── global-teardown.ts # Cleanup
├── package.json # Dependencies and scripts
├── tsconfig.json # TypeScript configuration
├── lib/
│ ├── api-client.ts # API interaction utilities
│ ├── event-generator.ts # Test event factory
│ ├── pipeline-runner.ts # TypeScript pipeline wrapper
│ ├── pipeline-worker.py # Python pipeline executor
│ ├── fixtures.ts # Playwright test fixtures
│ └── index.ts # Re-exports
└── tests/
└── dynamic-pricing.spec.ts # Main test file
Pipeline Worker
The tests use a dedicated Python pipeline worker (lib/pipeline-worker.py) instead of Airflow for faster, more reliable test execution.
# Run pipeline manually
python3 lib/pipeline-worker.py \
--store-mode hotel \
--high-threshold 3 \
--surge-multiplier 1.5 \
--json-output
# Dry run (no Redis publish)
python3 lib/pipeline-worker.py --dry-run
Debugging
View Kafka Events
# Via API
curl "http://localhost:5000/api/kafka/dump?topic=user-interactions&last_n=10"
# Via Redpanda Console (if started with --profile debug)
open http://localhost:8080
Check Redis State
docker exec -it PHANTOM-e2e-redis redis-cli
> GET prices:latest
> KEYS *
View Pipeline Logs
The pipeline worker logs detailed information:
[INFO] Starting E2E pricing pipeline: mode=hotel, high_threshold=3, surge_multiplier=1.5
[INFO] Fetched 15 interaction records
[INFO] Computed demand for 3 products
[INFO] Applied surge pricing:
e2e-test...: base=$100.00 -> optimal=$150.00 (demand=5, markup=1.50x)
[INFO] Published 3 prices to Redis
Writing New Tests
import { test, expect } from '../lib/fixtures';
import { generateTestProductId } from '../lib/event-generator';
test('my new pricing test', async ({ api, events, triggerPriceUpdate }) => {
// 1. Create unique product ID
const productId = generateTestProductId('my-test');
// 2. Log base price
await api.logPrice({
productId,
price: 100.0,
sessionId: events.session,
storeMode: 'hotel',
});
// 3. Generate events
const surgeEvents = events.generateSurgeSequence(productId, 5);
await api.ingestEvents(surgeEvents);
// 4. Trigger pipeline
const result = await triggerPriceUpdate();
// 5. Verify results
expect(result.success).toBe(true);
const pricedProduct = result.prices?.find(p => p.productId === productId);
expect(pricedProduct?.optimal_price).toBeGreaterThan(100);
});
Troubleshooting
"Backend not available"
Ensure services are running:
docker compose -f docker-compose.e2e.yml ps
docker compose -f docker-compose.e2e.yml logs backend
"No interactions found"
Check Kafka topic has events:
curl "http://localhost:5000/api/kafka/dump?topic=user-interactions"
"Pipeline timeout"
Increase timeout in playwright.config.ts:
timeout: 180_000, // 3 minutes
"Price not updated"
Check Redis has latest prices:
docker exec -it PHANTOM-e2e-redis redis-cli GET prices:latest