Testing: - Add pytest configuration (pytest.ini) - Add test fixtures (tests/conftest.py) - Add ContentGenerator tests (13 tests) - Add ContentScheduler tests (16 tests) - Add PublisherManager tests (16 tests) - All 45 tests passing Production Docker: - Add docker-compose.prod.yml with healthchecks, resource limits - Add Dockerfile.prod with multi-stage build, non-root user - Add nginx.prod.conf with SSL, rate limiting, security headers - Add .env.prod.example template Maintenance Scripts: - Add backup.sh for database and media backups - Add restore.sh for database restoration - Add cleanup.sh for log rotation and Docker cleanup - Add healthcheck.sh with Telegram alerts Documentation: - Add DEPLOY.md with complete deployment guide Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
125 lines
3.4 KiB
Python
125 lines
3.4 KiB
Python
"""
|
|
Test fixtures and configuration.
|
|
"""
|
|
|
|
import pytest
|
|
from unittest.mock import MagicMock, AsyncMock, patch
|
|
from datetime import datetime, timedelta
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.orm import sessionmaker
|
|
|
|
from app.core.database import Base
|
|
|
|
|
|
# In-memory SQLite for testing
|
|
TEST_DATABASE_URL = "sqlite:///:memory:"
|
|
|
|
|
|
@pytest.fixture
|
|
def test_engine():
|
|
"""Create an in-memory SQLite engine for testing."""
|
|
engine = create_engine(
|
|
TEST_DATABASE_URL,
|
|
connect_args={"check_same_thread": False}
|
|
)
|
|
Base.metadata.create_all(bind=engine)
|
|
yield engine
|
|
Base.metadata.drop_all(bind=engine)
|
|
|
|
|
|
@pytest.fixture
|
|
def test_session(test_engine):
|
|
"""Create a test database session."""
|
|
TestSessionLocal = sessionmaker(
|
|
autocommit=False, autoflush=False, bind=test_engine
|
|
)
|
|
session = TestSessionLocal()
|
|
yield session
|
|
session.close()
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_openai_client():
|
|
"""Mock OpenAI client for DeepSeek API tests."""
|
|
mock_client = MagicMock()
|
|
|
|
mock_response = MagicMock()
|
|
mock_response.choices = [MagicMock()]
|
|
mock_response.choices[0].message.content = "Generated test content #TechTip #AI"
|
|
|
|
mock_client.chat.completions.create.return_value = mock_response
|
|
|
|
return mock_client
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_httpx_client():
|
|
"""Mock httpx client for API calls."""
|
|
mock_client = AsyncMock()
|
|
mock_response = AsyncMock()
|
|
mock_response.status_code = 200
|
|
mock_response.json.return_value = {"id": "123", "success": True}
|
|
mock_client.get.return_value = mock_response
|
|
mock_client.post.return_value = mock_response
|
|
return mock_client
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_product():
|
|
"""Sample product data for testing."""
|
|
return {
|
|
"name": "Laptop HP Pavilion",
|
|
"description": "Laptop potente para trabajo y gaming",
|
|
"price": 15999.00,
|
|
"category": "laptops",
|
|
"specs": {
|
|
"processor": "Intel Core i5",
|
|
"ram": "16GB",
|
|
"storage": "512GB SSD"
|
|
},
|
|
"highlights": ["Alta velocidad", "Diseño compacto", "Garantía 2 años"]
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_service():
|
|
"""Sample service data for testing."""
|
|
return {
|
|
"name": "Automatización con IA",
|
|
"description": "Automatiza tus procesos con inteligencia artificial",
|
|
"category": "ai_automation",
|
|
"target_sectors": ["retail", "manufactura", "servicios"],
|
|
"benefits": ["Reduce costos", "Aumenta productividad", "24/7 operación"],
|
|
"call_to_action": "Agenda una demo gratuita"
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_interaction():
|
|
"""Sample interaction data for testing."""
|
|
return {
|
|
"content": "¿Qué procesador recomiendas para edición de video?",
|
|
"type": "comment",
|
|
"platform": "x",
|
|
"author": "user123"
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_settings():
|
|
"""Mock settings for testing."""
|
|
with patch('app.core.config.settings') as mock:
|
|
mock.DEEPSEEK_API_KEY = "test-api-key"
|
|
mock.DEEPSEEK_BASE_URL = "https://api.deepseek.com"
|
|
mock.BUSINESS_NAME = "Consultoría AS"
|
|
mock.BUSINESS_LOCATION = "Tijuana, México"
|
|
mock.BUSINESS_WEBSITE = "https://consultoria-as.com"
|
|
mock.CONTENT_TONE = "Profesional pero accesible"
|
|
yield mock
|
|
|
|
|
|
@pytest.fixture
|
|
def fixed_datetime():
|
|
"""Fixed datetime for consistent testing."""
|
|
return datetime(2024, 6, 15, 10, 0, 0) # Saturday 10:00
|