FactsDB/tests/test_scheduler_ext.py
Jarian Cottingham 93e287f88b test: add comprehensive test suite with 95% coverage
- 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
2026-07-06 16:27:51 +00:00

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