264 lines
8.0 KiB
Python
264 lines
8.0 KiB
Python
from datetime import datetime
|
|
|
|
import pytest
|
|
|
|
from src.models import (
|
|
AppConfig,
|
|
Article,
|
|
ProcessingResult,
|
|
ProcessingStats,
|
|
ProcessingStatus,
|
|
SimplifyCommand,
|
|
)
|
|
|
|
|
|
class TestAppConfig:
|
|
|
|
def test_default_values(self):
|
|
with pytest.raises(ValueError):
|
|
AppConfig()
|
|
|
|
def test_valid_config(self):
|
|
config = AppConfig(
|
|
openai_api_key="test_key",
|
|
db_path="./test.db",
|
|
)
|
|
|
|
assert config.openai_api_key == "test_key"
|
|
assert config.openai_model == "gpt-4o-mini"
|
|
assert config.openai_temperature == 0.0
|
|
assert config.max_concurrent_llm == 5
|
|
assert config.openai_rpm == 200
|
|
|
|
def test_db_url_generation(self):
|
|
config = AppConfig(
|
|
openai_api_key="test_key",
|
|
db_path="./test.db",
|
|
)
|
|
|
|
assert config.db_url == "sqlite+aiosqlite:///test.db"
|
|
assert config.sync_db_url == "sqlite:///test.db"
|
|
|
|
def test_validation_constraints(self):
|
|
with pytest.raises(ValueError):
|
|
AppConfig(
|
|
openai_api_key="test_key",
|
|
openai_temperature=3.0,
|
|
)
|
|
|
|
with pytest.raises(ValueError):
|
|
AppConfig(
|
|
openai_api_key="test_key",
|
|
max_concurrent_llm=100,
|
|
)
|
|
|
|
|
|
class TestArticle:
|
|
|
|
def test_article_creation(self, sample_article_data):
|
|
article = Article(
|
|
url=sample_article_data.url,
|
|
title=sample_article_data.title,
|
|
raw_text=sample_article_data.raw_text,
|
|
)
|
|
|
|
assert article.url == sample_article_data.url
|
|
assert article.title == sample_article_data.title
|
|
assert article.status == ProcessingStatus.PENDING
|
|
assert article.simplified_text is None
|
|
assert isinstance(article.created_at, datetime)
|
|
|
|
def test_mark_processing(self, sample_article):
|
|
article = sample_article
|
|
original_updated = article.updated_at
|
|
|
|
article.mark_processing()
|
|
|
|
assert article.status == ProcessingStatus.PROCESSING
|
|
assert article.updated_at != original_updated
|
|
|
|
def test_mark_completed(self, sample_article):
|
|
article = sample_article
|
|
simplified_text = "Упрощённый текст"
|
|
|
|
article.mark_completed(
|
|
simplified_text=simplified_text,
|
|
token_count_raw=100,
|
|
token_count_simplified=50,
|
|
processing_time=2.5,
|
|
)
|
|
|
|
assert article.status == ProcessingStatus.COMPLETED
|
|
assert article.simplified_text == simplified_text
|
|
assert article.token_count_raw == 100
|
|
assert article.token_count_simplified == 50
|
|
assert article.processing_time_seconds == 2.5
|
|
assert article.error_message is None
|
|
assert article.updated_at is not None
|
|
|
|
def test_mark_failed(self, sample_article):
|
|
article = sample_article
|
|
error_message = "Тестовая ошибка"
|
|
|
|
article.mark_failed(error_message)
|
|
|
|
assert article.status == ProcessingStatus.FAILED
|
|
assert article.error_message == error_message
|
|
assert article.updated_at is not None
|
|
|
|
def test_mark_failed_long_error(self, sample_article):
|
|
article = sample_article
|
|
long_error = "x" * 1500
|
|
|
|
article.mark_failed(long_error)
|
|
|
|
assert len(article.error_message) == 1000
|
|
assert article.error_message == "x" * 1000
|
|
|
|
|
|
class TestSimplifyCommand:
|
|
|
|
def test_command_creation(self):
|
|
url = "https://ru.wikipedia.org/wiki/Тест"
|
|
command = SimplifyCommand(url=url)
|
|
|
|
assert command.url == url
|
|
assert command.force_reprocess is False
|
|
|
|
def test_command_with_force(self):
|
|
url = "https://ru.wikipedia.org/wiki/Тест"
|
|
command = SimplifyCommand(url=url, force_reprocess=True)
|
|
|
|
assert command.url == url
|
|
assert command.force_reprocess is True
|
|
|
|
def test_command_string_representation(self):
|
|
url = "https://ru.wikipedia.org/wiki/Тест"
|
|
command = SimplifyCommand(url=url, force_reprocess=True)
|
|
|
|
expected = f"SimplifyCommand(url='{url}', force=True)"
|
|
assert str(command) == expected
|
|
|
|
|
|
class TestProcessingResult:
|
|
|
|
def test_success_result_creation(self):
|
|
result = ProcessingResult.success_result(
|
|
url="https://ru.wikipedia.org/wiki/Тест",
|
|
title="Тест",
|
|
raw_text="Исходный текст",
|
|
simplified_text="Упрощённый текст",
|
|
token_count_raw=100,
|
|
token_count_simplified=50,
|
|
processing_time_seconds=2.5,
|
|
)
|
|
|
|
assert result.success is True
|
|
assert result.url == "https://ru.wikipedia.org/wiki/Тест"
|
|
assert result.title == "Тест"
|
|
assert result.raw_text == "Исходный текст"
|
|
assert result.simplified_text == "Упрощённый текст"
|
|
assert result.token_count_raw == 100
|
|
assert result.token_count_simplified == 50
|
|
assert result.processing_time_seconds == 2.5
|
|
assert result.error_message is None
|
|
|
|
def test_failure_result_creation(self):
|
|
result = ProcessingResult.failure_result(
|
|
url="https://ru.wikipedia.org/wiki/Тест",
|
|
error_message="Тестовая ошибка",
|
|
)
|
|
|
|
assert result.success is False
|
|
assert result.url == "https://ru.wikipedia.org/wiki/Тест"
|
|
assert result.error_message == "Тестовая ошибка"
|
|
assert result.title is None
|
|
assert result.raw_text is None
|
|
assert result.simplified_text is None
|
|
|
|
|
|
class TestProcessingStats:
|
|
|
|
def test_initial_stats(self):
|
|
stats = ProcessingStats()
|
|
|
|
assert stats.total_processed == 0
|
|
assert stats.successful == 0
|
|
assert stats.failed == 0
|
|
assert stats.skipped == 0
|
|
assert stats.success_rate == 0.0
|
|
assert stats.average_processing_time == 0.0
|
|
|
|
def test_add_successful_result(self):
|
|
stats = ProcessingStats()
|
|
result = ProcessingResult.success_result(
|
|
url="test",
|
|
title="Test",
|
|
raw_text="text",
|
|
simplified_text="simple",
|
|
token_count_raw=100,
|
|
token_count_simplified=50,
|
|
processing_time_seconds=2.0,
|
|
)
|
|
|
|
stats.add_result(result)
|
|
|
|
assert stats.total_processed == 1
|
|
assert stats.successful == 1
|
|
assert stats.failed == 0
|
|
assert stats.success_rate == 100.0
|
|
assert stats.average_processing_time == 2.0
|
|
|
|
def test_add_failed_result(self):
|
|
stats = ProcessingStats()
|
|
result = ProcessingResult.failure_result("test", "error")
|
|
|
|
stats.add_result(result)
|
|
|
|
assert stats.total_processed == 1
|
|
assert stats.successful == 0
|
|
assert stats.failed == 1
|
|
assert stats.success_rate == 0.0
|
|
|
|
def test_mixed_results(self):
|
|
stats = ProcessingStats()
|
|
|
|
success_result = ProcessingResult.success_result(
|
|
url="test1",
|
|
title="Test1",
|
|
raw_text="text",
|
|
simplified_text="simple",
|
|
token_count_raw=100,
|
|
token_count_simplified=50,
|
|
processing_time_seconds=3.0,
|
|
)
|
|
stats.add_result(success_result)
|
|
|
|
failure_result = ProcessingResult.failure_result("test2", "error")
|
|
stats.add_result(failure_result)
|
|
|
|
success_result2 = ProcessingResult.success_result(
|
|
url="test3",
|
|
title="Test3",
|
|
raw_text="text",
|
|
simplified_text="simple",
|
|
token_count_raw=100,
|
|
token_count_simplified=50,
|
|
processing_time_seconds=1.0,
|
|
)
|
|
stats.add_result(success_result2)
|
|
|
|
assert stats.total_processed == 3
|
|
assert stats.successful == 2
|
|
assert stats.failed == 1
|
|
assert stats.success_rate == pytest.approx(66.67, rel=1e-2)
|
|
assert stats.average_processing_time == 2.0
|
|
|
|
def test_add_skipped(self):
|
|
stats = ProcessingStats()
|
|
|
|
stats.add_skipped()
|
|
stats.add_skipped()
|
|
|
|
assert stats.skipped == 2
|