#!/usr/bin/env python3 """ # Test Script for Docker Deployment This script provides comprehensive testing for the RAG system Docker deployment. ## Overview The test script validates all components required for successful Docker deployment: - Dockerfile syntax and structure - Docker Compose configuration - Docker build process - Container runtime functionality - File structure and dependencies ## Test Categories 1. **Dockerfile Tests**: Validate Dockerfile syntax and required components 2. **Docker Compose Tests**: Check docker-compose.yml configuration 3. **Build Tests**: Test Docker image building process 4. **Runtime Tests**: Validate container startup and health checks 5. **File Structure Tests**: Confirm all required files are present 6. **Requirements Tests**: Validate dependencies are properly specified ## Usage Run the script to check Docker deployment readiness: ```bash python test_docker.py ``` ## Prerequisites - Docker installed and running - Docker Compose available - Sufficient disk space for image building - Network connectivity for base image downloads ## Expected Output The script provides detailed feedback on each test: - āœ… PASS: Component is ready for Docker deployment - āŒ FAIL: Component needs attention before deployment - āš ļø WARNING: Optional component missing but not critical """ import os import sys import subprocess from pathlib import Path def test_dockerfile(): """ Test if Dockerfile exists and contains all required components This function validates: - Dockerfile exists in the project root - Contains essential Docker instructions - Proper syntax and structure - Required components for RAG system deployment Returns: bool: True if Dockerfile is valid, False otherwise """ print("šŸ” Testing Dockerfile...") dockerfile_path = Path("Dockerfile") if not dockerfile_path.exists(): print("āŒ Dockerfile not found") return False try: with open(dockerfile_path, "r") as f: content = f.read() # List of essential Dockerfile components that must be present required_components = [ "FROM python:", # Base image specification "WORKDIR /app", # Working directory setup "COPY requirements.txt", # Requirements file copying "RUN pip install", # Python package installation "COPY .", # Application files copying "EXPOSE 8501", # Port exposure for Streamlit 'CMD ["streamlit"', # Application startup command ] missing_components = [] for component in required_components: if component in content: print(f"āœ… {component}") else: print(f"āŒ {component} (missing)") missing_components.append(component) if missing_components: print(f"āŒ Missing Dockerfile components: {missing_components}") return False return True except Exception as e: print(f"āŒ Dockerfile test failed: {e}") return False def test_dockerignore(): """ Test if .dockerignore exists (optional but recommended) This function checks for the presence of .dockerignore file, which helps optimize Docker builds by excluding unnecessary files. Returns: bool: True if .dockerignore exists or is optional, False if critical """ print("\nšŸ” Testing .dockerignore...") dockerignore_path = Path(".dockerignore") if dockerignore_path.exists(): print("āœ… .dockerignore exists") return True else: print("āš ļø .dockerignore not found (optional but recommended)") return True def test_docker_compose(): """ Test if docker-compose.yml exists and is properly configured This function validates: - docker-compose.yml file exists - Contains proper service definitions - Port mappings are correct - Volume mounts are configured Returns: bool: True if docker-compose.yml is valid, False otherwise """ print("\nšŸ” Testing docker-compose.yml...") compose_path = Path("docker-compose.yml") if compose_path.exists(): print("āœ… docker-compose.yml exists") return True else: print("āš ļø docker-compose.yml not found (optional)") return True def test_docker_build(): """ Test Docker build process locally This function: - Attempts to build the Docker image - Validates build process completes successfully - Checks for build errors and warnings - Ensures all dependencies are properly resolved Returns: bool: True if Docker build succeeds, False otherwise """ print("\nšŸ” Testing Docker build...") try: # Test Docker build with timeout to prevent hanging result = subprocess.run( ["docker", "build", "-t", "rag-system-test", "."], capture_output=True, text=True, timeout=300, # 5 minutes timeout for build ) if result.returncode == 0: print("āœ… Docker build successful") return True else: print(f"āŒ Docker build failed: {result.stderr}") return False except subprocess.TimeoutExpired: print("āŒ Docker build timed out") return False except FileNotFoundError: print("āš ļø Docker not installed or not in PATH") return False except Exception as e: print(f"āŒ Docker build test failed: {e}") return False def test_docker_run(): """ Test Docker container runtime functionality This function: - Attempts to run the built Docker container - Validates container startup process - Checks if the application is accessible - Tests basic container functionality Returns: bool: True if Docker run succeeds, False otherwise """ print("\nšŸ” Testing Docker run...") try: # Test Docker run with brief execution result = subprocess.run( [ "docker", "run", "--rm", "-d", "-p", "8501:8501", "--name", "rag-test", "rag-system-test", ], capture_output=True, text=True, timeout=30, # 30 seconds timeout for startup ) if result.returncode == 0: print("āœ… Docker run successful") # Clean up the test container subprocess.run(["docker", "stop", "rag-test"], capture_output=True) return True else: print(f"āŒ Docker run failed: {result.stderr}") return False except subprocess.TimeoutExpired: print("āŒ Docker run timed out") return False except FileNotFoundError: print("āš ļø Docker not installed or not in PATH") return False except Exception as e: print(f"āŒ Docker run test failed: {e}") return False def test_file_structure(): """ Test if all required files exist for Docker deployment This function checks for essential files: - Main application files - Configuration files - Docker-related files - Documentation files Returns: bool: True if all required files exist, False otherwise """ print("\nšŸ” Testing file structure...") # List of required files for Docker deployment required_files = [ "app.py", # Main Streamlit application "rag_system.py", # Core RAG system "pdf_processor.py", # PDF processing utilities "requirements.txt", # Python dependencies "Dockerfile", # Docker configuration ] # List of optional files (nice to have but not critical) optional_files = [ ".dockerignore", # Docker build optimization "docker-compose.yml", # Multi-container setup "README.md", # Project documentation ] missing_required = [] missing_optional = [] # Check required files for file in required_files: if os.path.exists(file): print(f"āœ… {file}") else: print(f"āŒ {file} (missing)") missing_required.append(file) # Check optional files for file in optional_files: if os.path.exists(file): print(f"āœ… {file}") else: print(f"āš ļø {file} (optional)") missing_optional.append(file) if missing_required: print(f"āŒ Missing required files: {missing_required}") return False return True def test_requirements(): """ Test if requirements.txt contains all essential packages This function validates: - Essential packages are listed - Package versions are specified - No obvious missing dependencies - Compatibility with Docker environment Returns: bool: True if requirements are valid, False otherwise """ print("\nšŸ” Testing requirements.txt...") try: with open("requirements.txt", "r") as f: requirements = f.read() # List of essential packages that must be present essential_packages = [ "streamlit", # Web framework "torch", # Deep learning "transformers", # Language models "sentence-transformers", # Embeddings "faiss-cpu", # Vector search "rank-bm25", # Sparse retrieval "pypdf", # PDF processing ] missing_packages = [] for package in essential_packages: if package in requirements: print(f"āœ… {package}") else: print(f"āŒ {package} (missing)") missing_packages.append(package) if missing_packages: print(f"āŒ Missing packages: {missing_packages}") return False return True except Exception as e: print(f"āŒ Requirements test failed: {e}") return False def main(): """ Run all Docker deployment tests and provide comprehensive feedback This function: 1. Executes all Docker-related test categories 2. Tracks test results and provides detailed feedback 3. Gives deployment recommendations 4. Identifies potential issues before deployment The tests are designed to catch common Docker deployment issues early. """ print("🐳 Docker Deployment Test\n") # Define all test functions with descriptive names tests = [ ("File Structure", test_file_structure), ("Requirements", test_requirements), ("Dockerfile", test_dockerfile), (".dockerignore", test_dockerignore), ("docker-compose.yml", test_docker_compose), ("Docker Build", test_docker_build), ("Docker Run", test_docker_run), ] # Execute all tests and collect results results = [] for test_name, test_func in tests: try: result = test_func() results.append((test_name, result)) except Exception as e: print(f"āŒ {test_name} test failed with exception: {e}") results.append((test_name, False)) # ============================================================================= # RESULTS SUMMARY # ============================================================================= # Display comprehensive test results print("\n" + "=" * 50) print("šŸ“Š Test Results Summary") print("=" * 50) passed = 0 total = len(results) # Show individual test results for test_name, result in results: status = "āœ… PASS" if result else "āŒ FAIL" print(f"{test_name:20} {status}") if result: passed += 1 # Display overall statistics print(f"\nOverall: {passed}/{total} tests passed") # ============================================================================= # DEPLOYMENT RECOMMENDATIONS # ============================================================================= if passed == total: print("šŸŽ‰ All tests passed! Ready for Hugging Face Docker deployment.") print("\nNext steps:") print("1. Create a new Hugging Face Space with Docker SDK") print("2. Upload all files from this directory") print("3. Wait for Docker build to complete") print("4. Test your RAG system!") else: print("āš ļø Some tests failed. Please fix the issues before deployment.") print("\nTroubleshooting:") print("1. Install Docker if not available") print("2. Check file permissions and paths") print("3. Verify Dockerfile syntax") print("4. Test Docker build locally: docker build -t rag-system .") # ============================================================================= # SCRIPT ENTRY POINT # ============================================================================= if __name__ == "__main__": main()