fix(match): prioritize meaningful job terms

This commit is contained in:
cesnimda
2026-08-09 18:47:21 +02:00
parent f2d1963c61
commit da1aa8bb2a
5 changed files with 208 additions and 22 deletions
@@ -10,6 +10,84 @@ public sealed class JobCvMatchServiceTests
private static Dictionary<string, string> Sections(params (string Name, string Text)[] items)
=> items.ToDictionary(i => i.Name, i => i.Text, StringComparer.OrdinalIgnoreCase);
public static IEnumerable<object[]> QualityFixtures()
{
yield return new object[]
{
"Norwegian",
"Senior systemutvikler",
"Vi ser etter deg som har erfaring med C# og ASP.NET Core. Du vil designe skalerbare distribuerte systemer. Gode samarbeidsevner er en fordel.",
new[] { "C#", "ASP.NET Core", "designe skalerbare distribuerte systemer" },
new[] { "med", "til", "for", "som", "erfaring", "ser" },
};
yield return new object[]
{
"English",
"Cloud platform engineer",
"We need a candidate with experience in AWS and Terraform. You will lead incident response and operate distributed systems.",
new[] { "AWS", "Terraform", "incident response", "operate distributed systems" },
new[] { "the", "with", "experience", "candidate", "will" },
};
yield return new object[]
{
"Mixed Norwegian and English",
"DevOps-utvikler",
"Du vil jobbe med Node.js og CI/CD. Work closely with Azure DevOps and cross-functional product teams.",
new[] { "Node.js", "CI/CD", "Azure DevOps", "Collaboration" },
new[] { "og", "med", "with", "teams" },
};
yield return new object[]
{
"Short",
"Data developer",
"Python and SQL.",
new[] { "Python", "SQL" },
new[] { "and" },
};
yield return new object[]
{
"Noisy HTML",
"Frontend developer",
"<nav>Home Jobs Login</nav><script>trackingCookie('React')</script><main>Build accessible web applications with React and TypeScript.</main><footer>Cookie settings Privacy Terms</footer>",
new[] { "React", "TypeScript", "Build accessible web applications" },
new[] { "home", "jobs", "login", "cookie", "settings", "privacy", "terms", "trackingcookie" },
};
yield return new object[]
{
"Technology heavy",
"Platform developer",
"C++, C#, .NET, ASP.NET Core, Node.js, CI/CD, Azure DevOps and Kubernetes.",
new[] { "C++", "C#", ".NET", "ASP.NET Core", "Node.js", "CI/CD", "Azure DevOps", "Kubernetes" },
new[] { "and" },
};
yield return new object[]
{
"Repeated recruitment filler",
"Software engineer",
"Exciting opportunity for a passionate candidate. Great opportunity, strong experience required. We offer an exciting dynamic environment. Apply now. Build services using domain-driven design and Docker.",
new[] { "domain-driven design", "Docker" },
new[] { "exciting", "opportunity", "passionate", "candidate", "experience", "environment", "apply" },
};
}
[Theory]
[MemberData(nameof(QualityFixtures))]
public void Quality_fixtures_keep_useful_terms_and_suppress_noise(
string name,
string title,
string description,
string[] expected,
string[] excluded)
{
var result = _service.Evaluate(title, description, Sections(("Skills", "synthetic profile text")));
var terms = result.MatchedKeywords.Concat(result.MissingKeywords).ToList();
foreach (var term in expected)
Assert.True(terms.Contains(term, StringComparer.OrdinalIgnoreCase), $"{name}: expected '{term}' in [{string.Join(", ", terms)}]");
foreach (var term in excluded)
Assert.False(terms.Contains(term, StringComparer.OrdinalIgnoreCase), $"{name}: did not expect '{term}' in [{string.Join(", ", terms)}]");
}
[Fact]
public void Strong_overlap_scores_high_and_lists_matched_keywords()
{