SkillAgentSearch skills...

grade-tests

Grade specified test methods individually and produce a concise PR-ready table with each fully qualified test name, an A-F grade, score band, and one-line note. USE FOR per-test feedback on a curated list such as new or modified tests in a pull request, not a suite-wide audit.

Install / Use

npx skills add dotnet/skills --skill grade-tests

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

87/100

Supported Platforms

Universal

Our assessment of grade-tests

grade-tests scores 87/100 on our quality scale, 258th of 504 Content & Media skills we index.

Its SKILL.md is 19 KB long, well organised into 21 sections with 1 code example: a thorough specification that gives an agent plenty to work with.

With 5,471 GitHub stars, it is one of the more widely adopted skills in the catalogue.

Substance
30/30
Structure
17/20
Description
15/15
Adoption
16/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 2 days ago, so grade-tests is actively maintained.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

grade-tests compared with similar skills

All 4 of these similar skills score higher than grade-tests; compare them before choosing.

SkillScoreStarsUpdatedFormat
grade-tests (this skill)by dotnet875.5k2d agoSKILL.md
Agent-Reachby Panniantong10085.6k11d agoCLAUDE.md
headroomby headroomlabs-ai10073.9ktodayCLAUDE.md
Scraplingby D4Vinci10083.9ktodayMCP Server
siyuanby siyuan-note10046.5ktodayMCP Server

Frequently asked questions

How do I install grade-tests?
Run npx skills add dotnet/skills --skill grade-tests. The install tabs above show the steps for each supported agent.
Which AI agents does grade-tests work with?
It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
Is grade-tests safe to use?
It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is grade-tests still maintained?
The repository was last updated 2 days ago, so grade-tests is actively maintained.

name: grade-tests description: > Grade specified test methods individually and produce a concise PR-ready table with each fully qualified test name, an A-F grade, score band, and one-line note. USE FOR per-test feedback on a curated list such as new or modified tests in a pull request, not a suite-wide audit. Polyglot: .NET, Python, TS/JS, Java, Go, Ruby, Rust, Swift, Kotlin, PowerShell, C++. Inputs may be test methods, method bodies, or file-and-line spans. DO NOT USE FOR: full suite audits (use test-quality-auditor agent or test-anti-patterns), writing new tests (use code-testing-generator agent or writing-mstest-tests), fixing failures, or measuring code coverage. license: MIT

Grade Tests

Grade a curated list of test methods and produce a compact, PR-comment-friendly report: one row per test method with a letter grade, a score band, and a one-line note explaining the grade. The skill does not discover tests on its own — the caller (typically a PR automation workflow or a human reviewer holding a specific list) provides the test methods to grade.

Language-specific guidance: Call the test-analysis-extensions skill to discover available extension files, then read the file matching the target codebase's language and framework (e.g., extensions/dotnet.md, extensions/python.md, extensions/typescript.md, extensions/go.md). You MUST read the relevant extension file before scoring assertions or anti-patterns, because assertion APIs and idiomatic patterns differ significantly across frameworks.

Why a Per-Test Grade

Suite-wide audits (test-anti-patterns, assertion-quality, test-smell-detection) produce excellent diagnostic reports, but they are hard to consume as a short PR comment. Reviewers of a PR mostly want to know: for the tests this PR adds or changes, are they good? This skill answers that question with a one-row-per-test verdict that fits in a comment table.

When to Use

  • A PR automation workflow needs to post a comment grading the tests introduced or modified in a pull request.
  • A reviewer has a specific list of tests (a file, a class, a method list, or a diff hunk) and wants a per-test verdict rather than a suite report.
  • A maintainer wants to triage which of N tests in a contribution deserve follow-up improvements.

When Not to Use

  • The caller wants a full suite audit or comparative metrics — use test-anti-patterns (pragmatic) or test-smell-detection (formal) and let the test-quality-auditor agent orchestrate.
  • The caller wants to write new tests — use code-testing-generator (any language) or writing-mstest-tests (MSTest specifically).
  • The caller wants to measure code coverage or CRAP scores — use coverage-analysis or crap-score (.NET only).
  • The caller wants to fix issues directly in test code — invoke the appropriate editing skill.
  • No specific list of tests is provided. Do not try to grade every test in the workspace; ask the caller for an explicit list or scope.

Inputs

| Input | Required | Description | |-------|----------|-------------| | Test methods | Yes | A scope to grade. Provide one of: (a) an explicit list of test method names (fully-qualified, e.g. Namespace.ClassName.TestMethodName); (b) one or more file paths plus an explicit instruction to grade every test declared in those files; or (c) a diff hunk / PR identifier whose changed tests should be graded. File paths are recommended but optional when method names are unambiguous in the workspace. Ambiguous requests like "grade my tests" with no scope are rejected up-front (see Step 0); this skill is for curated input and does not auto-grade an entire workspace. | | Test bodies / spans | Recommended | The exact source lines for each test method. If omitted, read them from the listed files. | | Production code | No | The code under test, for judging whether assertions cover the meaningful behaviors. When unavailable, mark relevant findings as "Unverified" rather than guessing. | | Diff context | No | When grading PR changes, the unified diff for each test method helps focus on what actually changed. |

Step 0: Validate the input

Before doing anything else, check that the caller provided one of:

  1. An explicit list of test method names, or
  2. One or more file paths plus an explicit instruction to grade every test declared in those files (e.g., "grade every test in OrderTests.cs"), or
  3. A diff hunk or PR identifier whose changed tests should be graded.

If the request is ambiguous (e.g., "Grade my tests", "Are these tests any good?" with no scope, "Review the test suite"), do not load extensions, do not read files, and do not grade anything. Reply with a short message asking the caller to provide an explicit list / file(s) / diff, and optionally point them at test-quality-auditor agent or test-anti-patterns skill for full-suite analysis. Stop there.

Workflow

Step 1: Detect language and load extension

Identify the target codebase's language and test framework from the file extensions and the test method markers in the provided list. Call the test-analysis-extensions skill and read the matching extension file (e.g., extensions/dotnet.md for MSTest/xUnit/NUnit/TUnit, extensions/python.md for pytest, extensions/typescript.md for Jest/Vitest, extensions/go.md for the standard testing package). If the input contains tests from multiple languages, load each relevant extension and grade each test using its language's conventions.

Step 2: Resolve the test bodies

For each entry in the input list:

  1. If the test body is provided inline, use it directly.
  2. Otherwise read the file at the given path and locate the method by its fully-qualified name. Capture the full method body, including attributes / decorators / fixtures and any helper code that the test calls.
  3. If a method cannot be found, record it as N/A — method not found and continue. Never invent a body to grade.

Step 3: Score each test

Start every test at grade A (score band 90–100), then apply deductions strictly for observable issues in the captured body. Do not deduct for hypothetical concerns (e.g., "could have more negative assertions") unless the production code clearly demands them and the production code is available.

When production code is unavailable, grade observable issues in the test body normally, but do not infer missing behaviors or deduct for them. State Production-dependent behavior coverage: Unverified once in the summary so the reader can distinguish test-body findings from claims that require source code.

Three sub-dimensions

Compute three sub-grades (each A–F) that together drive the overall grade.

A. Assertion strength

Read the loaded language extension's assertion API list and classify every assertion in the test body. Score from highest to lowest:

| Sub-grade | Pattern | |-----------|---------| | A | At least one meaningful value assertion (equality / structural / exception / state) plus, where appropriate, additional checks (negative, type, collection contents). Mock-call verifications (Verify, toHaveBeenCalledWith, Should -Invoke) and bare assertion forms (pytest assert, Go if got != want { t.Errorf(...) }, Rust assert!()) count as real assertions. | | B | One clear meaningful assertion that verifies the behavior under test. | | C | Only trivial assertions (single IsNotNull / toBeDefined / assert x is not None), or assertions that check a single field while the operation produces a richer result. | | D | One self-referential / tautological assertion (Assert.AreEqual(x, x), assert dto.name == dto.name, round-trip identity without a non-trivial input), or broad exception assertions (Assert.ThrowsException<Exception>). | | F | No assertions at all; all assertions are always-true literals (Assert.IsTrue(true), assert True, expect(true).toBe(true)) — these verify nothing and are equivalent to having no assertions; or all assertions are silently un-awaited (e.g., expect(promise).resolves.toBe(x) without await/return, async TUnit/xUnit Assert.ThrowsAsync without await, pytest-asyncio with un-awaited coroutine). |

Exception and error-path tests (Assert.ThrowsException<T>, constrained pytest.raises, expect(fn).toThrow, assertThrows, #[should_panic], Should -Throw, EXPECT_THROW, or Go code that verifies an expected non-nil error) are complete on their own. Give Assertion strength A when the test checks the exact promised error condition for its stated scope. Do not deduct for having only that assertion, and do not require an error-message assertion unless the message is part of the documented contract. A Go happy-path test that only checks err == nil while discarding a meaningful returned value is still C because it does not verify the successful result.

B. Structure & focus

| Sub-grade | Pattern | |-----------|---------| | A | Clear Arrange-Act-Assert (or Given-When-Then) separation. Single behavior under test. Body under ~30 lines. Setup uses framework conventions. | | B | One mild structural issue (slightly long body, missing blank lines between phases) but intent is clear. | | C | Multiple behaviors mixed in one test, or AAA phases interleaved enough to slow comprehension. | | D | Conditional logic in the test (if/switch driving assertions) — except for idiomatic Go/Rust table-driven sub-test loops; or test relies on previous test state (ordering dependency). | | F | Test exceeds ~60 lines and verifies multiple unrelated behaviors; or shares mutable state with other tests through statics/globals without reset. |

C. Anti-pattern hygiene

Scan against the catalog below. The Anti-pattern sub-grade is computed in two passes and combined deterministically:

  1. Hard ceiling pass. Every Critical or High finding sets a maximum sub-grade (F, D, or C as labeled). Take the worst ceiling across all matched Critical/High findings — these do not accumulate (a single F finding caps the sub-grade at F regardless of how many other Critical/High findings are present).
  2. Medium-deduction pass. Start from A, then for each Medium finding deduct one sub-grade level (A→B, B→C, C→D, D→F). These do accumulate across findings.

The final Anti-pattern sub-grade is the worse of the two passes (i.e., min(hard_ceiling, A − medium_count)). Low findings never affect the grade — mention them in the note only.

Examples (Critical/High and Medium counts → Anti-pattern sub-grade):

  • Zero Critical/High, 1 Medium → B (A − 1)
  • Zero Critical/High, 3 Medium → D (A − 3)
  • One C-ceiling (e.g., over-mocking), 0 Medium → C
  • One C-ceiling, 2 Medium → C (min(C, A − 2 = C) = C; a third Medium tips to D)
  • One F-finding (e.g., swallowed exception) plus any number of Medium → F

Critical (drop straight to F or D)

  • No assertions at all → F (also drives Assertion sub-grade to F)
  • Swallowed exceptions: try { … } catch { } (.NET), bare except: pass (Python), try { … } catch (e) {} (JS/TS/Java), defer recover() without re-panic (Go), rescue StandardError with no assertion (Ruby), empty catch (Kotlin/Swift) → F
  • Assert-in-catch pattern (Assert.Fail(ex.Message) instead of Assert.ThrowsException) → D
  • Always-true literal assertions (Assert.IsTrue(true), assert True, expect(true).toBe(true)) → F (verifies nothing; also drives Assertion sub-grade to F)
  • Self-referential / tautological assertions on bound values (Assert.AreEqual(x, x), assert dto.name == dto.name) → D
  • Commented-out assertions → D

High (drop one or two sub-grades)

  • Wall-clock sleep used for synchronization: Thread.Sleep, Task.Delay, time.sleep, setTimeout-based wait, Thread.sleep, time.Sleep, `sleep

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars5.5k
CategoryContent
Updated2d ago
Forks418

Languages

C#

Trust signals

100/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

No cautions