Testfundament aufbauen und Bestandsaufnahme dokumentieren
IChatCompletionClient aus OpenRouterClient extrahiert, damit AgentEngine und ContextCompactor ohne echte API-Aufrufe testbar sind. Neues Testprojekt tests/ClawdDotNet.Core.Tests (xUnit, Shouldly, NSubstitute, FsCheck) mit: - FakeChatClient (programmierbare Antwortfolgen, Deep-Copy der Requests) - ContextInvariants (prueft die API-Regeln fuer tool_call-Paarung) - Conversation-Builder fuer gueltige Testkonversationen - 26 Tests: Compaction, LoopGuard, 2 Property-Tests 10 Tests sind bewusst rot — sie reproduzieren die Bugs B1, B3 und B14 aus der Bestandsaufnahme und werden mit den Fixes gruen. Ausserdem: fehlende Tool-Projekte in slnx ergaenzt, Test-Pakete im packageSourceMapping der NuGet.Config eingetragen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
92e50d3ac4
commit
667cecce25
@@ -0,0 +1,68 @@
|
||||
using ClawdDotNet.Core.Api.Models;
|
||||
|
||||
namespace ClawdDotNet.Core.Tests.Infrastructure;
|
||||
|
||||
/// <summary>
|
||||
/// Baut gültige Nachrichtenfolgen für Tests — lesbar und garantiert API-konform.
|
||||
/// </summary>
|
||||
internal sealed class Conversation
|
||||
{
|
||||
private readonly List<ChatMessage> _messages = new();
|
||||
private int _callCounter;
|
||||
|
||||
public static Conversation Start(string? systemPrompt = "Du bist ein Testagent.")
|
||||
{
|
||||
var c = new Conversation();
|
||||
if (!string.IsNullOrEmpty(systemPrompt))
|
||||
c._messages.Add(ChatMessage.System(systemPrompt));
|
||||
return c;
|
||||
}
|
||||
|
||||
public Conversation User(string text)
|
||||
{
|
||||
_messages.Add(ChatMessage.User(text));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Conversation Assistant(string text)
|
||||
{
|
||||
_messages.Add(ChatMessage.Assistant(text));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fügt einen vollständigen Tool-Zyklus hinzu: assistant mit N tool_calls,
|
||||
/// gefolgt von genau N passenden tool-Antworten.
|
||||
/// </summary>
|
||||
public Conversation ToolCycle(int count = 1, int resultLength = 50, string toolName = "TestTool")
|
||||
{
|
||||
var calls = new List<ToolCall>();
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
calls.Add(new ToolCall
|
||||
{
|
||||
Id = $"call_{++_callCounter}",
|
||||
Type = "function",
|
||||
Function = new ToolCallFunction { Name = toolName, Arguments = """{"action":"test"}""" }
|
||||
});
|
||||
}
|
||||
|
||||
_messages.Add(ChatMessage.AssistantWithToolCalls(calls));
|
||||
foreach (var call in calls)
|
||||
_messages.Add(ChatMessage.ToolResponse(call.Id, new string('x', resultLength)));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>Wiederholt ein Muster aus User-Nachricht und Tool-Zyklus.</summary>
|
||||
public Conversation Repeat(int times, int toolCallsPerCycle = 1, int resultLength = 50)
|
||||
{
|
||||
for (var i = 0; i < times; i++)
|
||||
User($"Anfrage {i}").ToolCycle(toolCallsPerCycle, resultLength).Assistant($"Antwort {i}");
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<ChatMessage> Build() => _messages;
|
||||
|
||||
public static implicit operator List<ChatMessage>(Conversation c) => c._messages;
|
||||
}
|
||||
Reference in New Issue
Block a user