Add automated unit and mock integration test suite
- Configure conftest.py with pytest tmp_path DB isolation fixtures - Add test_db.py for schema connection validations - Add test_fetcher.py with mocked yt-dlp subprocess parser checks - Add test_summarizer.py with mocked transcripts and Claude API requests - Add test_main.py for FastAPI router endpoints and state updates Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import pytest
|
||||
import os
|
||||
import json
|
||||
import aiosqlite
|
||||
import fetcher
|
||||
import asyncio
|
||||
from unittest.mock import patch, AsyncMock
|
||||
|
||||
class MockProcess:
|
||||
def __init__(self, stdout_data, returncode=0, stderr_data=b""):
|
||||
self.stdout_data = stdout_data
|
||||
self.stderr_data = stderr_data
|
||||
self.returncode = returncode
|
||||
|
||||
async def communicate(self):
|
||||
return self.stdout_data, self.stderr_data
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fetch_subscriptions_no_cookies(tmp_path, monkeypatch):
|
||||
monkeypatch.setattr(fetcher, "COOKIES_PATH", "/non/existent/path/cookies.txt")
|
||||
count = await fetcher.fetch_subscriptions()
|
||||
assert count == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fetch_subscriptions_success(test_db, tmp_path, monkeypatch):
|
||||
cookies_file = os.path.join(tmp_path, "mock_cookies.txt")
|
||||
with open(cookies_file, "w") as f:
|
||||
f.write("# Netscape HTTP Cookie File")
|
||||
monkeypatch.setattr(fetcher, "COOKIES_PATH", cookies_file)
|
||||
|
||||
video1 = {
|
||||
"id": "vid123",
|
||||
"title": "Mock Video 1",
|
||||
"uploader": "Uploader One",
|
||||
"uploader_id": "chan123",
|
||||
"upload_date": "20260601",
|
||||
"duration": 360,
|
||||
"thumbnail": "https://img.youtube.com/vi/vid123/hqdefault.jpg"
|
||||
}
|
||||
video2 = {
|
||||
"id": "vid456",
|
||||
"title": "Mock Video 2",
|
||||
"uploader": "Uploader Two",
|
||||
"uploader_id": "chan456",
|
||||
"upload_date": "20260602",
|
||||
"duration": 720
|
||||
}
|
||||
stdout_bytes = (json.dumps(video1) + "\n" + json.dumps(video2) + "\n").encode("utf-8")
|
||||
|
||||
mock_process = MockProcess(stdout_data=stdout_bytes, returncode=0)
|
||||
|
||||
with patch("asyncio.create_subprocess_exec", return_value=mock_process) as mock_exec:
|
||||
count = await fetcher.fetch_subscriptions()
|
||||
|
||||
mock_exec.assert_called_once()
|
||||
args = mock_exec.call_args[0]
|
||||
assert "yt-dlp" in args
|
||||
assert "https://www.youtube.com/feed/subscriptions" in args
|
||||
assert cookies_file in args
|
||||
assert count == 2
|
||||
|
||||
# Query db to verify values
|
||||
cursor = await test_db.execute("SELECT * FROM videos ORDER BY video_id")
|
||||
videos = await cursor.fetchall()
|
||||
assert len(videos) == 2
|
||||
|
||||
assert videos[0]["video_id"] == "vid123"
|
||||
assert videos[0]["title"] == "Mock Video 1"
|
||||
assert videos[0]["channel_name"] == "Uploader One"
|
||||
assert videos[0]["channel_id"] == "chan123"
|
||||
assert videos[0]["url"] == "https://www.youtube.com/watch?v=vid123"
|
||||
assert videos[0]["thumbnail_url"] == "https://img.youtube.com/vi/vid123/hqdefault.jpg"
|
||||
assert videos[0]["publish_date"] == "2026-06-01"
|
||||
assert videos[0]["duration"] == 360
|
||||
assert videos[0]["status"] == "pending"
|
||||
|
||||
assert videos[1]["video_id"] == "vid456"
|
||||
assert videos[1]["title"] == "Mock Video 2"
|
||||
assert videos[1]["publish_date"] == "2026-06-02"
|
||||
assert videos[1]["duration"] == 720
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_fetch_subscriptions_skip_duplicates(test_db, tmp_path, monkeypatch):
|
||||
cookies_file = os.path.join(tmp_path, "mock_cookies.txt")
|
||||
with open(cookies_file, "w") as f:
|
||||
f.write("# Netscape HTTP Cookie File")
|
||||
monkeypatch.setattr(fetcher, "COOKIES_PATH", cookies_file)
|
||||
|
||||
# Insert an existing video record first
|
||||
await test_db.execute("""
|
||||
INSERT INTO videos (video_id, title, url, status)
|
||||
VALUES ('vid123', 'Mock Video 1', 'https://www.youtube.com/watch?v=vid123', 'pending')
|
||||
""")
|
||||
await test_db.commit()
|
||||
|
||||
video1 = {
|
||||
"id": "vid123",
|
||||
"title": "Mock Video 1",
|
||||
"upload_date": "20260601"
|
||||
}
|
||||
video2 = {
|
||||
"id": "vid456",
|
||||
"title": "Mock Video 2",
|
||||
"upload_date": "20260602"
|
||||
}
|
||||
stdout_bytes = (json.dumps(video1) + "\n" + json.dumps(video2) + "\n").encode("utf-8")
|
||||
|
||||
mock_process = MockProcess(stdout_data=stdout_bytes, returncode=0)
|
||||
|
||||
with patch("asyncio.create_subprocess_exec", return_value=mock_process):
|
||||
count = await fetcher.fetch_subscriptions()
|
||||
assert count == 1 # Only 1 new video should be added (vid456)
|
||||
Reference in New Issue
Block a user