How to test ECAssistant-based agents at three levels — unit, user-experience, and full E2E — using ECAssistant.TestSupport (the same harness that tests ECAssistant itself).
The fake engine feeds queued decisions; everything else (orchestrator, tools, permissions) is the real product code.
var engine = new MockEngine(
cycleResponses: new[]
{
MockEngine.ToolCall("EShellAgent", new { command = "echo hello" }),
MockEngine.Answer("done — echoed hello")
},
config: new AppConfig());
var runner = new TestRunner(engine, workingDir: tempDir);
var result = await runner.RunAsync(TestScenario.Create("shell echo"));
Assert.True(result.Passed);Fast enough to run thousands; no model download, no GPU, no server.
The user doesn't see engine internals — they see the transcript. This harness drives AgentSession.Prompt (the real entry point), captures every visible line, answers approval prompts like a user, and registers the real tool set:
var harness = new UserExperienceHarness(serverUrl, config);
var (session, dir) = await harness.CreateAsync();
await session.Prompt("Create a file named notes.md containing 'journey marker 42'");
Assert.Contains("notes.md", harness.VisibleTranscript); // what the user saw
Assert.Equal("journey marker 42",
File.ReadAllText(Path.Combine(dir, "notes.md"))); // what the tool didThe full feature matrix against a live ECAssistantLLM server. Environment-gated — silently skipped when unset, so CI without secrets stays green.
# LOCAL SMALL — small local model, tier "small" (default qwen35-4b)
export ECA_E2E_SERVER=http://localhost:48321
export ECA_E2E_MODEL=qwen35-4b
# REMOTE LARGE — hosted large model, tier "large"
export ECA_E2E_REMOTE_ENDPOINT=https://ollama.com/v1
export ECA_E2E_REMOTE_MODEL=glm-5.3-flash:cloud
export ECA_E2E_REMOTE_KEYFILE=~/.secrets/ollama.key
export EcaUseProjectRefs=true
dotnet test --filter "FullyQualifiedName~JourneySuiteE2E"Handy knobs: ECA_JOURNEY_DEBUG=1 (per-turn transcripts + context snapshots), prepareWorkingDir (isolate file access per test).
- Local = small model (
qwen35-4b): validates scaffolding, strict recipes, permission flow under tight sampling. - Remote = large model (
glm-5.3-flash:cloud): validates slim profile, dataflow chains, longer reasoning. - Run BOTH before releases — the tiers exercise different harness paths by design.
- Targeted test runs only during interactive work:
--filterto one class. Full suites are for release checkpoints. - Kill leftover server processes after E2E:
pkill -f "ECAssistant.LLM.dll". - The server binds
localhost(IPv6) — usehttp://localhost:PORT, not127.0.0.1. - The harness is test-suites-only: never reference
ECAssistant.TestSupportfrom runtime projects.
- Harness reference: TestSupport README
- Journey suite source: JourneySuiteE2E.cs
- Agent lifecycle · Getting started