Generated banner for Code Testing Extensions
Generated logo for Code Testing Extensions

Code Testing Extensions

.NET (Microsoft)OfficialPublished by .NET (Microsoft)

  • Skill
  • Guidelines
  • Software development
  • MIT
  • Low risk

From the author

Provides file paths to language-specific extension files for the code-testing pipeline. Read this reference-only catalog for extension guidance files (e.g., dotnet.md for .NET, cpp.md for C++). Agents and skills read its bundled files directly; do not invoke this catalog through the model's skill tool.
— the description by .NET (Microsoft)

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

Code Testing Extensions is a non-invocable reference library designed to support automated testing workflows. It provides a structured collection of documentation files covering various programming languages, including .NET, Python, TypeScript, Go, Java, and more. Each entry offers essential guidance on build and test commands, framework-specific patterns, mocking strategies, and common error resolution. Additionally, the catalog includes example files that demonstrate complete testing pipeline cycles, from research and planning to test generation and reporting.

What it does

  • Provides language-specific testing guidance for multiple programming environments.
  • Lists standard build and test commands for various testing frameworks.
  • Offers best practices for mocking, project layout, and framework detection.
  • Includes concrete examples of full testing pipeline workflows.
  • Serves as a centralized reference for agents to ensure consistent testing standards.

When to use it

  • When an agent needs to determine the correct testing commands for a specific language.
  • When implementing or debugging a testing pipeline for a new project.
  • When guidance on framework-specific mocking or test structure is required.
  • When looking for representative examples of a complete test generation cycle.

Advantages

  • Ensures consistency across different testing environments.
  • Reduces ambiguity by providing standardized commands and patterns.
  • Provides both high-level guidance and concrete implementation examples.
  • Supports a wide range of modern programming languages and frameworks.

Usage examples

“Read extensions/python.md to understand the preferred testing patterns for a pytest project.”
The agent retrieves the Python-specific guidance, identifying the correct test runner commands and mocking strategies to apply.
“Consult extensions/java-examples.md to see how to structure a JUnit 5 test suite.”
The agent reviews the provided example to replicate the established project structure and testing conventions for the Java codebase.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/dotnet/code-testing-extensions/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip code-testing-extensions.zip -d .agents/skills

Documentation by .NET (Microsoft)

Code Testing Extensions

This reference-only catalog lists bundled guidance for the code-testing pipeline. Read the matching file directly; do not invoke this catalog as a skill. Resource paths are relative to this catalog, not the project workspace.

Available Extension Files

FileLanguageContents
extensions/dotnet.md.NET (C#/F#/VB)Build commands, test commands, project reference validation, common CS error codes, MSTest template
extensions/python.mdPythonFramework-adaptive test commands (pytest, custom runners), project layout detection, mocking guidelines, common errors
extensions/typescript.mdTypeScript/JavaScriptBuild/test commands (Jest/Vitest/Mocha), framework detection, mocking, TS-specific considerations
extensions/powershell.mdPowerShellTest commands (Pester v5), module import patterns, discovery/run pitfalls, mocking, common errors
extensions/cpp.mdC++Testing internals with friend declarations
extensions/go.mdGogo test commands, table-driven tests, integration vs unit layout, mocking via interfaces, common errors
extensions/java.mdJavaMaven/Gradle commands, JUnit 4/5 and TestNG detection, Mockito, Spring Boot slices, common errors
extensions/rust.mdRustcargo test commands, unit vs integration vs doc tests, features, async test harnesses, common errors
extensions/ruby.mdRubyRSpec and Minitest commands, Bundler usage, Rails specifics, mocking patterns, common errors
extensions/swift.mdSwiftSPM and Xcode test commands, XCTest vs Swift Testing, @testable import, async/throws tests, common errors
extensions/kotlin.mdKotlinGradle commands, JUnit/Kotest detection, MockK, coroutines test, KMP and Android specifics, common errors
extensions/dotnet-examples.md.NET (C#/F#/VB)Concrete pipeline examples: sample research output, plan, generated tests, fix cycles, final report
extensions/python-examples.mdPythonConcrete pipeline examples (pytest): research, plan, generated test file, fix cycles, final report
extensions/typescript-examples.mdTypeScript/JavaScriptConcrete pipeline examples (Vitest, applicable to Jest): research, plan, generated test file, fix cycles, final report
extensions/go-examples.mdGoConcrete pipeline examples (standard testing): research, plan, table-driven test file, fix cycles, final report
extensions/java-examples.mdJavaConcrete pipeline examples (JUnit 5 + Mockito on Maven): research, plan, generated test file, fix cycles, final report

Usage

Read the appropriate base extension before writing test code. Load an <language>-examples.md file only when the repository has no representative tests and the base extension does not resolve the needed pattern. Do not load end-to-end examples for a focused request with established local conventions.

Files

extensions/powershell.md

PowerShell Extension

Language-specific guidance for PowerShell test generation using Pester v5.

Rule #0: Confirm the Test Target

If the prompt does not name a specific file (e.g. "test the repository", "cover one core module", "comprehensive suite"), do not assume the largest or top-level upstream code is the intended target. In real workflows the user usually wants to test code they have just added, and large upstream repos contain hundreds of scripts already covered by existing *.Tests.ps1 files.

Run these read-only discovery commands first — they are the deliberate exception to Rule #1's "before writing any test or running any command" rule, and their output is the ground truth Rule #1's reading is meant to interpret. Do not write or execute any tests until Rule #0 and Rule #1 are both complete.

GoalCommand
List uncommitted edits + untracked filesgit status -s
Untracked files only (typical for newly-added modules)git ls-files --others --exclude-standard
Recently added scripts/modulesgit log --diff-filter=A --name-only -5 -- '*.ps1' '*.psm1' '*.psd1'
Modules with no matching *.Tests.ps1compare Get-ChildItem -Recurse -Include *.psm1,*.ps1 against *.Tests.ps1 files

Prefer targets that match all of:

  1. Untracked or recently added (git status / git log --diff-filter=A).

  2. Small and pure (a few hundred lines, no external state, no Invoke-WebRequest/registry/filesystem side effects).

  3. Located under a conventional source root (tools/, src/, Public/, Private/, or the module root next to a .psd1).

  4. Have no existing matching *.Tests.ps1 file.

If a .psd1 manifest's RootModule (or ModuleToProcess) points at a specific .psm1, that module is almost certainly the target — start there.

Test Placement Contract

Pester only discovers tests under the path passed to Invoke-Pester -Path (or the current directory when no path is given). Verification harnesses (CI, msbench, coverage tools) typically scope discovery to a single directory such as tools/ or tests/. Place every test file there, matching the existing convention in the repo:

Layout used by the repoTest placement
Co-located convention (Module.psm1 + Module.Tests.ps1 side-by-side)Drop <Module>.Tests.ps1 next to the source file (tools/StringUtils.psm1 → tools/StringUtils.Tests.ps1).
Sibling Tests/ directoryMirror the source path (src/Foo/Bar.psm1 → Tests/Foo/Bar.Tests.ps1).
Mixed / unknownCo-locate next to the source — this is what Pester discovers by default and what most harnesses scope to.

A *.Tests.ps1 file placed outside the discovery root will be invisible to both Invoke-Pester and the harness.

First-Test Sanity Loop

After writing the first *.Tests.ps1 file — before writing any others:

  1. Run Invoke-Pester -Path <dir> -PassThru and confirm the TotalCount is > 0. If it is 0, Pester is not discovering your file; fix the location, filename, or Describe/It structure before continuing.

  2. Run the test (Invoke-Pester -Path <your.Tests.ps1> -Output Detailed); fix Import-Module / dot-source / BeforeAll errors before adding more tests.

  3. Only then expand to cover the remaining functions.

This catches placement and discovery mistakes on turn 1 instead of after dozens of failed-test iterations.

Harness Discovery Check

Before reporting success, run the harness-equivalent discovery command from the repo root and confirm the test count went up by at least the number of tests you generated. CI/msbench/coverage harnesses do not know which directory you targeted with -Path; they invoke Pester from the repo root with default discovery, so a test that passes via Invoke-Pester -Path ./tools/Foo.Tests.ps1 is still worthless if Invoke-Pester from the repo root does not enumerate it.

# From repo root — mirrors what a generic harness sees
$result = Invoke-Pester -Configuration @{ Run = @{ PassThru = $true; SkipRun = $true } }
"$($result.TotalCount) tests discovered"

If the count did not increase, your *.Tests.ps1 file is outside the harness discovery root. Move it to the convention the repo's existing tests use (or, if there are no existing tests, prefer the repo root's tests/, Tests/, tst/, test/, or co-locate next to the source). Do not report success until the harness-equivalent command sees your new tests.

Rule #1: Investigate the Repo First

Before writing any test or running any command, read:

  1. Existing tests — find *.Tests.ps1 files and copy their style (structure, assertions, mock approach, import method)

  2. Module structure — look for .psd1 (manifest), .psm1 (root module), Public//Private/ organization

  3. Build/test scripts — check for build.ps1, Invoke-Build (*.build.ps1), psake, or CI scripts

  4. Shell target — check .psd1 for PowerShellVersion/CompatiblePSEditions, CI matrix for pwsh vs powershell.exe

Use the repo's existing test conventions. Only add Pester if the repo has no tests at all.

Build Commands

PowerShell is interpreted — no build step. If the repo has a build script, use it. Otherwise validate with:

  • Module loads: Import-Module ./MyModule.psd1 -Force -ErrorAction Stop

  • Script analyzer: Invoke-ScriptAnalyzer -Path ./src -Recurse (if PSScriptAnalyzer is available)

  • Lint: Invoke-ScriptAnalyzer -Path path/to/file.ps1 -Fix

Test Commands

ScopeCommand
All testsInvoke-Pester
Specific fileInvoke-Pester -Path ./Tests/Get-Widget.Tests.ps1
Filter by nameInvoke-Pester -FullNameFilter '*Get-Widget*'
Filter by tagInvoke-Pester -TagFilter 'Unit'
Non-interactive (CI)Invoke-Pester -CI
Detailed outputInvoke-Pester -Output Detailed
  • Prefer the repo's build/test script over raw Invoke-Pester

  • Use -Output Detailed during fix cycles, -Output Minimal for final validation

Project Layout and Imports

LayoutImport in BeforeAll
Module (.psd1)Import-Module "$PSScriptRoot/../MyModule.psd1" -Force
Library script (defines functions). $PSScriptRoot/Get-Widget.ps1
Co-located test. $PSCommandPath.Replace('.Tests.ps1', '.ps1')
Executable script (has param())Do not dot-source — invoke with & $PSScriptRoot/script.ps1 -Param value and assert on output/errors
  • All imports go in BeforeAll — never at script top level

  • Use $PSScriptRoot or $PSCommandPath — never $MyInvocation.MyCommand.Path (returns empty in BeforeAll)

  • Use -Force on Import-Module to pick up changes between runs

Test File Naming

  • Files: *.Tests.ps1 — match existing convention (co-located vs Tests/ directory)

Pester v5 Discovery vs Run (Critical)

Pester v5 runs in two phases: Discovery (collects test metadata) then Run (executes tests). This is the #1 source of agent errors.

Rules:

  • All setup code goes in BeforeAll or BeforeEach — never at script top level or loose inside Describe/Context

  • Code directly inside Describe/Context (but outside It/Before*/After*) runs during Discovery — do not put setup, imports, or variable assignments there

  • Data for -ForEach / -TestCases must be set in BeforeDiscovery, not BeforeAll (BeforeAll runs after discovery)

  • -Skip:$condition evaluates at Discovery time — conditions from BeforeAll will be $null

  • Use foreach loops for dynamic test generation only with BeforeDiscovery data

  • Use TestDrive: for file-based tests instead of touching repo files — Pester cleans it up automatically

Parameterized Test Display Names

Apply Report-safe test names and result validation. Use an explicit safe Name/Case in -ForEach or -TestCases data and expand only that field in the It title. Do not expand arbitrary <Input> or <Expected> values into discovery/report metadata.

For a function whose contract reverses UTF-16 code units (not Unicode scalars), the reversed supplementary character is intentionally malformed UTF-16. Keep that expected value in the assertion, not the title:

Use Text for the data field, not Input: $Input is PowerShell's automatic pipeline-input variable and can hide the intended case value inside It.

BeforeDiscovery {
    $cases = @(
        @{
            Name = 'supplementary code-unit reversal'
            Text = [string]::Concat([char]0xD83D, [char]0xDE00)
            Expected = [string]::Concat([char]0xDE00, [char]0xD83D)
        }
        @{
            Name = 'isolated high surrogate'
            Text = [string][char]0xD800
            Expected = [string][char]0xD800
        }
    )
}

Describe 'Get-Reversed' {
    BeforeAll {
        Import-Module (Join-Path $PSScriptRoot '../tools/StringUtils.psm1') -Force
    }

    It 'reverses <Name>' -ForEach $cases {
        Get-Reversed -Value $Text | Should -BeExactly $Expected
    }
}

Reuse the repository's configured Pester TestResult export path and format when present and parse the resulting artifact before reporting success. A passing TotalCount/PassedCount does not prove JUnit export succeeded.

Common Errors

ErrorFix
Variable is $null in It blockMove assignment into BeforeAll — variables set there are visible to child It blocks without $script:
-ForEach data is emptyMove data setup from BeforeAll to BeforeDiscovery
CommandNotFoundException for Mock targetThe function must exist before mocking — import the module in BeforeAll first
$MyInvocation.MyCommand.Path returns emptyUse $PSCommandPath or $PSScriptRoot instead
Should Be (no dash) failsUse v5 syntax: Should -Be (with dash prefix)
Assert-MockCalled not recognizedUse v5 syntax: Should -Invoke
Mock has no effectCheck scope — mocks in It only apply to that It; use BeforeAll/BeforeEach for broader scope
Should -Throw doesn't catch cmdlet errorsMost cmdlet errors are non-terminating — wrap with { cmd -ErrorAction Stop } or set $ErrorActionPreference = 'Stop' in BeforeEach
Tests pass on Windows but fail on LinuxUse Join-Path not string concatenation; match exact file casing; avoid Windows-only cmdlets (Registry, EventLog)

Mocking Rules

  • Place mocks in BeforeAll (shared) or BeforeEach (reset per test)

  • Mock where the command is called from — use -ModuleName to mock inside a module's scope

  • Use -ParameterFilter for selective mocking (no param() block needed in v5)

  • Verify calls with Should -Invoke — default scope inside It counts only that test's calls

  • Use InModuleScope sparingly and as narrowly as possible — prefer Mock -ModuleName for testing via public API

  • Inside mock bodies, use $PesterBoundParameters not $PSBoundParameters

  • If a test needs more than 3 mocks, flag it as a design smell

Non-Obvious Assertions

Most Should operators are self-explanatory. These are the ones agents get wrong:

  • Should -Throw requires a scriptblock: { risky-op } | Should -Throw — not a direct call

  • Should -Contain is for collections — use Should -Be for scalar equality

  • Should -HaveParameter validates cmdlet signatures: Get-Command X | Should -HaveParameter 'Name' -Mandatory

  • Should -Invoke verifies mock calls: Should -Invoke Get-Item -Times 1 -Exactly

Cross-Platform

  • Prefer pwsh (PowerShell 7+) unless the repo explicitly targets Windows PowerShell 5.1

  • Use Join-Path for paths — never string concatenation with \

  • Linux/macOS file systems are case-sensitive — match exact casing in imports and paths

  • Windows ships Pester 3.4.0 — if v5 is needed: Install-Module Pester -Force -SkipPublisherCheck

  • Check $PSVersionTable.PSEdition to detect Core vs Desktop

Skip Coverage Tools

Do not configure or run coverage tools (Pester CodeCoverage, JaCoCo export). Coverage is measured separately by the evaluation harness.

Requirements and compatibility

Written for: Claude Code

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Claude Code frontmatter, Needs Python

Security

What our scanner noticed· Low risk

  • Instructions that use the network

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
.NET (Microsoft)
Publisher
.NET (Microsoft) (Official)
Source
dotnet/skills · plugins/dotnet-test/skills/code-testing-extensions · commit 96c3d68
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by .NET (Microsoft) or .NET (Microsoft).

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download code-testing-extensions.zip