mirror of
https://github.com/dotnet/skills.git
synced 2026-09-20 09:49:54 +08:00
93dc33da86
* Deduplicate test skill references and clarify skill boundaries - Move platform-detection.md and filter-syntax.md to plugins/dotnet-test/shared/, removing 3 identical copies of each from run-tests, mtp-hot-reload, and migrate-vstest-to-mtp reference directories. - Move dotnet.md from exp-test-smell-detection/extensions/ to shared/ as dotnet-test-frameworks.md in both dotnet-test and dotnet-experimental plugins. Update exp-assertion-quality, exp-test-boilerplate-detection, exp-test-tagging, and test-anti-patterns to reference the shared file instead of inlining framework detection tables. - Differentiate test-anti-patterns (quick pragmatic review) from exp-test-smell-detection (deep formal audit with academic taxonomy) by updating descriptions and cross-referencing each other in When Not to Use sections. - Update skill-validator to allow ../../shared/ file references while still blocking other parent-directory traversals. Add tests for the new rule. * Switch from shared/ directories to hidden reference skills Replace the plugin-level shared/ directories with non-invocable reference skills (user-invocable: false) that other skills reference by name. - Create platform-detection, filter-syntax, and dotnet-test-frameworks as hidden skills under plugins/dotnet-test/skills/. These contain the detection tables and syntax references previously duplicated across run-tests, mtp-hot-reload, and migrate-vstest-to-mtp. - Create exp-dotnet-test-frameworks as a hidden skill under plugins/dotnet-experimental/skills/ for the experimental test analysis skills (exp-test-smell-detection, exp-assertion-quality, etc.). - Update all consuming skills to reference these by skill name in backtick notation instead of file links. - Revert the skill-validator ../../shared/ exception — no longer needed since all references now use the standard skill name mechanism. * Merge exp-test-boilerplate-detection into exp-test-maintainability exp-test-maintainability was only 6 calibration rules with no workflow. exp-test-boilerplate-detection had the full 5-category detection workflow, examples, calibration, and validation. Merge the boilerplate content into exp-test-maintainability (the broader, more user-facing name) and add the two unique maintainability rules (DisplayName guidance, DataRow vs DynamicData preference) to Category 3. - Replace exp-test-maintainability SKILL.md with the merged content - Move test fixtures from exp-test-boilerplate-detection to exp-test-maintainability - Merge eval.yaml scenarios (4 total: 2 from each original skill) - Delete exp-test-boilerplate-detection skill and tests - Update all cross-references in exp-test-smell-detection, dotnet-test-frameworks, exp-dotnet-test-frameworks, and CODEOWNERS * Add cross-references to test-anti-patterns for deep mock and duplication analysis Point users to exp-mock-usage-analysis from the Over-mocking entry and to exp-test-maintainability from the Duplicate tests entry. * Add exp-dotnet-test-frameworks to CODEOWNERS * Improve run-tests SDK 10 MTP detection for blame-hang scenario Inline the critical SDK 10 detection signal (global.json test.runner) directly in Step 1 instead of deferring entirely to the platform-detection skill. This makes the distinction between SDK 10 (no -- separator) and SDK 8/9 (requires -- separator) more prominent. Add a quick detection summary table, strengthen the Common Pitfalls entry for SDK 10 with a blame-hang-timeout example, and keep the platform-detection skill reference for the full detection logic. * Improve skill activation keywords in descriptions - exp-test-maintainability: Add 'suggest a better test structure', 'consolidate similar test methods', 'convert copy-paste tests to data-driven parameterized tests' to match prompts like 'each new case needs a whole new method, suggest a better structure'. - test-anti-patterns: Add 'review tests', 'find test problems', 'check test quality', 'audit tests for common mistakes' to match review-style prompts that don't use the word 'anti-pattern'. - run-tests: Add 'hang timeout', 'blame-hang', 'blame-crash', 'TUnit' to match SDK 10 blame scenarios and TUnit filter scenarios that were intermittently not activating.
247 lines
11 KiB
YAML
247 lines
11 KiB
YAML
scenarios:
|
|
- name: "Recommend data-driven patterns with display names for unclear parameters"
|
|
prompt: |
|
|
I need to add more test cases for our validation logic but each new case needs a whole new method.
|
|
Can you suggest a better structure?
|
|
|
|
```csharp
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
|
namespace Validation.Tests;
|
|
|
|
[TestClass]
|
|
public sealed class InputValidatorTests
|
|
{
|
|
[TestMethod]
|
|
public void Validate_EmptyString_ReturnsFalse()
|
|
{
|
|
var validator = new InputValidator();
|
|
var result = validator.Validate("");
|
|
Assert.IsFalse(result.IsValid);
|
|
Assert.AreEqual("Input cannot be empty", result.ErrorMessage);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Validate_TooShort_ReturnsFalse()
|
|
{
|
|
var validator = new InputValidator();
|
|
var result = validator.Validate("ab");
|
|
Assert.IsFalse(result.IsValid);
|
|
Assert.AreEqual("Input must be at least 3 characters", result.ErrorMessage);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Validate_TooLong_ReturnsFalse()
|
|
{
|
|
var validator = new InputValidator();
|
|
var result = validator.Validate(new string('x', 256));
|
|
Assert.IsFalse(result.IsValid);
|
|
Assert.AreEqual("Input must not exceed 255 characters", result.ErrorMessage);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Validate_ContainsSpecialChars_ReturnsFalse()
|
|
{
|
|
var validator = new InputValidator();
|
|
var result = validator.Validate("hello<script>");
|
|
Assert.IsFalse(result.IsValid);
|
|
Assert.AreEqual("Input contains invalid characters", result.ErrorMessage);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Validate_ValidInput_ReturnsTrue()
|
|
{
|
|
var validator = new InputValidator();
|
|
var result = validator.Validate("hello-world");
|
|
Assert.IsTrue(result.IsValid);
|
|
Assert.IsNull(result.ErrorMessage);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Validate_MinLength_ReturnsTrue()
|
|
{
|
|
var validator = new InputValidator();
|
|
var result = validator.Validate("abc");
|
|
Assert.IsTrue(result.IsValid);
|
|
Assert.IsNull(result.ErrorMessage);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Validate_MaxLength_ReturnsTrue()
|
|
{
|
|
var validator = new InputValidator();
|
|
var result = validator.Validate(new string('a', 255));
|
|
Assert.IsTrue(result.IsValid);
|
|
Assert.IsNull(result.ErrorMessage);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Validate_Null_ReturnsFalse()
|
|
{
|
|
var validator = new InputValidator();
|
|
var result = validator.Validate(null);
|
|
Assert.IsFalse(result.IsValid);
|
|
Assert.AreEqual("Input cannot be empty", result.ErrorMessage);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Validate_WhitespaceOnly_ReturnsFalse()
|
|
{
|
|
var validator = new InputValidator();
|
|
var result = validator.Validate(" ");
|
|
Assert.IsFalse(result.IsValid);
|
|
Assert.AreEqual("Input cannot be empty", result.ErrorMessage);
|
|
}
|
|
}
|
|
```
|
|
assertions:
|
|
- type: "output_matches"
|
|
pattern: "(DataRow|InlineData|TestCase|data.driven|parameteriz)"
|
|
- type: "output_matches"
|
|
pattern: "(DisplayName|display.name)"
|
|
- type: "exit_success"
|
|
rubric:
|
|
- "Identified that the invalid-input tests can be consolidated into a parameterized test with DataRow"
|
|
- "Identified that the valid-input tests can similarly be consolidated"
|
|
- "Recommended labeling parameterized test cases so that test runner output identifies which case failed"
|
|
- "Showed concrete refactored code with clear test case labels"
|
|
- "Acknowledged that the tests are otherwise well-structured (focused, clear assertions, proper naming)"
|
|
timeout: 120
|
|
|
|
- name: "Recognize well-maintained tests that need minimal changes"
|
|
prompt: |
|
|
Can you review these tests for maintainability? I want to make sure they'll be easy
|
|
to update as the codebase evolves.
|
|
|
|
```csharp
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
|
namespace Auth.Tests;
|
|
|
|
[TestClass]
|
|
public sealed class TokenServiceTests
|
|
{
|
|
[TestMethod]
|
|
[DataRow("user@example.com", "admin", DisplayName = "Admin user gets full-access token")]
|
|
[DataRow("viewer@example.com", "viewer", DisplayName = "Viewer gets read-only token")]
|
|
[DataRow("api@example.com", "service", DisplayName = "Service account gets API token")]
|
|
public void GenerateToken_ValidUser_ReturnsTokenWithCorrectRole(string email, string role)
|
|
{
|
|
var service = CreateTokenService();
|
|
|
|
var token = service.GenerateToken(email, role);
|
|
|
|
Assert.IsNotNull(token);
|
|
Assert.AreEqual(role, token.Role);
|
|
Assert.IsTrue(token.ExpiresAt > DateTime.UtcNow);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void GenerateToken_ExpiredCredentials_ThrowsAuthException()
|
|
{
|
|
var service = CreateTokenService(clockOffset: TimeSpan.FromDays(-1));
|
|
|
|
Assert.ThrowsException<AuthenticationException>(
|
|
() => service.GenerateToken("user@example.com", "admin"));
|
|
}
|
|
|
|
[TestMethod]
|
|
public void RevokeToken_ValidToken_MarksRevoked()
|
|
{
|
|
var service = CreateTokenService();
|
|
var token = service.GenerateToken("user@example.com", "admin");
|
|
|
|
service.RevokeToken(token.Id);
|
|
|
|
Assert.IsTrue(service.IsRevoked(token.Id));
|
|
}
|
|
|
|
[TestMethod]
|
|
public void RevokeToken_AlreadyRevoked_IsIdempotent()
|
|
{
|
|
var service = CreateTokenService();
|
|
var token = service.GenerateToken("user@example.com", "admin");
|
|
service.RevokeToken(token.Id);
|
|
|
|
service.RevokeToken(token.Id); // second call
|
|
|
|
Assert.IsTrue(service.IsRevoked(token.Id));
|
|
}
|
|
|
|
private static TokenService CreateTokenService(TimeSpan? clockOffset = null)
|
|
{
|
|
var clock = clockOffset.HasValue
|
|
? new FakeClock(DateTimeOffset.UtcNow + clockOffset.Value)
|
|
: new FakeClock(DateTimeOffset.UtcNow);
|
|
return new TokenService(clock, new InMemoryTokenStore());
|
|
}
|
|
}
|
|
```
|
|
assertions:
|
|
- type: "output_matches"
|
|
pattern: "(well.maintained|good shape|clean|solid|maintainable|easy to maintain|no.*(major|significant))"
|
|
- type: "exit_success"
|
|
rubric:
|
|
- "Recognized that these tests are already well-maintained and need no major refactoring"
|
|
- "Acknowledged the existing helper method (CreateTokenService) as a good pattern"
|
|
- "Acknowledged that parameterized tests are well-labeled and effectively structured"
|
|
- "Did not recommend over-engineered patterns disproportionate to the test complexity"
|
|
- "If any suggestions were made, they were minor and clearly labeled as optional polish"
|
|
timeout: 120
|
|
|
|
# ==========================================================================
|
|
# Scenario 3: Heavy boilerplate — repeated construction and assertion patterns
|
|
# ==========================================================================
|
|
|
|
- name: "Detect repeated object construction and setup across test methods"
|
|
prompt: |
|
|
I feel like my test code has a lot of copy-paste. Can you analyze
|
|
my OrderService.Tests project and tell me what patterns are repeated
|
|
and where I could refactor?
|
|
setup:
|
|
files:
|
|
- path: "OrderService.Tests/OrderService.Tests.csproj"
|
|
source: "fixtures/heavy-boilerplate/OrderService.Tests/OrderService.Tests.csproj"
|
|
- path: "OrderService.Tests/OrderProcessorTests.cs"
|
|
source: "fixtures/heavy-boilerplate/OrderService.Tests/OrderProcessorTests.cs"
|
|
assertions:
|
|
- type: "output_matches"
|
|
pattern: "(factory|helper|extract|CreateProcessor|CreateOrder|shared|reuse|common)"
|
|
- type: "output_matches"
|
|
pattern: "(3|4|5|6|7|8|multiple|every|all|each|repeated)"
|
|
- type: "exit_success"
|
|
rubric:
|
|
- "Identified that the three-line FakeLogger/FakeEmailService/FakeInventoryService construction block is repeated in every OrderProcessorTests test method"
|
|
- "Identified that Order object construction with Items list is repeated across both test classes with very similar structure"
|
|
- "Suggested extracting a helper method or factory for creating the OrderProcessor with its dependencies"
|
|
- "Suggested extracting a helper for creating test Order objects with customizable properties"
|
|
- "Noted that OrderValidatorTests also repeats the same Order construction pattern as OrderProcessorTests, suggesting a cross-class shared helper"
|
|
- "Provided concrete before/after code showing how at least one extraction would look"
|
|
- "Did not recommend removing all duplication indiscriminately — acknowledged trade-offs between DRY and test readability"
|
|
timeout: 120
|
|
|
|
# ==========================================================================
|
|
# Scenario 4: Minimal boilerplate — tests are already well-structured
|
|
# ==========================================================================
|
|
|
|
- name: "Recognize tests with minimal boilerplate that need no refactoring"
|
|
prompt: |
|
|
Can you check my Calculator.Tests project for any repeated code patterns
|
|
that I should clean up? I have two test classes in there.
|
|
setup:
|
|
files:
|
|
- path: "Calculator.Tests/Calculator.Tests.csproj"
|
|
source: "fixtures/minimal-boilerplate/Calculator.Tests/Calculator.Tests.csproj"
|
|
- path: "Calculator.Tests/CalculatorTests.cs"
|
|
source: "fixtures/minimal-boilerplate/Calculator.Tests/CalculatorTests.cs"
|
|
assertions:
|
|
- type: "output_matches"
|
|
pattern: "(clean|minimal|good|well.structured|no.*(major|significant)|already|little.*(duplicat|boilerplate)|minor)"
|
|
- type: "exit_success"
|
|
rubric:
|
|
- "Recognized that CalculatorTests already uses parameterized data-driven tests and a shared field instance effectively"
|
|
- "Identified that ScientificCalculatorTests has individual test methods that could be consolidated into parameterized tests (e.g., SquareRoot positive/zero cases, Power squared/zero/negative exponent cases)"
|
|
- "Noted that the overall code is well-structured and any suggestions are minor improvements, not critical refactorings"
|
|
- "Did not recommend over-engineered patterns like base classes or shared fixtures for these simple test classes"
|
|
timeout: 120
|