test_docker.sh 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. #!/bin/bash
  2. #
  3. # Docker Test Suite for BamBuddy
  4. # Runs build verification, unit tests, and integration tests in Docker
  5. #
  6. set -e
  7. # Colors for output
  8. RED='\033[0;31m'
  9. GREEN='\033[0;32m'
  10. YELLOW='\033[1;33m'
  11. BLUE='\033[0;34m'
  12. NC='\033[0m' # No Color
  13. # Track results
  14. TESTS_PASSED=0
  15. TESTS_FAILED=0
  16. FAILED_TESTS=""
  17. print_header() {
  18. echo ""
  19. echo -e "${BLUE}========================================${NC}"
  20. echo -e "${BLUE} $1${NC}"
  21. echo -e "${BLUE}========================================${NC}"
  22. }
  23. print_success() {
  24. echo -e "${GREEN}✓ $1${NC}"
  25. TESTS_PASSED=$((TESTS_PASSED + 1))
  26. }
  27. print_failure() {
  28. echo -e "${RED}✗ $1${NC}"
  29. TESTS_FAILED=$((TESTS_FAILED + 1))
  30. FAILED_TESTS="${FAILED_TESTS}\n - $1"
  31. }
  32. print_info() {
  33. echo -e "${YELLOW}→ $1${NC}"
  34. }
  35. cleanup() {
  36. print_info "Cleaning up test containers..."
  37. docker compose -f docker-compose.test.yml down -v --remove-orphans 2>/dev/null || true
  38. docker compose down -v --remove-orphans 2>/dev/null || true
  39. }
  40. # Cleanup on exit
  41. trap cleanup EXIT
  42. # Parse arguments
  43. RUN_BUILD=true
  44. RUN_BACKEND=true
  45. RUN_FRONTEND=true
  46. RUN_INTEGRATION=true
  47. while [[ $# -gt 0 ]]; do
  48. case $1 in
  49. --build-only)
  50. RUN_BACKEND=false
  51. RUN_FRONTEND=false
  52. RUN_INTEGRATION=false
  53. shift
  54. ;;
  55. --backend-only)
  56. RUN_BUILD=false
  57. RUN_FRONTEND=false
  58. RUN_INTEGRATION=false
  59. shift
  60. ;;
  61. --frontend-only)
  62. RUN_BUILD=false
  63. RUN_BACKEND=false
  64. RUN_INTEGRATION=false
  65. shift
  66. ;;
  67. --integration-only)
  68. RUN_BUILD=false
  69. RUN_BACKEND=false
  70. RUN_FRONTEND=false
  71. shift
  72. ;;
  73. --skip-build)
  74. RUN_BUILD=false
  75. shift
  76. ;;
  77. --skip-integration)
  78. RUN_INTEGRATION=false
  79. shift
  80. ;;
  81. -h|--help)
  82. echo "Usage: $0 [OPTIONS]"
  83. echo ""
  84. echo "Options:"
  85. echo " --build-only Only run build test"
  86. echo " --backend-only Only run backend tests"
  87. echo " --frontend-only Only run frontend tests"
  88. echo " --integration-only Only run integration tests"
  89. echo " --skip-build Skip build test"
  90. echo " --skip-integration Skip integration tests"
  91. echo " -h, --help Show this help"
  92. exit 0
  93. ;;
  94. *)
  95. echo "Unknown option: $1"
  96. exit 1
  97. ;;
  98. esac
  99. done
  100. print_header "BamBuddy Docker Test Suite"
  101. # ============================================
  102. # Test 1: Docker Build
  103. # ============================================
  104. if [ "$RUN_BUILD" = true ]; then
  105. print_header "Test 1: Docker Build"
  106. print_info "Building production Docker image..."
  107. if docker build -t bambuddy:test . --quiet --pull; then
  108. print_success "Production image builds successfully"
  109. # Verify image has expected labels/structure
  110. print_info "Verifying image structure..."
  111. if docker run --rm bambuddy:test python -c "import backend.app.main; print('Backend imports OK')"; then
  112. print_success "Backend module imports correctly"
  113. else
  114. print_failure "Backend module import failed"
  115. fi
  116. if docker run --rm bambuddy:test test -d /app/static; then
  117. print_success "Static files directory exists"
  118. else
  119. print_failure "Static files directory missing"
  120. fi
  121. else
  122. print_failure "Production image build failed"
  123. fi
  124. fi
  125. # ============================================
  126. # Test 2: Backend Unit Tests
  127. # ============================================
  128. if [ "$RUN_BACKEND" = true ]; then
  129. print_header "Test 2: Backend Unit Tests"
  130. print_info "Building backend test image..."
  131. if docker compose -f docker-compose.test.yml build backend-test --quiet --pull; then
  132. print_info "Running backend tests..."
  133. if docker compose -f docker-compose.test.yml run --rm backend-test; then
  134. print_success "Backend unit tests passed"
  135. else
  136. print_failure "Backend unit tests failed"
  137. fi
  138. else
  139. print_failure "Backend test image build failed"
  140. fi
  141. fi
  142. # ============================================
  143. # Test 3: Frontend Unit Tests
  144. # ============================================
  145. if [ "$RUN_FRONTEND" = true ]; then
  146. print_header "Test 3: Frontend Unit Tests"
  147. print_info "Building frontend test image..."
  148. if docker compose -f docker-compose.test.yml build frontend-test --quiet --pull; then
  149. print_info "Running frontend tests..."
  150. if docker compose -f docker-compose.test.yml run --rm frontend-test; then
  151. print_success "Frontend unit tests passed"
  152. else
  153. print_failure "Frontend unit tests failed"
  154. fi
  155. else
  156. print_failure "Frontend test image build failed"
  157. fi
  158. fi
  159. # ============================================
  160. # Test 4: Integration Tests
  161. # ============================================
  162. if [ "$RUN_INTEGRATION" = true ]; then
  163. print_header "Test 4: Integration Tests"
  164. print_info "Building integration container..."
  165. # Build the integration container first to ensure latest code
  166. if ! docker compose -f docker-compose.test.yml build integration --quiet --pull; then
  167. print_failure "Integration container build failed"
  168. else
  169. print_info "Starting application container..."
  170. # Start the integration container
  171. docker compose -f docker-compose.test.yml up -d integration
  172. # Wait for health check
  173. print_info "Waiting for application to be healthy..."
  174. RETRIES=30
  175. while [ $RETRIES -gt 0 ]; do
  176. if docker compose -f docker-compose.test.yml ps integration | grep -q "healthy"; then
  177. break
  178. fi
  179. sleep 2
  180. ((RETRIES--))
  181. done
  182. if [ $RETRIES -eq 0 ]; then
  183. print_failure "Application failed to become healthy"
  184. docker compose -f docker-compose.test.yml logs integration
  185. else
  186. print_success "Application is healthy"
  187. # Run basic health checks
  188. print_info "Running integration tests..."
  189. # Test health endpoint
  190. HEALTH_RESPONSE=$(docker compose -f docker-compose.test.yml exec -T integration curl -s http://localhost:8000/health)
  191. if echo "$HEALTH_RESPONSE" | grep -q "healthy"; then
  192. print_success "Health endpoint responds correctly"
  193. else
  194. print_failure "Health endpoint check failed"
  195. fi
  196. # Test API endpoints
  197. API_RESPONSE=$(docker compose -f docker-compose.test.yml exec -T integration curl -s http://localhost:8000/api/v1/settings)
  198. if echo "$API_RESPONSE" | grep -q "settings"; then
  199. print_success "Settings API endpoint responds"
  200. else
  201. # Settings might return empty, which is OK
  202. print_success "Settings API endpoint accessible"
  203. fi
  204. # Test static files
  205. STATIC_RESPONSE=$(docker compose -f docker-compose.test.yml exec -T integration curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/)
  206. if [ "$STATIC_RESPONSE" = "200" ]; then
  207. print_success "Static files served correctly"
  208. else
  209. print_failure "Static files not served (HTTP $STATIC_RESPONSE)"
  210. fi
  211. # Run pytest integration tests if they exist
  212. if docker compose -f docker-compose.test.yml run --rm integration-test-runner 2>/dev/null; then
  213. print_success "Integration test suite passed"
  214. else
  215. print_info "No Docker-specific integration tests found (this is OK)"
  216. fi
  217. fi
  218. fi
  219. # Cleanup integration containers
  220. docker compose -f docker-compose.test.yml down -v
  221. fi
  222. # ============================================
  223. # Summary
  224. # ============================================
  225. print_header "Test Summary"
  226. echo ""
  227. echo -e "Tests Passed: ${GREEN}${TESTS_PASSED}${NC}"
  228. echo -e "Tests Failed: ${RED}${TESTS_FAILED}${NC}"
  229. if [ $TESTS_FAILED -gt 0 ]; then
  230. echo ""
  231. echo -e "${RED}Failed tests:${NC}"
  232. echo -e "$FAILED_TESTS"
  233. echo ""
  234. exit 1
  235. else
  236. echo ""
  237. echo -e "${GREEN}All tests passed!${NC}"
  238. echo ""
  239. exit 0
  240. fi