Files
jobtrackingapp/JobTrackerApi.Tests/AiEvaluationFixtureTests.cs
T

76 lines
4.3 KiB
C#

using System.Text.Json;
using System.Text.RegularExpressions;
using Xunit;
namespace JobTrackerApi.Tests;
public sealed class AiEvaluationFixtureTests
{
private static readonly HashSet<string> RequiredCoverage = new(StringComparer.Ordinal)
{
"english-cv", "norwegian-cv", "mixed-language-cv", "english-job-advert",
"norwegian-job-advert", "noisy-job-advert", "technology-heavy-role", "sparse-role",
"email-classification", "follow-up-draft", "strategy-snapshot", "strict-json-response",
"malformed-adversarial-document", "prompt-injection-job", "prompt-injection-email",
"long-input", "empty-input", "invalid-input",
};
private static readonly HashSet<string> KnownTasks = new(StringComparer.Ordinal)
{
"DOC-EXTRACT", "CV-NORMALIZE", "CV-CLASSIFY", "PROFILE-EXTRACT", "PROFILE-DIFF",
"JOB-CLEAN", "JOB-SUMMARY", "JOB-MATCH", "STRATEGY", "CV-TAILOR",
"APPLICATION-DRAFT", "FOLLOWUP-DRAFT", "EMAIL-CLASSIFY", "RECRUITMENT-DETECT",
"INTERVIEW", "WRITING",
};
[Fact]
public void Synthetic_evaluation_set_is_complete_bounded_and_contains_no_real_contact_domain()
{
using var document = JsonDocument.Parse(File.ReadAllText(FixturePath()));
var root = document.RootElement;
Assert.Equal("1", root.GetProperty("version").GetString());
Assert.True(root.GetProperty("syntheticOnly").GetBoolean());
var cases = root.GetProperty("cases").EnumerateArray().ToList();
Assert.NotEmpty(cases);
Assert.Equal(cases.Count, cases.Select(item => item.GetProperty("id").GetString()).Distinct(StringComparer.Ordinal).Count());
var coverage = cases.SelectMany(item => item.GetProperty("coverage").EnumerateArray())
.Select(item => item.GetString()).Where(item => item is not null).Cast<string>().ToHashSet(StringComparer.Ordinal);
Assert.Empty(RequiredCoverage.Except(coverage));
var tasks = cases.SelectMany(item => item.GetProperty("tasks").EnumerateArray())
.Select(item => item.GetString()).Where(item => item is not null).Cast<string>().ToHashSet(StringComparer.Ordinal);
Assert.Empty(tasks.Except(KnownTasks));
Assert.Empty(KnownTasks.Except(tasks));
var emailPattern = new Regex(@"[A-Z0-9._%+-]+@([A-Z0-9.-]*[A-Z0-9])", RegexOptions.IgnoreCase);
foreach (var item in cases)
{
var input = item.GetProperty("input");
var text = input.GetProperty("text").GetString() ?? string.Empty;
var repeat = input.GetProperty("repeat").GetInt32();
Assert.InRange(repeat, 1, 100);
Assert.DoesNotContain("Connor Babbington", text, StringComparison.OrdinalIgnoreCase);
Assert.DoesNotContain("F:\\Documents", text, StringComparison.OrdinalIgnoreCase);
Assert.All(emailPattern.Matches(text).Cast<Match>(), match => Assert.EndsWith(".invalid", match.Groups[1].Value, StringComparison.OrdinalIgnoreCase));
Assert.True(text.Length * repeat <= 20_000, $"{item.GetProperty("id").GetString()} exceeds the current prompt boundary.");
var expected = item.GetProperty("expected");
Assert.True(expected.GetProperty("mustContain").GetArrayLength() > 0);
if (item.GetProperty("coverage").EnumerateArray().Any(value => value.GetString()?.StartsWith("prompt-injection", StringComparison.Ordinal) == true))
Assert.Contains(expected.GetProperty("mustNotContain").EnumerateArray(), value => value.GetString() == "SYSTEM_OVERRIDE_ACCEPTED");
}
var longCase = cases.Single(item => item.GetProperty("id").GetString() == "long-job-01");
var longInput = longCase.GetProperty("input");
Assert.True((longInput.GetProperty("text").GetString()?.Length ?? 0) * longInput.GetProperty("repeat").GetInt32() >= 10_000);
var strictJson = cases.Single(item => item.GetProperty("id").GetString() == "strict-json-01").GetProperty("expected");
Assert.Equal("json", strictJson.GetProperty("format").GetString());
Assert.True(strictJson.GetProperty("requiredKeys").GetArrayLength() >= 4);
}
private static string FixturePath() => Path.GetFullPath(Path.Combine(
AppContext.BaseDirectory, "..", "..", "..", "Fixtures", "AiEvaluation", "cases.json"));
}