chore: reorganize test files into domain-specific subdirectories under tests/
Split the monolithic test directory into three tiers (unit, api, e2e) with a path-mirroring directory structure. Added corresponding Makefile targets (test-unit, test-api, test-e2e) and updated all documentation references (CLAUDE.md, README.md, testing-cicd.html, testing-framework.html, testing-make.html) to reflect the new layout and naming conventions.
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
import httpx
|
||||
from devplacepy.services import news as news_mod
|
||||
from devplacepy.services import base as base_mod
|
||||
from devplacepy.services.news import (
|
||||
NewsService,
|
||||
_extract_grade,
|
||||
_get_ai_key,
|
||||
_get_article_images,
|
||||
)
|
||||
from devplacepy.database import get_table
|
||||
from devplacepy.utils import generate_uid
|
||||
from tests.conftest import run_async
|
||||
API_URL = "http://news.test/api"
|
||||
AI_URL = "http://ai.test/v1/chat"
|
||||
LINK_HIGH = "http://news.test/high"
|
||||
LINK_LOW = "http://news.test/low"
|
||||
class FakeResp_news_service:
|
||||
def __init__(self, json_data=None, text="", status=200):
|
||||
self._json = json_data
|
||||
self.text = text
|
||||
self.status_code = status
|
||||
|
||||
def raise_for_status(self):
|
||||
if self.status_code >= 400:
|
||||
raise httpx.HTTPError(f"status {self.status_code}")
|
||||
|
||||
def json(self):
|
||||
return self._json
|
||||
class FakeClient_news_service:
|
||||
def __init__(self, articles):
|
||||
self.articles = articles
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, *exc):
|
||||
return False
|
||||
|
||||
async def get(self, url, timeout=None):
|
||||
if url == API_URL:
|
||||
return FakeResp_news_service(json_data={"articles": self.articles})
|
||||
return FakeResp_news_service(text='<img src="http://img.test/a.png">')
|
||||
|
||||
async def post(self, url, json=None, headers=None, timeout=None):
|
||||
prompt = json["messages"][0]["content"]
|
||||
if "FailArticle" in prompt:
|
||||
return FakeResp_news_service(status=500, text="err")
|
||||
if "EmptyArticle" in prompt:
|
||||
return FakeResp_news_service(json_data={"choices": [{"message": {"content": ""}}]})
|
||||
if "BadArticle" in prompt:
|
||||
return FakeResp_news_service(
|
||||
json_data={"choices": [{"message": {"content": "no number"}}]}
|
||||
)
|
||||
grade = "9" if "HighArticle" in prompt else "3"
|
||||
return FakeResp_news_service(json_data={"choices": [{"message": {"content": grade}}]})
|
||||
class FailingApiClient(FakeClient_news_service):
|
||||
async def get(self, url, timeout=None):
|
||||
if url == API_URL:
|
||||
raise httpx.HTTPError("api down")
|
||||
return FakeResp_news_service(text="")
|
||||
def _settings_stub(threshold="7"):
|
||||
def fake_get_setting(key, default=None):
|
||||
return {
|
||||
"news_api_url": API_URL,
|
||||
"news_ai_url": AI_URL,
|
||||
"news_ai_model": "test-model",
|
||||
"news_grade_threshold": threshold,
|
||||
"news_ai_key": "",
|
||||
}.get(key, default)
|
||||
|
||||
return fake_get_setting
|
||||
|
||||
|
||||
def test_get_article_images_network_error_returns_empty():
|
||||
client = FakeClient_news_service([])
|
||||
|
||||
async def failing_get(url, timeout=None):
|
||||
raise httpx.HTTPError("down")
|
||||
|
||||
client.get = failing_get
|
||||
assert run_async(_get_article_images("http://news.test/page", client)) == []
|
||||
Reference in New Issue
Block a user