test_docker.sh 8.4 KB

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