Skip to main content

End-to-End Testing and Validation

Introduction​

Before declaring a deployment "in production," it is essential to validate that all components work correctly together. This section presents a comprehensive testing methodology.

Testing Methodology​

┌─────────────────────────────────────────────────────────────┐
│ INFRASTRUCTURE TESTING PYRAMID │
├─────────────────────────────────────────────────────────────┤
│ │
│ ▲ │
│ ╱ ╲ │
│ ╱ ╲ │
│ ╱ E2E ╲ End-to-End Tests │
│ ╱───────╲ (real user) │
│ ╱ ╲ │
│ ╱Integration╲ Integration Tests │
│ ╱─────────────╲ (components together) │
│ ╱ ╲ │
│ ╱ Components ╲ Unit Tests │
│ ╱───────────────────╲ (each service) │
│ ╱ ╲ │
│ ╱ Infrastructure ╲ Config Validation │
│ ╱─────────────────────────╲(CloudFormation, etc) │
│ │
│ Start from the bottom, gradually move up │
│ │
└─────────────────────────────────────────────────────────────┘

Infrastructure Validation Tests​

1. VPC and Network Validation​

# Test 1: VPC exists and is available
aws ec2 describe-vpcs --vpc-ids vpc-xxx \
--query 'Vpcs[0].State'
# Expected: "available"

# Test 2: All subnets created
aws ec2 describe-subnets --filters "Name=vpc-id,Values=vpc-xxx" \
--query 'Subnets[*].[SubnetId,CidrBlock,AvailabilityZone]'
# Expected: 6 subnets listed

# Test 3: Internet Gateway attached
aws ec2 describe-internet-gateways \
--filters "Name=attachment.vpc-id,Values=vpc-xxx" \
--query 'InternetGateways[0].Attachments[0].State'
# Expected: "available"

# Test 4: Correct routes
aws ec2 describe-route-tables \
--filters "Name=vpc-id,Values=vpc-xxx" \
--query 'RouteTables[*].Routes'
# Expected: route 0.0.0.0/0 to igw for public subnets

2. Security Groups Validation​

# Test 5: SG ALB allows HTTPS
aws ec2 describe-security-groups --group-ids sg-alb \
--query 'SecurityGroups[0].IpPermissions[?ToPort==`443`]'
# Expected: rule with 0.0.0.0/0

# Test 6: SG App allows only from ALB
aws ec2 describe-security-groups --group-ids sg-app \
--query 'SecurityGroups[0].IpPermissions[*].UserIdGroupPairs[*].GroupId'
# Expected: contains sg-alb

# Test 7: SG DB allows only from App
aws ec2 describe-security-groups --group-ids sg-db \
--query 'SecurityGroups[0].IpPermissions[*].UserIdGroupPairs[*].GroupId'
# Expected: contains sg-app

3. EC2 Instances Validation​

# Test 8: Instances running
aws ec2 describe-instance-status \
--instance-ids i-app1 i-app2 \
--query 'InstanceStatuses[*].[InstanceId,InstanceState.Name,SystemStatus.Status,InstanceStatus.Status]'
# Expected: all "running", "ok", "ok"

# Test 9: Instances in correct subnets
aws ec2 describe-instances --instance-ids i-app1 i-app2 \
--query 'Reservations[*].Instances[*].[InstanceId,SubnetId]'
# Expected: private subnets (10.0.11.0/24, 10.0.12.0/24)

Connectivity Tests​

Test Matrix​

┌─────────────────────────────────────────────────────────────┐
│ CONNECTIVITY MATRIX │
├─────────────────────────────────────────────────────────────┤
│ │
│ FROM / TO │ Internet │ ALB │ App │ DB │ S3 │
│ ─────────────┼──────────┼─────┼─────┼─────┼─────────── │
│ Internet │ - │ ✅ │ ❌ │ ❌ │ ✅(public) │
│ ALB │ ✅ │ - │ ✅ │ ❌ │ ❌ │
│ App │ ✅(NAT) │ ❌ │ ✅ │ ✅ │ ✅(endpoint) │
│ DB │ ❌ │ ❌ │ ❌ │ - │ ❌ │
│ │
│ ✅ = Must work │
│ ❌ = Must be blocked │
│ │
└─────────────────────────────────────────────────────────────┘

Connectivity Test Scripts​

#!/bin/bash
# test-connectivity.sh

echo "=== BlogPro Connectivity Tests ==="

# Test Internet → ALB (HTTPS)
echo -n "Test 1: Internet → ALB (HTTPS)... "
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" https://blog.example.com)
if [ "$HTTP_CODE" = "200" ]; then
echo "✅ PASS ($HTTP_CODE)"
else
echo "❌ FAIL ($HTTP_CODE)"
fi

# Test Internet → ALB (HTTP redirect)
echo -n "Test 2: HTTP → HTTPS redirect... "
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://blog.example.com)
if [ "$HTTP_CODE" = "301" ] || [ "$HTTP_CODE" = "302" ]; then
echo "✅ PASS (redirect $HTTP_CODE)"
else
echo "❌ FAIL ($HTTP_CODE)"
fi

# Test Health Check endpoint
echo -n "Test 3: Health Check... "
HEALTH=$(curl -s https://blog.example.com/health | jq -r '.status')
if [ "$HEALTH" = "healthy" ]; then
echo "✅ PASS"
else
echo "❌ FAIL ($HEALTH)"
fi

# Test Direct IP access (should fail - no public IP)
echo -n "Test 4: Direct IP access (should timeout)... "
timeout 5 curl -s http://10.0.11.20 > /dev/null 2>&1
if [ $? -eq 124 ]; then
echo "✅ PASS (correctly blocked)"
else
echo "❌ FAIL (should not be accessible)"
fi

echo "=== Tests completed ==="

Load Balancing Tests​

Verify Distribution​

#!/bin/bash
# test-load-balancing.sh

echo "=== Load Balancer Distribution Test ==="

# Make 20 requests and count responses from each server
declare -A SERVER_COUNT

for i in {1..20}; do
SERVER=$(curl -s https://blog.example.com/api/server-id)
((SERVER_COUNT[$SERVER]++))
done

echo "Request distribution:"
for server in "${!SERVER_COUNT[@]}"; do
echo " $server: ${SERVER_COUNT[$server]} requests"
done

# Verify that both servers received requests
if [ ${#SERVER_COUNT[@]} -ge 2 ]; then
echo "✅ Load balancing functional"
else
echo "❌ Load balancing failing"
fi

Failover Test​

┌─────────────────────────────────────────────────────────────┐
│ FAILOVER TEST PROCEDURE │
├─────────────────────────────────────────────────────────────┤
│ │
│ Step 1 : Verify initial state │
│ ──────────────────────────────── │
│ $ aws elbv2 describe-target-health \ │
│ --target-group-arn arn:aws:...:tg-app │
│ → Both targets must be "healthy" │
│ │
│ Step 2 : Simulate server failure │
│ ───────────────────────────────────── │
│ $ aws ec2 stop-instances --instance-ids i-app1 │
│ │
│ Step 3 : Wait for health check (30-60s) │
│ ────────────────────────────────────────── │
│ $ watch -n 5 'curl -s https://blog.example.com/health' │
│ → Site must remain accessible │
│ │
│ Step 4 : Verify traffic goes to App2 │
│ ──────────────────────────────────────────── │
│ $ for i in {1..10}; do curl -s https://blog.example.com/ │
│ api/server-id; done │
│ → All responses come from App2 │
│ │
│ Step 5 : Restore App1 │
│ ──────────────────────────── │
│ $ aws ec2 start-instances --instance-ids i-app1 │
│ → After a few minutes, traffic distributed again │
│ │
└─────────────────────────────────────────────────────────────┘

Performance Tests​

Basic Load Test​

# Use Apache Benchmark (ab)
# 1000 requests, 50 concurrent
ab -n 1000 -c 50 https://blog.example.com/

# Expected results:
# - Requests per second > 100
# - Time per request < 500ms (mean)
# - Failed requests: 0

Metrics to Monitor​

MetricAcceptable ThresholdAction if Exceeded
Latency P50< 200msOptimize code/cache
Latency P95< 500msCheck DB queries
Latency P99< 1000msInvestigate outliers
Error rate< 0.1%Check logs
CPU (EC2)< 70%Add instances
Memory (EC2)< 80%Increase size

Security Tests​

Security Checklist​

┌─────────────────────────────────────────────────────────────┐
│ SECURITY CHECKLIST │
├─────────────────────────────────────────────────────────────┤
│ │
│ NETWORK │
│ ☐ No unnecessary ports open to the Internet │
│ ☐ SSH accessible only via bastion/VPN │
│ ☐ Database not accessible from the Internet │
│ ☐ HTTPS enforced (redirect HTTP→HTTPS) │
│ │
│ SSL CERTIFICATE │
│ ☐ Valid certificate (not expired) │
│ ☐ Complete certificate chain │
│ ☐ TLS 1.2+ only │
│ ☐ No SSL vulnerabilities (test SSL Labs) │
│ │
│ INSTANCES │
│ ☐ No credentials in code/user-data │
│ ☐ IAM roles used (no keys) │
│ ☐ OS up to date │
│ ☐ Local firewall configured │
│ │
│ DATABASE │
│ ☐ Encryption at rest enabled │
│ ☐ Encryption in transit (SSL) │
│ ☐ No default credentials │
│ ☐ Automatic backups enabled │
│ │
└─────────────────────────────────────────────────────────────┘

SSL Test with SSL Labs​

# Use the online SSL Labs test
# https://www.ssllabs.com/ssltest/

# Or with testssl.sh
docker run --rm -ti drwetter/testssl.sh https://blog.example.com

# Expected score: A or A+

Validation Report​

Report Template​

# Validation Report - BlogPro

## Executive Summary
- Date: YYYY-MM-DD
- Version: 1.0
- Status: ✅ VALIDATED / ❌ NOT VALIDATED

## Infrastructure Tests
| Test | Result | Notes |
|------|--------|-------|
| VPC created | ✅ | vpc-xxx |
| Subnets (6) | ✅ | |
| IGW attached | ✅ | |
| Correct routes | ✅ | |

## Security Tests
| Test | Result | Notes |
|------|--------|-------|
| SG ALB | ✅ | HTTPS only |
| SG App | ✅ | ALB only |
| SG DB | ✅ | App only |
| SSL Grade | A | SSL Labs |

## Functional Tests
| Test | Result | Notes |
|------|--------|-------|
| Site accessible | ✅ | 200 OK |
| Health check | ✅ | healthy |
| Load balancing | ✅ | 50/50 |
| Failover | ✅ | < 60s |

## Performance Tests
| Metric | Value | Threshold | Status |
|--------|-------|-----------|--------|
| Latency P50 | 150ms | < 200ms | ✅ |
| Latency P95 | 380ms | < 500ms | ✅ |
| Throughput | 250 rps | > 100 rps | ✅ |

## Identified Issues
1. None

## Recommendations
1. Enable VPC Flow Logs for monitoring
2. Set up CloudWatch alerts

## Approval
- [ ] Tech Lead
- [ ] Security Review
- [ ] Ops Team

Test Automation​

Complete Validation Script​

#!/bin/bash
# validate-deployment.sh

RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color

DOMAIN="blog.example.com"
PASS=0
FAIL=0

function test_result() {
if [ $1 -eq 0 ]; then
echo -e "${GREEN}✅ PASS${NC}: $2"
((PASS++))
else
echo -e "${RED}❌ FAIL${NC}: $2"
((FAIL++))
fi
}

echo "========================================"
echo " BLOGPRO DEPLOYMENT VALIDATION"
echo "========================================"
echo ""

# Test 1: Site accessible
echo "Test 1: HTTPS Accessibility"
curl -sf "https://${DOMAIN}" > /dev/null
test_result $? "Site accessible via HTTPS"

# Test 2: Health check
echo "Test 2: Health Check"
HEALTH=$(curl -sf "https://${DOMAIN}/health" | jq -r '.status' 2>/dev/null)
[ "$HEALTH" = "healthy" ]
test_result $? "Health check endpoint"

# Test 3: HTTP redirect
echo "Test 3: HTTP → HTTPS redirect"
CODE=$(curl -sf -o /dev/null -w "%{http_code}" "http://${DOMAIN}")
[ "$CODE" = "301" ] || [ "$CODE" = "302" ]
test_result $? "HTTP redirect to HTTPS"

# Test 4: SSL Certificate
echo "Test 4: Valid SSL Certificate"
curl -sf --cert-status "https://${DOMAIN}" > /dev/null
test_result $? "Valid SSL Certificate"

# Test 5: Response time
echo "Test 5: Response time < 500ms"
TIME=$(curl -sf -o /dev/null -w "%{time_total}" "https://${DOMAIN}")
[ $(echo "$TIME < 0.5" | bc) -eq 1 ]
test_result $? "Response time (${TIME}s)"

echo ""
echo "========================================"
echo " RESULT: $PASS PASS, $FAIL FAIL"
echo "========================================"

if [ $FAIL -gt 0 ]; then
exit 1
fi

Summary​

PhaseTestsTools
InfrastructureVPC, SG, RoutesAWS CLI
ConnectivityAccess matrixcurl, nc, telnet
FunctionalE2E, Healthcurl, scripts
PerformanceLoad, latencyab, hey, k6
SecuritySSL, accesstestssl, nmap

Return: MODULE 7 Overview