FakeClaude, test per area e renderer diviso in due file
- tests/FakeClaude: eseguibile finto 'claude' configurabile con variabili d'ambiente (registro di argomenti/cwd/stdin, output, exit code, ritardo), con le prove FK-01…FK-05. - Test organizzati per livello (Gui/, Process/, Support/) e struttura descritta in TESTING.md. - MarkdownView: la parte sulle immagini passa in MarkdownView.Images.cs (partial), senza cambiare il comportamento. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
51993dd0c8
commit
5870de6fda
14 files changed
+292
-119
No files matched your search
File renamed without changes.
@@ -0,0 +1,89 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace AgentWikiUi.Tests;
|
||||
|
||||
/// <summary>Il doppio di test di <c>claude</c> (docs/TESTING.md → FakeClaude, FK-01…FK-05).</summary>
|
||||
[Trait("Category", "Process")]
|
||||
public sealed class FakeClaudeTests : IDisposable
|
||||
{
|
||||
readonly string dir = Directory.CreateTempSubdirectory("awui-fake-").FullName;
|
||||
|
||||
public void Dispose() => Directory.Delete(dir, true);
|
||||
|
||||
string LogPath => Path.Combine(dir, "log.jsonl");
|
||||
|
||||
Process Start(IEnumerable<string> args, Dictionary<string, string>? env = null, string? cwd = null)
|
||||
{
|
||||
var psi = new ProcessStartInfo(FakeClaudePath.Exe)
|
||||
{
|
||||
UseShellExecute = false, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true,
|
||||
WorkingDirectory = cwd ?? dir,
|
||||
};
|
||||
foreach (var a in args) psi.ArgumentList.Add(a);
|
||||
psi.Environment["FAKE_CLAUDE_LOG"] = LogPath;
|
||||
foreach (var (k, v) in env ?? []) psi.Environment[k] = v;
|
||||
return Process.Start(psi)!;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Registra_argomenti_cwd_e_stdin()
|
||||
{
|
||||
var cwd = Directory.CreateDirectory(Path.Combine(dir, "lavoro")).FullName;
|
||||
using var p = Start(["-p", "dì \"ciao\" a tutti", "--model", "m"], cwd: cwd);
|
||||
p.StandardInput.Write("dati da stdin");
|
||||
p.StandardInput.Close();
|
||||
Assert.True(p.WaitForExit(10_000));
|
||||
|
||||
using var line = JsonDocument.Parse(File.ReadAllLines(LogPath).Single());
|
||||
var r = line.RootElement;
|
||||
Assert.Equal(["-p", "dì \"ciao\" a tutti", "--model", "m"], r.GetProperty("args").EnumerateArray().Select(a => a.GetString()));
|
||||
Assert.Equal(cwd, r.GetProperty("cwd").GetString());
|
||||
Assert.Equal("dati da stdin", r.GetProperty("stdin").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Output_e_stderr_configurati()
|
||||
{
|
||||
using var p = Start([], new() { ["FAKE_CLAUDE_OUT"] = "risposta", ["FAKE_CLAUDE_ERR"] = "avviso" });
|
||||
p.StandardInput.Close();
|
||||
Assert.Equal("risposta", p.StandardOutput.ReadToEnd());
|
||||
Assert.Equal("avviso", p.StandardError.ReadToEnd());
|
||||
Assert.True(p.WaitForExit(10_000));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, 0)]
|
||||
[InlineData("3", 3)]
|
||||
[InlineData("127", 127)]
|
||||
public void ExitCode_configurato(string? configured, int expected)
|
||||
{
|
||||
using var p = Start([], configured is null ? null : new() { ["FAKE_CLAUDE_EXIT"] = configured });
|
||||
p.StandardInput.Close();
|
||||
Assert.True(p.WaitForExit(10_000));
|
||||
Assert.Equal(expected, p.ExitCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ritardo_configurato()
|
||||
{
|
||||
using var p = Start([], new() { ["FAKE_CLAUDE_DELAY_MS"] = "600" });
|
||||
var sw = Stopwatch.StartNew();
|
||||
p.StandardInput.Close();
|
||||
Assert.True(p.WaitForExit(10_000));
|
||||
Assert.True(sw.ElapsedMilliseconds >= 500, $"terminato dopo {sw.ElapsedMilliseconds} ms");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Attende_la_chiusura_di_stdin()
|
||||
{
|
||||
using var p = Start([]);
|
||||
try
|
||||
{
|
||||
Assert.False(p.WaitForExit(700), "il processo è terminato con stdin ancora aperto");
|
||||
p.StandardInput.Close();
|
||||
Assert.True(p.WaitForExit(10_000));
|
||||
}
|
||||
finally { if (!p.HasExited) p.Kill(); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace AgentWikiUi.Tests;
|
||||
|
||||
/// <summary>Percorso del <c>claude</c> finto compilato (tests/FakeClaude), nella stessa configurazione dei test.</summary>
|
||||
static class FakeClaudePath
|
||||
{
|
||||
public static string Exe
|
||||
{
|
||||
get
|
||||
{
|
||||
// …/tests/agent-wiki-ui.Tests/bin/<config>/net10.0/
|
||||
var tfm = new DirectoryInfo(AppContext.BaseDirectory.TrimEnd(Path.DirectorySeparatorChar));
|
||||
var config = tfm.Parent!;
|
||||
var testsRoot = config.Parent!.Parent!.Parent!;
|
||||
return Path.Combine(testsRoot.FullName, "FakeClaude", "bin", config.Name, tfm.Name, OperatingSystem.IsWindows() ? "claude.exe" : "claude");
|
||||
}
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
@@ -21,6 +21,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../src/agent-wiki-ui/agent-wiki-ui.csproj" />
|
||||
<!-- solo compilato (non referenziato): i test avviano l'eseguibile -->
|
||||
<ProjectReference Include="../FakeClaude/FakeClaude.csproj" ReferenceOutputAssembly="false" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in new issue
Block a user