test(02-02): add failing tests for PlatformAdapter base class

- Add test for abstract class instantiation prevention
- Add test for incomplete implementation detection
- Add test for complete implementation instantiation
- Add test for async method signatures
- Add shared fixtures for platform tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 18:19:24 +08:00
parent ae7dea9581
commit 3f42bfaf0d
5 changed files with 400 additions and 0 deletions
+122
View File
@@ -0,0 +1,122 @@
"""Tests for PlatformAdapter base class
This module tests the interface contracts for the PlatformAdapter abstract base class:
1. PlatformAdapter is an abstract class and cannot be instantiated directly
2. Subclasses must implement all abstract methods
"""
import pytest
from abc import ABC
from typing import Dict, Any
from kb_pipeline.platforms.base import PlatformAdapter
class TestPlatformAdapterInterface:
"""Test the PlatformAdapter interface contracts"""
def test_platform_adapter_is_abstract(self):
"""Test 1: PlatformAdapter is an abstract class and cannot be instantiated directly"""
# Verify it's an ABC subclass
assert issubclass(PlatformAdapter, ABC)
# Verify it cannot be instantiated directly
with pytest.raises(TypeError) as exc_info:
PlatformAdapter()
# Error should mention abstract methods
assert "abstract" in str(exc_info.value).lower()
def test_subclass_must_implement_all_methods(self):
"""Test 2: Subclass must implement all abstract methods"""
# Create an incomplete implementation
class IncompleteAdapter(PlatformAdapter):
def get_content_type(self, url: str) -> str:
return "video"
# Missing: fetch_metadata, fetch_content, get_output_filename
# This should fail to instantiate
with pytest.raises(TypeError) as exc_info:
IncompleteAdapter()
# Verify error mentions missing methods
error_msg = str(exc_info.value).lower()
assert "abstract" in error_msg or "implement" in error_msg
def test_complete_implementation_can_be_instantiated(self):
"""Test that a complete implementation can be instantiated"""
class CompleteAdapter(PlatformAdapter):
def get_content_type(self, url: str) -> str:
return "video"
async def fetch_metadata(self, content_id: str, content_type: str) -> Dict[str, Any]:
return {"title": "test"}
async def fetch_content(self, content_id: str, content_type: str) -> str:
return "# Test Content"
def get_output_filename(self, content_id: str, content_type: str, suffix: str) -> str:
return f"test_{content_id}_{suffix}"
# Should instantiate without error
adapter = CompleteAdapter()
assert adapter is not None
assert adapter.get_content_type("https://example.com/video/123") == "video"
class TestPlatformAdapterMethods:
"""Test the abstract method signatures"""
def test_get_content_type_signature(self):
"""Test get_content_type method signature"""
class TestAdapter(PlatformAdapter):
def get_content_type(self, url: str) -> str:
return "video"
async def fetch_metadata(self, content_id: str, content_type: str) -> Dict[str, Any]:
return {}
async def fetch_content(self, content_id: str, content_type: str) -> str:
return ""
def get_output_filename(self, content_id: str, content_type: str, suffix: str) -> str:
return ""
adapter = TestAdapter()
# Method should accept URL string and return content type string
result = adapter.get_content_type("https://www.bilibili.com/video/BV1test")
assert isinstance(result, str)
def test_fetch_metadata_is_async(self):
"""Test fetch_metadata is an async method"""
import inspect
assert inspect.iscoroutinefunction(PlatformAdapter.fetch_metadata)
def test_fetch_content_is_async(self):
"""Test fetch_content is an async method"""
import inspect
assert inspect.iscoroutinefunction(PlatformAdapter.fetch_content)
def test_get_output_filename_signature(self):
"""Test get_output_filename method signature"""
class TestAdapter(PlatformAdapter):
def get_content_type(self, url: str) -> str:
return ""
async def fetch_metadata(self, content_id: str, content_type: str) -> Dict[str, Any]:
return {}
async def fetch_content(self, content_id: str, content_type: str) -> str:
return ""
def get_output_filename(self, content_id: str, content_type: str, suffix: str) -> str:
return f"{content_type}_{content_id}_{suffix}"
adapter = TestAdapter()
# Method should accept content_id, content_type, suffix and return filename string
result = adapter.get_output_filename("BV1test", "video", "metadata.json")
assert isinstance(result, str)
assert "BV1test" in result
assert "video" in result
assert "metadata.json" in result