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:
2026-06-13 14:32:33 +00:00
parent 014c4c6bb3
commit 43f4011005
268 changed files with 20634 additions and 9206 deletions
+56
View File
@@ -0,0 +1,56 @@
# retoor <retoor@molodetz.nl>
import json
from devplacepy.services.devii.agentic.loop import _run_tool_call
from tests.conftest import run_async
class _FakeDispatcher:
def __init__(self):
self.calls = []
async def dispatch(self, name, arguments):
self.calls.append((name, arguments))
return json.dumps({"status": "ok"})
def _run(call, dispatcher=None):
return json.loads(run_async(_run_tool_call(dispatcher, call)))
def test_truncated_arguments_reported_not_dispatched():
dispatcher = _FakeDispatcher()
call = {
"function": {
"name": "project_write_file",
"arguments": '{"path":"a.md","content":"# hi',
}
}
out = _run(call, dispatcher)
assert out["error"] == "tool_input_truncated"
assert "one write tool call per turn" in out["message"]
assert dispatcher.calls == []
def test_non_object_arguments_rejected():
dispatcher = _FakeDispatcher()
out = _run({"function": {"name": "x", "arguments": '"a string"'}}, dispatcher)
assert out["error"] == "tool_input_error"
assert dispatcher.calls == []
def test_valid_string_arguments_dispatched():
dispatcher = _FakeDispatcher()
out = _run({"function": {"name": "vote", "arguments": '{"value":1}'}}, dispatcher)
assert out["status"] == "ok"
assert dispatcher.calls == [("vote", {"value": 1})]
def test_valid_dict_arguments_dispatched():
dispatcher = _FakeDispatcher()
out = _run({"function": {"name": "vote", "arguments": {"value": -1}}}, dispatcher)
assert out["status"] == "ok"
assert dispatcher.calls == [("vote", {"value": -1})]
def test_missing_arguments_defaults_to_empty_object():
dispatcher = _FakeDispatcher()
out = _run({"function": {"name": "auth_status"}}, dispatcher)
assert out["status"] == "ok"
assert dispatcher.calls == [("auth_status", {})]
+177
View File
@@ -0,0 +1,177 @@
# retoor <retoor@molodetz.nl>
from datetime import datetime, timezone
from types import SimpleNamespace
from tests.conftest import BASE_URL
from devplacepy.database import get_table, set_setting
from devplacepy.utils import generate_uid
from devplacepy.services.devii.config import (
effective_daily_limit,
FIELD_USER_DAILY_USD,
FIELD_GUEST_DAILY_USD,
FIELD_ADMIN_DAILY_USD,
)
from devplacepy.services.devii.store import UsageLedger
LEDGER = "devii_usage_ledger"
def _now_iso_devii_quota():
return datetime.now(timezone.utc).isoformat()
def _seed_ledger(owner_kind, owner_id, cost, n=1):
table = get_table(LEDGER)
for _ in range(n):
table.insert(
{
"owner_kind": owner_kind,
"owner_id": owner_id,
"created_at": _now_iso_devii_quota(),
"cost_usd": cost,
}
)
def _ensure_devii():
from devplacepy.services.manager import service_manager
from devplacepy.services.devii import DeviiService
if service_manager.get_service("devii") is None:
service_manager.register(DeviiService())
return service_manager.get_service("devii")
def _make_user_devii_quota(role="Member"):
uid = generate_uid()
username = f"quota_{uid[-12:]}"
get_table("users").insert(
{
"uid": uid,
"username": username,
"email": f"{username}@t.dev",
"api_key": generate_uid(),
"role": role,
"is_active": True,
}
)
return uid, username
def test_effective_limit_resolver():
cfg = {
FIELD_USER_DAILY_USD: 1.0,
FIELD_GUEST_DAILY_USD: 0.05,
FIELD_ADMIN_DAILY_USD: 0.0,
}
assert effective_daily_limit(cfg, "user", False) == 1.0
assert effective_daily_limit(cfg, "guest", False) == 0.05
assert effective_daily_limit(cfg, "user", True) == 0.0
cfg[FIELD_ADMIN_DAILY_USD] = 5.0
assert effective_daily_limit(cfg, "user", True) == 5.0
def test_admin_exempt_by_default(local_db):
from devplacepy.routers.profile import _ai_quota
_ensure_devii()
set_setting("devii_user_daily_usd", "1.0")
set_setting("devii_admin_daily_usd", "0.0")
try:
uid, _ = _make_user_devii_quota()
_seed_ledger("user", uid, 5.0)
member_view = _ai_quota(uid, is_admin=False)
admin_view = _ai_quota(uid, is_admin=True)
assert member_view["used_pct"] == 100.0
assert admin_view["used_pct"] == 0.0
finally:
set_setting("devii_user_daily_usd", "1.0")
set_setting("devii_admin_daily_usd", "0.0")
def test_admin_limit_is_zero_by_default(local_db):
svc = _ensure_devii()
set_setting("devii_admin_daily_usd", "0.0")
try:
assert svc.daily_limit_for("user", True) == 0.0
assert svc.daily_limit_for("user", False) == 1.0
finally:
set_setting("devii_admin_daily_usd", "0.0")
def test_admin_cap_configurable(local_db):
from devplacepy.routers.profile import _ai_quota
_ensure_devii()
set_setting("devii_admin_daily_usd", "2.0")
try:
uid, _ = _make_user_devii_quota()
_seed_ledger("user", uid, 1.0)
quota = _ai_quota(uid, is_admin=True)
assert quota["used_pct"] == 50.0
finally:
set_setting("devii_admin_daily_usd", "0.0")
def test_guest_cap_configurable(local_db):
svc = _ensure_devii()
set_setting("devii_guest_daily_usd", "0.10")
try:
assert svc.daily_limit_for("guest") == 0.10
finally:
set_setting("devii_guest_daily_usd", "0.05")
def test_reset_single_owner(local_db):
ledger = UsageLedger()
uid, _ = _make_user_devii_quota()
_seed_ledger("user", uid, 0.5, n=3)
assert ledger.spent_24h("user", uid) == 1.5
removed = ledger.reset("user", uid)
assert removed == 3
assert ledger.spent_24h("user", uid) == 0.0
def test_reset_guests_only_leaves_users(local_db):
ledger = UsageLedger()
guest_id = f"guest-{generate_uid()[:8]}"
user_id, _ = _make_user_devii_quota()
_seed_ledger("guest", guest_id, 0.02, n=2)
_seed_ledger("user", user_id, 0.5, n=1)
ledger.reset_owner_kind("guest")
assert ledger.spent_24h("guest", guest_id) == 0.0
assert ledger.spent_24h("user", user_id) == 0.5
def test_reset_all(local_db):
ledger = UsageLedger()
guest_id = f"guest-{generate_uid()[:8]}"
user_id, _ = _make_user_devii_quota()
_seed_ledger("guest", guest_id, 0.02, n=2)
_seed_ledger("user", user_id, 0.5, n=2)
ledger.reset_all()
assert ledger.spent_24h("guest", guest_id) == 0.0
assert ledger.spent_24h("user", user_id) == 0.0
def test_cli_reset_quota_for_user(local_db):
from devplacepy.cli import cmd_devii_reset_quota
uid, username = _make_user_devii_quota()
_seed_ledger("user", uid, 0.5, n=2)
cmd_devii_reset_quota(SimpleNamespace(username=username, guests=False, all=False))
assert get_table(LEDGER).count(owner_kind="user", owner_id=uid) == 0
def test_cli_reset_quota_guests(local_db):
from devplacepy.cli import cmd_devii_reset_quota
guest_id = f"guest-{generate_uid()[:8]}"
user_id, _ = _make_user_devii_quota()
_seed_ledger("guest", guest_id, 0.02, n=2)
_seed_ledger("user", user_id, 0.5, n=1)
cmd_devii_reset_quota(SimpleNamespace(username=None, guests=True, all=False))
assert get_table(LEDGER).count(owner_kind="guest", owner_id=guest_id) == 0
assert get_table(LEDGER).count(owner_kind="user", owner_id=user_id) == 1
def test_cli_reset_quota_all(local_db):
from devplacepy.cli import cmd_devii_reset_quota
guest_id = f"guest-{generate_uid()[:8]}"
user_id, _ = _make_user_devii_quota()
_seed_ledger("guest", guest_id, 0.02, n=1)
_seed_ledger("user", user_id, 0.5, n=1)
cmd_devii_reset_quota(SimpleNamespace(username=None, guests=False, all=True))
assert get_table(LEDGER).count() == 0