Files
qwenpaw/tests/unit/agents/test_prompt_sections.py
agent-radar 1a3a4ccde1
Creator App Tests / PR Spam Gate (push) Skipped
Frontend Tests / PR Spam Gate (push) Skipped
NPM Format (website & console) / PR Spam Gate (push) Skipped
Pre-commit Checks / PR Spam Gate (push) Skipped
QwenPaw Creator Plugin Release / check-version (push) Canceled after 0s
QwenPaw Creator Plugin Release / upload-oss (push) Canceled after 0s
Tests / PR Spam Gate (push) Skipped
CodeQL / CodeQL (python) (push) Canceled after 0s
CodeQL / CodeQL (typescript) (push) Canceled after 0s
Creator App Tests / Creator Backend Tests (push) Canceled after 0s
Creator App Tests / Creator UI Build & Tests (push) Canceled after 0s
E2E Smoke Tests / Playwright UI Smoke (push) Canceled after 0s
Frontend Tests / Detect console changes (push) Canceled after 0s
NPM Format (website & console) / website format check (push) Canceled after 0s
NPM Format (website & console) / console format check (push) Canceled after 0s
Pre-commit Checks / Pre-commit (push) Canceled after 0s
QwenPaw Data Plugin Release / check-version (push) Canceled after 0s
Tests / Detect code changes (push) Canceled after 0s
Frontend Tests / Vitest Unit Tests (push) Canceled after 0s
Frontend Tests / Frontend Summary (push) Canceled after 0s
QwenPaw Data Plugin Release / upload-oss (push) Canceled after 0s
Tests / Maintainer Approval (push) Canceled after 0s
Tests / Unit Tests - py3.11 - macos-latest (push) Canceled after 0s
Tests / Unit Tests - py3.11 - ubuntu-latest (push) Canceled after 0s
Tests / Unit Tests - py3.13 - ubuntu-latest (push) Canceled after 0s
Tests / Unit Tests - py3.11 - windows-latest (push) Canceled after 0s
Tests / Contract Tests - py3.11 - macos-latest (push) Canceled after 0s
Tests / Contract Tests - py3.11 - ubuntu-latest (push) Canceled after 0s
Tests / Contract Tests - py3.13 - ubuntu-latest (push) Canceled after 0s
Tests / Contract Tests - py3.11 - windows-latest (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - macos-latest - p0 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - macos-latest - p1 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - macos-latest - p2 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - ubuntu-latest - fallback (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - ubuntu-latest - p0 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - ubuntu-latest - p1 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - ubuntu-latest - p2 (push) Canceled after 0s
Tests / Integrated Tests - py3.13 - ubuntu-latest - p0 (push) Canceled after 0s
Tests / Integrated Tests - py3.13 - ubuntu-latest - p1 (push) Canceled after 0s
Tests / Integrated Tests - py3.13 - ubuntu-latest - p2 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - windows-latest - p0 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - windows-latest - p1 (push) Canceled after 0s
Tests / Integrated Tests - py3.11 - windows-latest - p2 (push) Canceled after 0s
Tests / Coverage Report (push) Canceled after 0s
Tests / Test Summary (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:01:50 +08:00

145 lines
3.9 KiB
Python

# -*- coding: utf-8 -*-
"""Tests for PromptBuilder and plugin prompt section registration."""
from __future__ import annotations
from unittest.mock import patch
import pytest
from qwenpaw.agents.prompt_builder import PromptBuilder
from qwenpaw.plugins.registry import PluginRegistry
class _FakeAgent:
"""Minimal stand-in providing only what providers may receive."""
def __init__(self, *, agent_id: str = "datapaw") -> None:
self._request_context = {"agent_id": agent_id}
@pytest.fixture(autouse=True)
def clean_prompt_sections():
"""Keep singleton registry state isolated for these tests."""
registry = PluginRegistry()
for plugin_id in ("test-a", "test-b", "broken-plugin"):
registry.unregister_plugin(plugin_id)
yield
for plugin_id in ("test-a", "test-b", "broken-plugin"):
registry.unregister_plugin(plugin_id)
def test_builder_orders_sections_after_host_anchor():
"""Plugin sections follow their declared host anchor."""
registry = PluginRegistry()
registry.register_prompt_section(
plugin_id="test-a",
name="plugin.master",
after="workspace",
agent_id="datapaw",
provider=lambda agent: "MASTER",
)
registry.register_prompt_section(
plugin_id="test-a",
name="plugin.env",
after="workspace",
agent_id="datapaw",
provider=lambda agent: "ENV",
)
builder = PromptBuilder(registry)
result = builder.build(
agent=_FakeAgent(),
agent_id="datapaw",
workspace="WORKSPACE",
multimodal="MULTIMODAL",
env_context="HOST_ENV",
)
assert result == (
"WORKSPACE\n\n" "MASTER\n\n" "ENV\n\n" "MULTIMODAL\n\n" "HOST_ENV"
)
def test_registry_rejects_invalid_anchor():
"""after must reference a valid host anchor."""
registry = PluginRegistry()
with pytest.raises(ValueError, match="must reference a host anchor"):
registry.register_prompt_section(
plugin_id="test-a",
name="plugin.bad",
after="nonexistent",
agent_id="datapaw",
provider=lambda agent: "X",
)
def test_builder_filters_by_agent_id():
"""agent_id limits which sections appear in the prompt."""
registry = PluginRegistry()
registry.register_prompt_section(
plugin_id="test-a",
name="plugin.datapaw",
after="workspace",
agent_id="datapaw",
provider=lambda agent: "DATAPAW",
)
registry.register_prompt_section(
plugin_id="test-b",
name="plugin.all",
after="workspace",
agent_id=None,
provider=lambda agent: "ALL",
)
builder = PromptBuilder(registry)
other = builder.build(
agent=_FakeAgent(agent_id="other"),
agent_id="other",
workspace="WORKSPACE",
)
assert other == "WORKSPACE\n\nALL"
registry.unregister_plugin("test-b")
datapaw = builder.build(
agent=_FakeAgent(),
agent_id="datapaw",
workspace="WORKSPACE",
)
assert datapaw == "WORKSPACE\n\nDATAPAW"
def test_builder_skips_empty_and_failed_providers():
"""Bad or empty providers do not break prompt assembly."""
registry = PluginRegistry()
registry.register_prompt_section(
plugin_id="test-a",
name="plugin.empty",
after="workspace",
agent_id="datapaw",
provider=lambda agent: "",
)
def _raise(_agent):
raise RuntimeError("boom")
registry.register_prompt_section(
plugin_id="broken-plugin",
name="plugin.broken",
after="workspace",
agent_id="datapaw",
provider=_raise,
)
with patch(
"qwenpaw.agents.prompt_builder.logger.exception",
) as log_exc:
result = PromptBuilder(registry).build(
agent=_FakeAgent(),
agent_id="datapaw",
workspace="WORKSPACE",
)
assert result == "WORKSPACE"
log_exc.assert_called_once()