Files
dotnet__skills/tests/dotnet-test/test-smell-detection/eval.yaml
Amaury Levé 680292e04c Make dotnet-test analysis skills and auditor agent polyglot (#707)
* Make dotnet-test analysis skills and auditor agent polyglot

Five test analysis skills and the test-quality-auditor agent in
plugins/dotnet-test previously activated only on .NET MSTest/xUnit/NUnit/
TUnit cues, even though the underlying techniques (assertion diversity,
anti-pattern detection, pseudo-mutation gap analysis, academic smell
catalog, trait tagging) apply equally to other test frameworks.

This change makes them polyglot across .NET, Python (pytest/unittest),
TypeScript/JavaScript (Jest/Vitest/Mocha/node:test), Java (JUnit/TestNG),
Go, Ruby (RSpec/Minitest), Rust, Swift (XCTest/Swift Testing), Kotlin
(JUnit/Kotest), PowerShell (Pester), and C++ (GoogleTest/Catch2/doctest).

Changes
-------

* New reference skill `test-analysis-extensions` with per-language
  extension files (dotnet, python, typescript, java, go, ruby, rust,
  swift, kotlin, powershell, cpp). Each documents test markers,
  assertion APIs, sleep / time / random APIs, skip annotations,
  setup/teardown, mystery-guest indicators, integration markers, and
  tag-support capability for the corresponding framework.
* `assertion-quality`, `test-anti-patterns`, `test-gap-analysis`,
  `test-smell-detection`, `test-tagging` SKILL.md updated: frontmatter
  now lists all polyglot frameworks (keeping .NET trigger words for
  backward compat); bodies reference `test-analysis-extensions` and
  add per-language calibration (e.g., Go/Rust table-driven loops are
  idiomatic and not Conditional Test Logic; pytest bare `assert` is
  canonical; missing-await on async assertions is a new Critical smell).
* `test-quality-auditor` agent now runs language detection, gates
  .NET-only pipeline steps (coverage-analysis, CRAP, detect-static-
  dependencies, testability migration, experimental dotnet skills), and
  recommends native tooling for non-.NET projects via an explicit
  Capability Matrix.
* README updated to split sections by polyglot vs .NET-only.
* New polyglot eval scenarios added (Python/pytest, TS/Jest,
  Java/JUnit) alongside existing C# scenarios in
  `test-anti-patterns`, `assertion-quality`,
  `test-smell-detection`.

The .NET-only skills (writing-mstest-tests, migrate-*, coverage-analysis,
crap-score, detect-static-dependencies, run-tests, filter-syntax,
platform-detection, dotnet-test-frameworks, mtp-hot-reload, exp-*) are
unchanged and continue to activate only for .NET work.

Validated with skill-validator `check --plugin ./plugins/dotnet-test`.

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

* Address PR #707 review feedback

* typescript.md: replace xpect.fail() recommendation (Jest has no
  such API) with 	hrow new Error(...) / explicit failing assertion.
* test-tagging SKILL.md description: clarify that unittest has no
  canonical tag syntax (pytest markers are the auto-edit mechanism;
  unittest is report-only). Switch doctest reference to "decorators"
  rather than implying a Catch2-style [tags] mechanism exists.
* test-tagging SKILL.md auto-edit list and table: use
  `* doctest::test_suite("tag")` decorator chain syntax for doctest
  in both the bullet list and the per-framework table, matching the
  example already shown.
* cpp.md extension: spell out the Catch2 vs doctest tagging
  distinction in the capability matrix (Catch2 [tag], doctest
  * doctest::test_suite("tag") decorator).

Validated with `dotnet run --project eng/skill-validator/src -- check
--plugin ./plugins/dotnet-test` (23 skills + 11 agents).

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

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
2026-06-01 16:46:26 +02:00

191 lines
10 KiB
YAML

scenarios:
# ==========================================================================
# Scenario 1: Multiple test smells in a single test suite
# ==========================================================================
- name: "Detect multiple test smells in order processing test suite"
prompt: |
I'm worried about the quality of our OrderProcessor test suite.
Please run a full testsmells.org 19-smell catalog audit on this
suite and name each finding using the academic taxonomy
(Conditional Test Logic, Mystery Guest, Sleepy Test,
Assertion-Free Test, etc.) so I can cite the research catalog
when I share the results.
setup:
files:
- path: "OrderService.Tests/OrderService.Tests.csproj"
source: "fixtures/smelly-tests/OrderService.Tests/OrderService.Tests.csproj"
- path: "OrderService.Tests/OrderProcessorTests.cs"
source: "fixtures/smelly-tests/OrderService.Tests/OrderProcessorTests.cs"
assertions:
- type: "output_matches"
pattern: "(conditional|if.else|control flow|branch)"
- type: "output_matches"
pattern: "(no assert|assertion.free|without.*assert|zero assert|missing.*assert)"
- type: "output_matches"
pattern: "(Thread\\.Sleep|sleep|delay|sleepy)"
- type: "exit_success"
rubric:
- "Identified the conditional test logic in ProcessOrder_SetsCorrectStatus — the if/else means one branch is always untested"
- "Flagged ProcessOrder_CompletesWithoutError as having no assertions — it only calls the method without verifying anything"
- "Identified the Thread.Sleep(2000) in ProcessOrder_AsyncNotification_IsSent as a flakiness risk"
- "Noted the try/catch pattern in ProcessOrder_EmptyOrder_ThrowsValidationError and suggested using Assert.ThrowsException instead"
- "Identified the ToString() comparison in GetOrderSummary_ReturnsFormattedString as fragile"
- "Noted the File.ReadAllText with a hard-coded path in ImportOrders_FromCsv_ParsesCorrectly as an external dependency problem"
- "Provided concrete fix suggestions showing how to rewrite at least some of the smelly tests"
timeout: 120
# ==========================================================================
# Scenario 2: Clean test suite — acknowledge good quality
# ==========================================================================
- name: "Recognize well-written tests with no significant smells"
prompt: |
Can you do a research-backed academic test-smell taxonomy review
of my Calculator tests using the full testsmells.org 19-smell
catalog? I want each finding (or "no smell detected") to map to
a named smell from the academic literature so we can use these
tests as a clean reference template.
setup:
files:
- path: "Calculator.Tests/Calculator.Tests.csproj"
source: "fixtures/clean-tests/Calculator.Tests/Calculator.Tests.csproj"
- path: "Calculator.Tests/ScientificCalculatorTests.cs"
source: "fixtures/clean-tests/Calculator.Tests/ScientificCalculatorTests.cs"
assertions:
- type: "output_matches"
pattern: "(clean|good|well.written|no.*(major|significant).*(smell|issue|problem)|solid|well.structured)"
- type: "exit_success"
rubric:
- "Recognized that the test suite is well-structured with clear Arrange-Act-Assert patterns"
- "Acknowledged proper use of Assert.ThrowsException for exception testing instead of try/catch"
- "Noted the use of parameterized tests with [DataTestMethod] as a good practice"
- "Did not invent false problems or flag correct patterns as smells"
- "If any minor suggestions were made, they were presented as optional improvements rather than problems"
timeout: 120
# ==========================================================================
# Scenario 3: Integration tests — don't over-flag legitimate patterns
# ==========================================================================
- name: "Recognize integration tests and avoid false positives for external resources"
prompt: |
Our team has been arguing about whether our integration tests are
well-designed. Please use the academic testsmells.org 19-smell
catalog to give us an objective severity-ranked assessment, with
each finding tagged by its formal taxonomy name and integration-
test calibration rules applied.
setup:
files:
- path: "DataAccess.IntegrationTests/DataAccess.IntegrationTests.csproj"
source: "fixtures/integration-tests/DataAccess.IntegrationTests/DataAccess.IntegrationTests.csproj"
- path: "DataAccess.IntegrationTests/UserRepositoryIntegrationTests.cs"
source: "fixtures/integration-tests/DataAccess.IntegrationTests/UserRepositoryIntegrationTests.cs"
assertions:
- type: "output_matches"
pattern: "(integration|appropriate|expected|legitimate|acceptable)"
- type: "output_matches"
pattern: "(Sleep|delay|sleepy|conditional|if.else|assert|no assert)"
- type: "exit_success"
rubric:
- "Recognized that these are integration tests and did not flag database usage or insert-then-query patterns as smells"
- "Identified the Thread.Sleep(3000) in NotifyOnInsert_SendsEventAfterDelay as a real smell even in an integration test context"
- "Flagged the if/else conditional logic in GetUser_ReturnsCorrectType as a test smell — one branch is untested"
- "Identified BulkInsert_RunsWithoutErrors as having no assertions — it exercises code but verifies nothing"
- "Distinguished between the legitimate integration patterns (setup/teardown, multi-step persistence) and the actual smells (sleep, conditional, assertion-free)"
timeout: 120
# ==========================================================================
# Scenario 4: Non-activation — user wants to write new tests
# ==========================================================================
- name: "Decline request to write new tests from scratch"
prompt: |
I need to write unit tests for my ShoppingCart class. It supports
adding items, removing items, calculating totals, and applying
coupon codes. Can you write a complete MSTest test suite for me?
expect_activation: false
setup:
files:
- path: "ShoppingCart.cs"
content: |
namespace Store;
public sealed class ShoppingCart
{
public void AddItem(string sku, int quantity, decimal price) => throw new NotImplementedException();
public void RemoveItem(string sku) => throw new NotImplementedException();
public decimal CalculateTotal() => throw new NotImplementedException();
public void ApplyCoupon(string code) => throw new NotImplementedException();
}
assertions:
- type: "output_matches"
pattern: "(TestMethod|TestClass|\\[Fact\\]|test)"
rubric:
- "Wrote test methods for the ShoppingCart class"
- "Covered multiple methods of the class"
timeout: 300
# ==========================================================================
# Scenario: Polyglot — canonical smells in a JUnit/Java suite
# ==========================================================================
- name: "Polyglot: detect canonical test smells in a JUnit/Java Catalog suite"
prompt: |
Audit `src/test/java/com/example/CatalogTest.java` for test smells.
The production code is at `src/main/java/com/example/Catalog.java`.
This is JUnit 5 / Java, not .NET — apply the same smell catalog
using JUnit equivalents (`@Test`, `@BeforeEach`, `@Disabled`,
`Thread.sleep`, `assertThrows`, etc.).
Walk through each test method by name and identify which canonical
smell it exhibits. Recommend a concrete refactor for each. Do not
edit the files — read-only review.
setup:
files:
- path: "pom.xml"
source: "fixtures/junit-smells/pom.xml"
- path: "src/main/java/com/example/Catalog.java"
source: "fixtures/junit-smells/src/main/java/com/example/Catalog.java"
- path: "src/test/java/com/example/CatalogTest.java"
source: "fixtures/junit-smells/src/test/java/com/example/CatalogTest.java"
assertions:
- type: "output_matches"
pattern: "(conditional|if/else|branch|loop with if)"
- type: "output_matches"
pattern: "(mystery guest|file|external|temp)"
- type: "output_matches"
pattern: "(sleep|Thread\\.sleep|sleepy|wall.clock)"
- type: "output_matches"
pattern: "(no assertion|assertion.?free|empty test|missing assert)"
- type: "output_matches"
pattern: "(eager|multiple.*method|too many|doing too much)"
- type: "output_matches"
pattern: "(magic|literal|unexplain|42|hard.?coded)"
- type: "output_matches"
pattern: "(sensitiv|toString|format.*equal)"
- type: "output_matches"
pattern: "(try.catch|exception handling|manual.*catch|assertThrows)"
- type: "output_matches"
pattern: "(general fixture|unused|rng|over.*setup)"
- type: "output_matches"
pattern: "(disabled|ignored|@Disabled|skipped)"
- type: "exit_success"
rubric:
- "Identified JUnit-specific patterns correctly (did NOT mention MSTest/xUnit attributes as if present)"
- "Mapped addConditionalLogic → Conditional Test Logic (branching inside test)"
- "Mapped addLoadsFromFile → Mystery Guest (reads from the file system)"
- "Mapped addSleepy → Sleepy Test (Thread.sleep used for synchronization)"
- "Mapped addAndDoNothing → Assertion-Free Test"
- "Mapped doEverythingAtOnce → Eager Test (exercises many methods in one test)"
- "Mapped quantityAfterAdds → Magic Number Test (unexplained 41, 1, 42)"
- "Mapped toStringFormat → Sensitive Equality (asserts on toString() output)"
- "Mapped addNullSkuManualCatch → Exception Handling in Tests (recommended assertThrows)"
- "Mapped quantityZeroOnUnknownSku → General Fixture (rng is set up in @BeforeEach but never used)"
- "Mapped disabledTest → Ignored / Disabled Test (@Disabled with vague reason)"
- "Acknowledged addThrowsOnNegativeCount as a well-written test that uses assertThrows correctly"
reject_tools: ["bash", "edit", "create"]
timeout: 180