- Add pytest test suite across all modules (config, database, file_processor, ai_processor, api, scheduler, monitoring, ftp_server) - 145 tests covering normal paths, error handling, edge cases - Mock external dependencies (AI endpoint, requests, pyftpdlib) - 95% code coverage with fail-under=90 threshold in CI - Update CI workflow to run pytest with coverage enforcement - Add pyproject.toml with pytest/coverage configuration
131 lines
4.5 KiB
Python
131 lines
4.5 KiB
Python
"""Extended tests for scheduler: job execution flow."""
|
|
|
|
import os
|
|
import pytest
|
|
from unittest.mock import patch, MagicMock
|
|
|
|
from factsdb.config import DatabaseConfig, AIEndpointConfig, FTPServerConfig, SchedulerConfig
|
|
|
|
|
|
class MockConfig:
|
|
def __init__(self, db_path=":memory:"):
|
|
self.database = DatabaseConfig(path=db_path)
|
|
self.ai_endpoint = AIEndpointConfig(url="http://localhost", auth_token="tok")
|
|
self.ftp_server = FTPServerConfig(host="0.0.0.0", port=2121, username="u", password="p")
|
|
self.scheduler = SchedulerConfig(interval_minutes=10)
|
|
|
|
|
|
class TestFactExtractionJobExecute:
|
|
def test_execute_success(self, tmp_path):
|
|
from factsdb.scheduler import FactExtractionJob
|
|
from factsdb.database import DatabaseManager
|
|
from factsdb.file_processor import FileProcessor
|
|
|
|
cfg = MockConfig(db_path=str(tmp_path / "sched.db"))
|
|
dm = DatabaseManager(cfg.database)
|
|
fp = FileProcessor()
|
|
|
|
dm.create_table("t1")
|
|
|
|
# Create a test file
|
|
test_file = tmp_path / "test.txt"
|
|
test_file.write_text("Apple released the iPhone in 2007")
|
|
|
|
# Mock AI processor
|
|
mock_ai = MagicMock()
|
|
mock_ai.extract_facts_from_text.return_value = {
|
|
"fact": "Test fact",
|
|
"key_entities": ["Apple"],
|
|
"key_dates": ["2007"],
|
|
}
|
|
|
|
job = FactExtractionJob(cfg, dm, fp, mock_ai)
|
|
job.execute(str(tmp_path), "t1", "", "gpt-oss")
|
|
|
|
facts = dm.get_facts("t1")
|
|
assert len(facts) == 1
|
|
assert facts[0]["fact"] == "Test fact"
|
|
|
|
def test_execute_skip_processed(self, tmp_path):
|
|
from factsdb.scheduler import FactExtractionJob
|
|
from factsdb.database import DatabaseManager
|
|
from factsdb.file_processor import FileProcessor
|
|
|
|
cfg = MockConfig(db_path=str(tmp_path / "sched.db"))
|
|
dm = DatabaseManager(cfg.database)
|
|
fp = FileProcessor()
|
|
dm.create_table("t1")
|
|
|
|
test_file = tmp_path / "test.txt"
|
|
test_file.write_text("content")
|
|
dm.mark_file_processed(str(test_file), "t1", True)
|
|
|
|
mock_ai = MagicMock()
|
|
job = FactExtractionJob(cfg, dm, fp, mock_ai)
|
|
job.execute(str(tmp_path), "t1", "", "gpt-oss")
|
|
|
|
mock_ai.extract_facts_from_text.assert_not_called()
|
|
|
|
def test_execute_file_error_continues(self, tmp_path):
|
|
from factsdb.scheduler import FactExtractionJob
|
|
from factsdb.database import DatabaseManager
|
|
from factsdb.file_processor import FileProcessor
|
|
|
|
cfg = MockConfig(db_path=str(tmp_path / "sched.db"))
|
|
dm = DatabaseManager(cfg.database)
|
|
dm.create_table("t1")
|
|
fp = FileProcessor()
|
|
|
|
test_file = tmp_path / "test.txt"
|
|
test_file.write_text("content")
|
|
|
|
mock_ai = MagicMock()
|
|
mock_ai.extract_facts_from_text.side_effect = Exception("AI error")
|
|
|
|
job = FactExtractionJob(cfg, dm, fp, mock_ai)
|
|
job.execute(str(tmp_path), "t1", "", "gpt-oss")
|
|
|
|
facts = dm.get_facts("t1")
|
|
assert len(facts) == 0
|
|
|
|
|
|
class TestSchedulerInitError:
|
|
def test_scheduler_db_init_error(self, tmp_path, monkeypatch):
|
|
from factsdb.scheduler import FactExtractionScheduler
|
|
|
|
cfg = MockConfig(db_path=str(tmp_path / "sched.db"))
|
|
with patch("factsdb.scheduler.AIProcessor"):
|
|
with patch("factsdb.scheduler.DatabaseManager", side_effect=Exception("db error")):
|
|
sched = FactExtractionScheduler(cfg)
|
|
assert sched.db_manager is None
|
|
|
|
|
|
class TestSchedulerRunAllJobs:
|
|
def test_run_all_jobs(self, tmp_path, monkeypatch):
|
|
from factsdb.scheduler import FactExtractionScheduler
|
|
from factsdb.database import DatabaseManager
|
|
|
|
cfg = MockConfig(db_path=str(tmp_path / "sched.db"))
|
|
dm = DatabaseManager(cfg.database)
|
|
dm.create_table("t1")
|
|
|
|
test_file = tmp_path / "test.txt"
|
|
test_file.write_text("content")
|
|
|
|
with patch("factsdb.scheduler.AIProcessor") as mock_ai_cls:
|
|
mock_ai = MagicMock()
|
|
mock_ai.extract_facts_from_text.return_value = {
|
|
"fact": "F",
|
|
"key_entities": [],
|
|
"key_dates": [],
|
|
}
|
|
mock_ai_cls.return_value = mock_ai
|
|
|
|
with patch("factsdb.scheduler.DatabaseManager", return_value=dm):
|
|
sched = FactExtractionScheduler(cfg)
|
|
sched.add_job(str(tmp_path), "t1", "", "gpt-oss")
|
|
sched._run_all_jobs()
|
|
|
|
facts = dm.get_facts("t1")
|
|
assert len(facts) == 1
|