Testing Strategy for Billing System
Overview
Testing payment systems requires careful consideration of security and isolation. Here's our recommended approach:
Testing Levels
1. Unit Tests (No External Dependencies)
- Mock all external services (Stripe, Supabase)
- Test business logic in isolation
- Fast, reliable, no security concerns
- Run on every commit
2. Integration Tests (Local Services)
- Use Supabase local development
- Mock Stripe API responses
- Test database interactions
- No real API keys needed
3. E2E Tests (CI/CD Only)
- Run only in GitHub Actions
- Use GitHub Secrets for credentials
- Create isolated test data
- Clean up after each run
Security Best Practices
❌ Never Do This
- Commit API keys (even test keys) to git
- Use production credentials in tests
- Share test credentials publicly
- Run E2E tests with real APIs locally
✅ Always Do This
- Use environment variables from CI/CD secrets
- Mock external services when possible
- Isolate test data with unique identifiers
- Clean up test data after runs
Local Development Testing
For local development, use one of these approaches:
Option 1: Mock Everything (Recommended)
# Run unit tests with mocks
pnpm test:unit
Option 2: Local Services Only
# Start local Supabase
supabase start
# Run integration tests (Stripe mocked)
pnpm test:integration
Option 3: Skip E2E Locally
# Run all tests except E2E
pnpm test --exclude="**/*.e2e.test.ts"
CI/CD Testing
GitHub Actions will run all tests including E2E:
- name: Run E2E Tests
env:
STRIPE_SECRET_KEY: ${{ secrets.STRIPE_TEST_SECRET_KEY }}
SUPABASE_URL: ${{ secrets.SUPABASE_TEST_URL }}
SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_TEST_SERVICE_KEY }}
run: pnpm test:e2e
Test Data Management
Isolation
- Prefix all test data with timestamps
- Use unique identifiers for each test run
- Never reuse test data between runs
Cleanup
- Always clean up test data after tests
- Use try/finally blocks to ensure cleanup
- Have a backup cleanup job in CI/CD
Stripe Testing
Test Mode
- Always use Stripe test mode keys
- Never use live mode keys in tests
- Use Stripe's test card numbers
Test Cards
- Success: 4242 4242 4242 4242
- Decline: 4000 0000 0000 0002
- 3D Secure: 4000 0025 0000 3155
Example Safe Test
describe('Billing Service', () => {
// Skip in local environment
describe.skipIf(!process.env.CI)('E2E Tests', () => {
it('should create subscription', async () => {
// This only runs in CI with secure credentials
})
})
// Always run with mocks
describe('Unit Tests', () => {
it('should calculate subscription price', () => {
// Pure business logic, no external calls
})
})
})
Environment Variables
Required for E2E Tests (CI/CD only)
STRIPE_SECRET_KEY- Stripe test mode secret keySUPABASE_URL- Test Supabase project URLSUPABASE_SERVICE_ROLE_KEY- Test Supabase service key
Never Commit
- Any file containing real API keys
.env.testwith actual credentials- Test results with sensitive data
Monitoring
- Review test logs for accidental key exposure
- Rotate test keys regularly
- Monitor Stripe test mode for unusual activity
- Set up alerts for test data threshold