Skip to content

TUnit Fixes & Improvements - #677

Merged
Evangelink merged 5 commits into
dotnet:mainfrom
thomhurst:feature/tunit-updates
May 28, 2026
Merged

TUnit Fixes & Improvements#677
Evangelink merged 5 commits into
dotnet:mainfrom
thomhurst:feature/tunit-updates

Conversation

@thomhurst

Copy link
Copy Markdown
Contributor

Some docs for TUnit was either wrong, or missing in comparison tables, so these have been fixed.

Also updated the example project to a modern version.

Also added some other useful bits to know too.

thomhurst added 3 commits May 19, 2026 20:09
Cross-referenced against tunit.dev/llms.txt and the official attributes
comparison page. Corrects the test class marker (TUnit is convention-based,
not [ClassDataSource]), and fills in the previously-missing TUnit rows for
the assertion APIs, setup/teardown methods, exception-handling examples,
and integration test category marker.
The Type row's TUnit cell now uses IsAssignableTo<T>() to match the
assignable-type semantics of the MSTest/xUnit/NUnit equivalents, with a
note pointing at IsTypeOf<T>() for exact-type checks. The Skip row now
documents that [Skip] also applies at class and assembly scope and that
Skip.Test("reason") handles dynamic in-test skipping.

Verified against the TUnit migration guides and the type-assertions docs.
Copilot AI review requested due to automatic review settings May 19, 2026 19:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the .NET test framework reference material to correct/expand TUnit guidance (detection markers, assertion APIs, skipping, and lifecycle hooks), and modernizes the TUnit test fixture project used by the dotnet-test run-tests scenarios.

Changes:

  • Update the TUnit fixture project to target net10.0 and use a newer TUnit package version.
  • Expand dotnet-test-frameworks reference tables and examples to include TUnit assertion APIs, skipping behavior, and setup/teardown hooks.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
tests/dotnet-test/run-tests/fixtures/mtp-tunit/TestProject.csproj Updates the TUnit fixture to net10.0 and bumps the TUnit package version.
plugins/dotnet-test/skills/dotnet-test-frameworks/SKILL.md Fixes/extends TUnit documentation in framework reference tables and adds TUnit-specific guidance/examples.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread plugins/dotnet-test/skills/dotnet-test-frameworks/SKILL.md Outdated
The Boolean, Null, Exception, and Type rows in the assertions table
previously used a `await Assert.That(x).IsTrue()` / `.IsFalse()` shorthand
for the alternative form. A reader copy-pasting just the second fragment
would end up with an un-awaited assertion that silently passes — which
contradicts the note immediately below the table about always awaiting.
Each alternative is now a complete, independently copy-pasteable expression.

Addresses the inline review on dotnet#677.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@Evangelink

Copy link
Copy Markdown
Member

Thanks @thomhurst! Let me see if we need some extra work on eval for the newly added info

@Evangelink

Copy link
Copy Markdown
Member

/evaluate

github-actions Bot added a commit that referenced this pull request May 20, 2026
github-actions Bot added a commit that referenced this pull request May 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Skill Validation Results

Skill Scenario Quality Skills Loaded Overfit Verdict
dotnet-test-frameworks Cross-framework assertion equivalence mapping 5.0/5 → 5.0/5 ℹ️ not activated (expected) ✅ 0.10 [1]
dotnet-test-frameworks Identify TUnit framework and its unique attributes 5.0/5 → 5.0/5 ✅ dotnet-test-frameworks; tools: report_intent, skill / ℹ️ not activated (expected) ✅ 0.10 [2]
dotnet-test-frameworks Replace try-catch with framework-native exception assertions 5.0/5 → 5.0/5 ℹ️ not activated (expected) ✅ 0.10 [3]
dotnet-test-frameworks Skip annotations across all four frameworks 5.0/5 → 5.0/5 ✅ dotnet-test-frameworks; tools: report_intent, skill / ℹ️ not activated (expected) ✅ 0.10 [4]
dotnet-test-frameworks Convert NUnit lifecycle methods to xUnit equivalents 5.0/5 → 5.0/5 ℹ️ not activated (expected) ✅ 0.10 [5]
dotnet-test-frameworks Identify integration tests by markers and code patterns 5.0/5 → 5.0/5 ℹ️ not activated (expected) ✅ 0.10 [6]
run-tests Run tests in a VSTest MSTest project 4.0/5 → 3.3/5 🔴 ✅ run-tests; tools: skill, glob [7]
run-tests Run tests with trx reporting on MTP project (SDK 9) 2.0/5 → 4.7/5 🟢 ✅ run-tests; tools: skill / ✅ run-tests; tools: skill, glob, edit [8]
run-tests Run tests with blame-hang on MTP project (SDK 10) 2.3/5 → 3.0/5 🟢 ✅ run-tests; tools: skill, bash / ✅ run-tests; tools: skill, glob, bash, edit [9]
run-tests Run tests in a multi-TFM project targeting a specific framework 4.3/5 → 3.0/5 ⏰ 🔴 ✅ run-tests; tools: skill, view, glob / ⚠️ NOT ACTIVATED [10]
run-tests Filter MSTest tests by category on VSTest 3.0/5 → 5.0/5 🟢 ✅ run-tests; tools: report_intent, skill, view, glob, bash / ✅ run-tests; tools: report_intent, view, skill, bash
run-tests Filter NUnit tests by class name on VSTest 2.7/5 → 5.0/5 🟢 ✅ run-tests; tools: report_intent, skill, view, bash / ✅ run-tests; tools: report_intent, skill, view, bash, glob
run-tests Filter xUnit v3 tests by class on MTP 1.0/5 → 5.0/5 🟢 ✅ run-tests; tools: report_intent, skill, view, bash / ✅ run-tests; tools: report_intent, skill, view
run-tests Filter xUnit v3 tests by trait on MTP 1.0/5 → 5.0/5 🟢 ✅ run-tests; tools: skill, bash, glob / ✅ run-tests; tools: skill, bash
run-tests Filter xUnit v3 tests by class pattern and trait using query filter language 1.0/5 → 1.0/5 ✅ run-tests; tools: skill, bash, glob / ✅ run-tests; filter-syntax; tools: skill, bash [11]
run-tests Filter TUnit tests by class using treenode-filter 2.7/5 → 3.7/5 🟢 ✅ run-tests; tools: skill, bash [12]
run-tests Combine multiple filter criteria on VSTest MSTest 4.0/5 → 5.0/5 🟢 ✅ run-tests; tools: skill, bash, glob / ✅ run-tests; tools: skill, glob [13]
run-tests MTP project on SDK 9 must use -- separator for args 1.3/5 → 3.7/5 🟢 ✅ run-tests; tools: skill, bash, glob / ✅ run-tests; tools: skill, bash, read_bash, glob [14]
run-tests MTP project on SDK 10 passes args directly 2.0/5 → 3.7/5 🟢 ✅ run-tests; tools: skill, glob, edit / ✅ run-tests; tools: skill, edit [15]
run-tests Detect test platform from Directory.Build.props 2.7/5 → 1.0/5 🔴 ✅ run-tests; tools: skill [16]
run-tests Negative test: do not use MTP syntax for a VSTest project 4.0/5 → 1.0/5 🔴 ✅ run-tests; tools: skill, view, glob

[1] (Plugin) Quality unchanged but weighted score is -2.6% due to: tokens (12931 → 17866), time (11.9s → 15.1s)
[2] (Isolated) Quality unchanged but weighted score is -2.5% due to: tokens (12973 → 28614), tool calls (0 → 2)
[3] (Plugin) Quality unchanged but weighted score is -2.3% due to: tokens (13199 → 18148)
[4] ⚠️ High run-to-run variance (CV=63%) — consider re-running with --runs 5. (Isolated) Quality unchanged but weighted score is -6.7% due to: tokens (12786 → 23136), tool calls (0 → 1)
[5] ⚠️ High run-to-run variance (CV=186%) — consider re-running with --runs 5
[6] (Plugin) Quality unchanged but weighted score is -1.8% due to: tokens (13236 → 18192)
[7] ⚠️ High run-to-run variance (CV=253%) — consider re-running with --runs 5
[8] ⚠️ High run-to-run variance (CV=55%) — consider re-running with --runs 5
[9] ⚠️ High run-to-run variance (CV=1566%) — consider re-running with --runs 5
[10] ⚠️ High run-to-run variance (CV=141%) — consider re-running with --runs 5
[11] ⚠️ High run-to-run variance (CV=208%) — consider re-running with --runs 5
[12] ⚠️ High run-to-run variance (CV=66%) — consider re-running with --runs 5
[13] ⚠️ High run-to-run variance (CV=177%) — consider re-running with --runs 5
[14] ⚠️ High run-to-run variance (CV=119%) — consider re-running with --runs 5
[15] ⚠️ High run-to-run variance (CV=235%) — consider re-running with --runs 5. (Plugin) Quality improved but weighted score is -33.0% due to: quality, judgment, tokens (35267 → 473632), tool calls (6 → 21), time (39.2s → 182.1s)
[16] ⚠️ High run-to-run variance (CV=65%) — consider re-running with --runs 5

timeout — run(s) hit the (120s, 420s) scenario timeout limit; scoring may be impacted by aborting model execution before it could produce its full output (increase via timeout in eval.yaml)

Model: claude-opus-4.6 | Judge: claude-opus-4.6

🔍 Full Results - additional metrics and failure investigation steps

▶ Sessions Visualisation -- interactive replay of all evaluation sessions

@Evangelink

Copy link
Copy Markdown
Member

@thomhurst do you mind adding some evals (copilot is good at helping) to validate that the TUnit instructions are actually helping LLM?

Evangelink added a commit that referenced this pull request May 28, 2026
* Add TUnit-focused eval scenarios for dotnet-test-frameworks

Adds 5 new evaluation scenarios and tightens 2 existing scenarios to
exercise the expanded TUnit coverage in dotnet-test-frameworks/SKILL.md
(see #677).

New scenarios:
- Convert cross-framework assertions to TUnit syntax (await / IsEqualTo /
  IsTrue / IsNull / IsAssignableTo / Contains / Throws<T>)
- Diagnose silently-passing TUnit test with missing await (debugging
  mystery framed without naming the pitfall)
- Refactor TUnit try/catch to native exception assertion (Throws<T>()
  / ThrowsExactly<T>() / WithMessage)
- TUnit lifecycle hooks at test / class / assembly / session scope
- TUnit skip mechanisms — attribute, assembly-wide [assembly: Skip],
  and dynamic Skip.Test(...)

Updated scenarios:
- Identify TUnit framework: rubric now distinguishes [ClassDataSource]
  as a fixture/data source rather than a class marker (TUnit classes
  are convention-based, like xUnit)
- Identify integration tests: adds a TUnit Project D using live
  SqlConnection and requires recommending [Category("Integration")] for
  TUnit

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Mirror TUnit eval scenarios into Vally spec

Apply the same updated and new scenarios as in eval.yaml to the parallel

eval.vally.yaml so both pipelines exercise the new TUnit-focused checks.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Amaury Levé <amauryleve@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

Copy link
Copy Markdown
Member

/evaluate

github-actions Bot added a commit that referenced this pull request May 28, 2026
github-actions Bot added a commit that referenced this pull request May 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Skill Validation Results

Skill Scenario Quality Skills Loaded Overfit Verdict
dotnet-test-frameworks Cross-framework assertion equivalence mapping 5.0/5 → 5.0/5 ℹ️ not activated (expected) ✅ 0.09 [1]
dotnet-test-frameworks Identify TUnit framework and its unique attributes 5.0/5 → 5.0/5 ✅ dotnet-test-frameworks; tools: report_intent, skill / ℹ️ not activated (expected) ✅ 0.09 [2]
dotnet-test-frameworks Replace try-catch with framework-native exception assertions 5.0/5 → 5.0/5 ℹ️ not activated (expected) ✅ 0.09 [3]
dotnet-test-frameworks Skip annotations across all four frameworks 5.0/5 → 5.0/5 ✅ dotnet-test-frameworks; tools: report_intent, skill / ℹ️ not activated (expected) ✅ 0.09 [4]
dotnet-test-frameworks Convert NUnit lifecycle methods to xUnit equivalents 5.0/5 → 5.0/5 ℹ️ not activated (expected) ✅ 0.09
dotnet-test-frameworks Identify integration tests by markers and code patterns 5.0/5 → 5.0/5 ℹ️ not activated (expected) ✅ 0.09 [5]
dotnet-test-frameworks Convert cross-framework assertions to TUnit syntax 1.7/5 → 5.0/5 🟢 ✅ dotnet-test-frameworks; tools: report_intent, skill / ℹ️ not activated (expected) ✅ 0.09 [6]
dotnet-test-frameworks Diagnose silently-passing TUnit test with missing await 4.7/5 → 4.7/5 ✅ dotnet-test-frameworks; tools: report_intent, skill / ℹ️ not activated (expected) ✅ 0.09 [7]
dotnet-test-frameworks Refactor TUnit try/catch to native exception assertion 3.0/5 → 3.3/5 🟢 ℹ️ not activated (expected) ✅ 0.09 [8]
dotnet-test-frameworks TUnit lifecycle hooks at test, class, assembly, and session scope 4.0/5 → 5.0/5 🟢 ✅ dotnet-test-frameworks; tools: report_intent, skill / ℹ️ not activated (expected) ✅ 0.09 [9]
dotnet-test-frameworks TUnit skip mechanisms — attribute, assembly-wide, and dynamic 3.0/5 → 5.0/5 🟢 ✅ dotnet-test-frameworks; tools: report_intent, skill / ℹ️ not activated (expected) ✅ 0.09 [10]
run-tests Run tests in a VSTest MSTest project 4.0/5 → 4.7/5 🟢 ✅ run-tests; tools: skill ✅ 0.16 [11]
run-tests Run tests with trx reporting on MTP project (SDK 9) 2.3/5 → 3.7/5 🟢 ✅ run-tests; tools: skill, edit ✅ 0.16 [12]
run-tests Run tests with blame-hang on MTP project (SDK 10) 2.0/5 → 3.7/5 🟢 ✅ run-tests; tools: skill, bash, edit / ✅ run-tests; tools: skill ✅ 0.16
run-tests Run tests on a specific TFM with TRX in a multi-TFM MTP project (SDK 9) 5.0/5 → 4.7/5 🔴 ✅ run-tests; tools: skill, bash, edit / ✅ run-tests; tools: skill ✅ 0.16 [13]
run-tests Filter MSTest tests by category on VSTest 5.0/5 → 5.0/5 ⚠️ NOT ACTIVATED ✅ 0.16 [14]
run-tests Filter NUnit tests by class name on VSTest 3.0/5 → 5.0/5 🟢 ✅ run-tests; tools: skill, view, bash / ✅ run-tests; tools: skill, view ✅ 0.16
run-tests Filter xUnit v3 tests by class on MTP 1.0/5 → 5.0/5 🟢 ✅ run-tests; tools: skill, view ✅ 0.16
run-tests Filter xUnit v3 tests by trait on MTP 1.0/5 → 5.0/5 🟢 ✅ run-tests; tools: skill, view ✅ 0.16 [15]
run-tests Filter xUnit v3 tests by class pattern and trait using query filter language 1.0/5 → 1.0/5 ✅ run-tests; tools: report_intent, skill, view / ⚠️ NOT ACTIVATED ✅ 0.16 [16]
run-tests Filter TUnit tests by class using treenode-filter 3.0/5 → 3.7/5 🟢 ✅ run-tests; tools: skill, bash / ⚠️ NOT ACTIVATED ✅ 0.16 [17]
run-tests Combine multiple filter criteria on VSTest MSTest 3.7/5 → 5.0/5 🟢 ✅ run-tests; tools: skill, bash, report_intent, view / ✅ run-tests; tools: skill, report_intent, view ✅ 0.16 [18]
run-tests MTP project on SDK 9 must use -- separator for args 2.0/5 → 5.0/5 🟢 ✅ run-tests; tools: skill, bash / ✅ run-tests; tools: skill, edit, bash ✅ 0.16
run-tests MTP project on SDK 10 passes args directly 3.0/5 → 3.3/5 ⏰ 🟢 ✅ run-tests; tools: skill ✅ 0.16
run-tests Detect test platform from Directory.Build.props 2.7/5 → 2.0/5 🔴 ✅ run-tests; tools: skill / ⚠️ NOT ACTIVATED ✅ 0.16 [19]
run-tests Negative test: do not use MTP syntax for a VSTest project 4.3/5 → 5.0/5 🟢 ✅ run-tests; tools: skill, view, glob / ✅ run-tests; tools: skill, view ✅ 0.16 [20]

[1] ⚠️ High run-to-run variance (CV=59%) — consider re-running with --runs 5. (Plugin) Quality unchanged but weighted score is -2.3% due to: tokens (12938 → 17579), time (14.0s → 16.9s)
[2] ⚠️ High run-to-run variance (CV=77%) — consider re-running with --runs 5. (Isolated) Quality unchanged but weighted score is -17.3% due to: judgment, tokens (13152 → 28677), tool calls (0 → 2)
[3] ⚠️ High run-to-run variance (CV=54%) — consider re-running with --runs 5. (Plugin) Quality unchanged but weighted score is -2.1% due to: tokens (13190 → 17851)
[4] ⚠️ High run-to-run variance (CV=103%) — consider re-running with --runs 5. (Isolated) Quality unchanged but weighted score is -6.7% due to: tokens (12780 → 23179), tool calls (0 → 1)
[5] (Plugin) Quality unchanged but weighted score is -2.0% due to: tokens (13428 → 18080)
[6] ⚠️ High run-to-run variance (CV=177%) — consider re-running with --runs 5. (Plugin) Quality unchanged but weighted score is -9.0% due to: tokens (12845 → 29124), tool calls (0 → 1), time (6.5s → 10.3s)
[7] ⚠️ High run-to-run variance (CV=100%) — consider re-running with --runs 5. (Isolated) Quality unchanged but weighted score is -20.5% due to: judgment, quality, tool calls (0 → 1), tokens (12884 → 18199), time (9.1s → 11.7s)
[8] ⚠️ High run-to-run variance (CV=415%) — consider re-running with --runs 5
[9] ⚠️ High run-to-run variance (CV=231%) — consider re-running with --runs 5
[10] ⚠️ High run-to-run variance (CV=54%) — consider re-running with --runs 5
[11] ⚠️ High run-to-run variance (CV=248%) — consider re-running with --runs 5
[12] ⚠️ High run-to-run variance (CV=57%) — consider re-running with --runs 5
[13] (Plugin) Quality unchanged but weighted score is -2.9% due to: tokens (25697 → 43949), time (18.6s → 28.0s), tool calls (2 → 3)
[14] (Plugin) Quality unchanged but weighted score is -3.9% due to: tokens (25637 → 35361), tool calls (2 → 3), time (15.9s → 20.5s)
[15] ⚠️ High run-to-run variance (CV=213%) — consider re-running with --runs 5. (Plugin) Quality improved but weighted score is -2.8% due to: tokens (35768 → 56535)
[16] ⚠️ High run-to-run variance (CV=232%) — consider re-running with --runs 5
[17] ⚠️ High run-to-run variance (CV=457%) — consider re-running with --runs 5. (Plugin) Quality improved but weighted score is -49.2% due to: judgment, quality, tokens (25779 → 35335), tool calls (2 → 3)
[18] ⚠️ High run-to-run variance (CV=122%) — consider re-running with --runs 5
[19] ⚠️ High run-to-run variance (CV=118%) — consider re-running with --runs 5
[20] ⚠️ High run-to-run variance (CV=98%) — consider re-running with --runs 5

timeout — run(s) hit the (300s) scenario timeout limit; scoring may be impacted by aborting model execution before it could produce its full output (increase via timeout in eval.yaml)

Model: claude-opus-4.6 | Judge: claude-opus-4.6

🔍 Full Results - additional metrics and failure investigation steps

To investigate failures, paste this to your AI coding agent:

For PR 677 in dotnet/skills, download eval artifacts with gh run download 26575565398 --repo dotnet/skills --pattern "skill-validator-results-*" --dir ./eval-results, then fetch https://raw.githubusercontent.com/dotnet/skills/45b70286628bc30309523a7fc5c3ca8db0786885/eng/skill-validator/src/docs/InvestigatingResults.md and follow it to analyze the results.json files. Diagnose each failure, suggest fixes to the eval.yaml and skill content, and tell me what to fix first.

▶ Sessions Visualisation -- interactive replay of all evaluation sessions

@Evangelink
Evangelink merged commit 36209c3 into dotnet:main May 28, 2026
37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants