run_tests.sh
Rama main · réplica de lectura del repositorio original.
#!/bin/bash
# Calibre-Web Automated - Interactive Test Runner
# Copyright (C) 2024-2025 Calibre-Web Automated contributors
# SPDX-License-Identifier: GPL-3.0-or-later
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
BOLD='\033[1m'
# Script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# Activate venv if it exists
if [ -d ".venv" ]; then
source .venv/bin/activate
fi
# Test configuration
# Default to 8085 to avoid conflicts with production CWA on 8083
TEST_PORT="${CWA_TEST_PORT:-8085}"
# Determine pytest command (python3 -m pytest works in more environments)
if command -v pytest &> /dev/null; then
PYTEST="pytest"
else
PYTEST="python3 -m pytest"
fi
# Check dependencies
check_dependencies() {
local missing_deps=0
# Check Docker
if ! command -v docker &> /dev/null; then
print_warning "Docker not found - integration tests will fail"
missing_deps=1
elif ! docker info &> /dev/null; then
print_warning "Docker daemon not running - integration tests will fail"
missing_deps=1
fi
# Check Python venv
if [ ! -d ".venv" ]; then
print_warning "Virtual environment not found"
echo " Run: python3 -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt"
missing_deps=1
fi
# Check pytest
if ! command -v pytest &> /dev/null && ! python3 -c "import pytest" &> /dev/null; then
print_warning "pytest not installed"
echo " Run: pip install pytest pytest-timeout pytest-flask pytest-mock faker testcontainers"
missing_deps=1
fi
if [ $missing_deps -eq 1 ]; then
echo ""
read -p "Continue anyway? [y/N]: " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
}
# Print header
print_header() {
clear
echo -e "${BOLD}${CYAN}"
echo "╔════════════════════════════════════════════════════════════╗"
echo "║ ║"
echo "║ Calibre-Web Automated - Test Suite Runner ║"
echo "║ ║"
echo "╚════════════════════════════════════════════════════════════╝"
echo "Setup Guide:"
echo "https://github.com/crocodilestick/Calibre-Web-Automated/wiki/Testing-Quick-Setup"
echo -e "${NC}"
}
# Print section header
print_section() {
echo -e "\n${BOLD}${BLUE}▶ $1${NC}"
}
# Print success message
print_success() {
echo -e "${GREEN}✓${NC} $1"
}
# Print error message
print_error() {
echo -e "${RED}✗${NC} $1"
}
# Print warning message
print_warning() {
echo -e "${YELLOW}⚠${NC} $1"
}
# Print info message
print_info() {
echo -e "${CYAN}ℹ${NC} $1"
}
# Check if running inside Docker
check_environment() {
if [ -f /.dockerenv ]; then
ENVIRONMENT="docker"
print_info "Running inside Docker container (Dev Container detected)"
DEFAULT_MODE="dind"
else
ENVIRONMENT="host"
print_info "Running on host machine"
DEFAULT_MODE="bind"
fi
}
# Show main menu
show_menu() {
print_header
check_environment
check_dependencies
echo ""
echo -e "${BOLD}Select Test Mode:${NC}"
echo ""
echo -e " ${BOLD}1)${NC} Integration Tests (Bind Mount Mode)"
echo " └─ Standard mode - uses temporary directories"
echo " └─ Best for: Local development, CI/CD"
echo ""
echo -e " ${BOLD}2)${NC} Integration Tests (Docker Volume Mode)"
echo " └─ DinD compatible - uses Docker volumes"
echo " └─ Best for: Dev containers, Docker-in-Docker"
echo ""
echo -e " ${BOLD}3)${NC} Docker Startup Tests"
echo " └─ Tests container initialization and health"
echo ""
echo -e " ${BOLD}4)${NC} All Tests (Full Suite)"
echo " └─ Run everything available"
echo ""
echo -e " ${BOLD}5)${NC} Quick Test (Single Integration Test)"
echo " └─ Fast verification - runs one test"
echo ""
echo -e " ${BOLD}6)${NC} Custom Test Selection"
echo " └─ Choose specific test file or pattern"
echo ""
echo -e " ${BOLD}7)${NC} Show Test Info & Status"
echo ""
echo -e " ${BOLD}q)${NC} Quit"
echo ""
echo -ne "${BOLD}Enter your choice [1-7, q]:${NC} "
}
# Run integration tests in bind mount mode
run_integration_bind() {
print_header
print_section "Running Integration Tests (Bind Mount Mode)"
echo ""
print_info "Starting test container with bind mounts..."
print_info "This will take ~3-4 minutes"
echo ""
# Check if pytest is available
if ! command -v pytest &> /dev/null; then
print_error "pytest not found! Installing..."
pip install -q pytest pytest-timeout pytest-flask pytest-mock faker
fi
# Run tests
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
if pytest tests/integration/test_ingest_pipeline.py -v --tb=short; then
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
echo ""
print_success "All integration tests passed!"
else
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
echo ""
print_error "Some tests failed. Check output above."
fi
echo ""
read -p "Press Enter to continue..."
}
# Run integration tests in Docker volume mode
run_integration_dind() {
print_header
print_section "Running Integration Tests (Docker Volume Mode)"
echo ""
print_info "Starting test container with Docker volumes..."
print_info "This will take ~3-4 minutes"
print_warning "Note: One test (cwa_db_tracks_import) will be skipped"
echo ""
# Check if pytest is available
if ! command -v pytest &> /dev/null; then
print_error "pytest not found! Installing..."
pip install -q pytest pytest-timeout pytest-flask pytest-mock faker
fi
# Run tests with volume mode enabled
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
if USE_DOCKER_VOLUMES=true pytest tests/integration/test_ingest_pipeline.py -v --tb=short; then
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
echo ""
print_success "All runnable tests passed! (19/20, 1 skipped)"
else
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
echo ""
print_error "Some tests failed. Check output above."
fi
echo ""
read -p "Press Enter to continue..."
}
# Run Docker startup tests
run_docker_tests() {
print_header
print_section "Running Docker Startup Tests"
echo ""
print_info "Testing container initialization..."
echo ""
if [ ! -f tests/docker/test_container_startup.py ]; then
print_error "Docker tests not found at tests/docker/test_container_startup.py"
echo ""
read -p "Press Enter to continue..."
return
fi
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
if pytest tests/docker/ -v --tb=short; then
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
echo ""
print_success "Docker tests passed!"
else
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
echo ""
print_error "Some Docker tests failed."
fi
echo ""
read -p "Press Enter to continue..."
}
# Run all tests
run_all_tests() {
print_header
print_section "Running Full Test Suite"
echo ""
print_info "This will run all available tests"
print_warning "Estimated time: 5-7 minutes"
echo ""
echo -ne "Continue? [y/N]: "
read -r confirm
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
return
fi
echo ""
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
# Determine mode based on environment
if [ "$DEFAULT_MODE" = "dind" ]; then
print_info "Using Docker Volume mode (DinD environment detected)"
USE_DOCKER_VOLUMES=true $PYTEST tests/ -v --tb=short || true
else
print_info "Using Bind Mount mode"
$PYTEST tests/ -v --tb=short || true
fi
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
echo ""
read -p "Press Enter to continue..."
}
# Run quick test
run_quick_test() {
print_header
print_section "Quick Test - Single Integration Test"
echo ""
print_info "Running: test_ingest_epub_already_target_format"
print_info "This verifies basic ingest functionality (~30 seconds)"
echo ""
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
if [ "$DEFAULT_MODE" = "dind" ]; then
USE_DOCKER_VOLUMES=true $PYTEST tests/integration/test_ingest_pipeline.py::TestBookIngestInContainer::test_ingest_epub_already_target_format -v
else
$PYTEST tests/integration/test_ingest_pipeline.py::TestBookIngestInContainer::test_ingest_epub_already_target_format -v
fi
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
echo ""
read -p "Press Enter to continue..."
}
# Custom test selection
run_custom_test() {
print_header
print_section "Custom Test Selection"
echo ""
echo "Available test files:"
echo " 1) tests/integration/test_ingest_pipeline.py (20 tests)"
echo " 2) tests/docker/test_container_startup.py (9 tests)"
echo ""
echo "Or enter a custom pytest pattern (e.g., tests/integration/ -k metadata)"
echo ""
echo -ne "Enter choice [1-2 or custom pattern]: "
read -r choice
case $choice in
1)
TEST_PATH="tests/integration/test_ingest_pipeline.py"
;;
2)
TEST_PATH="tests/docker/test_container_startup.py"
;;
*)
TEST_PATH="$choice"
;;
esac
echo ""
print_info "Running: $TEST_PATH"
echo ""
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
if [ "$DEFAULT_MODE" = "dind" ]; then
USE_DOCKER_VOLUMES=true $PYTEST $TEST_PATH -v
else
$PYTEST $TEST_PATH -v
fi
echo -e "${YELLOW}═══════════════════════════════════════════════════════════${NC}"
echo ""
read -p "Press Enter to continue..."
}
# Show test information
show_info() {
print_header
print_section "Test Suite Information"
echo ""
print_info "Test Environment: $ENVIRONMENT"
print_info "Default Mode: $DEFAULT_MODE"
echo ""
echo -e "${BOLD}Available Tests:${NC}"
echo ""
# Count tests
echo "📊 Integration Tests:"
$PYTEST tests/integration/ --collect-only -q 2>/dev/null | tail -1 || echo " (pytest needed to count)"
echo ""
if [ -d tests/docker ]; then
echo "🐳 Docker Tests:"
$PYTEST tests/docker/ --collect-only -q 2>/dev/null | tail -1 || echo " (pytest needed to count)"
echo ""
fi
echo -e "${BOLD}Test Modes:${NC}"
echo ""
echo -e "• ${BOLD}Bind Mount Mode${NC} (Default on host)"
echo " └─ Uses temporary directories"
echo " └─ 20/20 integration tests pass"
echo " └─ Faster cleanup"
echo ""
echo -e "• ${BOLD}Docker Volume Mode${NC} (Default in dev containers)"
echo " └─ Uses Docker volumes via docker cp"
echo " └─ 19/20 integration tests pass (1 skipped)"
echo " └─ Required for Docker-in-Docker"
echo ""
echo -e "${BOLD}Documentation:${NC}"
echo " • tests/DOCKER_VOLUMES.md - Volume mode details"
echo " • HYBRID_DOCKER_IMPLEMENTATION.md - Implementation notes"
echo " • DIND_MODE_COMPLETE.md - Completion summary"
echo ""
read -p "Press Enter to continue..."
}
# Main loop
main() {
# Check for required dependencies
if ! command -v docker &> /dev/null; then
print_header
print_error "Docker is required but not found!"
echo ""
echo "Please install Docker and try again."
exit 1
fi
while true; do
show_menu
read -r choice
case $choice in
1)
run_integration_bind
;;
2)
run_integration_dind
;;
3)
run_docker_tests
;;
4)
run_all_tests
;;
5)
run_quick_test
;;
6)
run_custom_test
;;
7)
show_info
;;
q|Q)
print_header
print_success "Goodbye!"
echo ""
exit 0
;;
*)
print_header
print_error "Invalid choice. Please try again."
sleep 2
;;
esac
done
}
# Run main function
main