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://mp-staging.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/java-examples.md

Java Pipeline Examples

Concrete input→output examples for the test generation pipeline targeting a Java codebase using JUnit 5 + Mockito. These show what each pipeline phase produces for a small project.

Source Under Test

A simple InvoiceService in a Maven project using JUnit 5:

pom.xml
src/main/java/com/contoso/billing/
  InvoiceService.java
  Invoice.java                       (mutable POJO with status, taxRate, lineItems and setStatus / setPaidDate mutators)
  InvoiceStatus.java                 (enum: PENDING, PAID)
  InvoiceRepository.java             (interface)
src/test/java/com/contoso/billing/   (exists, empty)
// src/main/java/com/contoso/billing/InvoiceService.java
package com.contoso.billing;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Clock;
import java.time.LocalDateTime;
import java.util.Optional;

public class InvoiceService {

    private final InvoiceRepository repository;
    private final Clock clock;

    public InvoiceService(InvoiceRepository repository) {
        this(repository, Clock.systemUTC());
    }

    public InvoiceService(InvoiceRepository repository, Clock clock) {
        this.repository = repository;
        this.clock = clock;
    }

    public BigDecimal calculateTotal(Invoice invoice) {
        if (invoice == null) {
            throw new IllegalArgumentException("invoice must not be null");
        }
        if (invoice.lineItems().isEmpty()) {
            throw new IllegalStateException("Invoice has no line items.");
        }
        BigDecimal subtotal = invoice.lineItems().stream()
            .map(li -> li.unitPrice().multiply(BigDecimal.valueOf(li.quantity())))
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal tax = subtotal.multiply(invoice.taxRate());
        return subtotal.add(tax).setScale(2, RoundingMode.HALF_UP);
    }

    public Invoice getById(int id) {
        Optional<Invoice> invoice = repository.find(id);
        return invoice.orElseThrow(
            () -> new IllegalArgumentException("Invoice " + id + " not found."));
    }

    public void markAsPaid(int id) {
        Invoice invoice = repository.find(id)
            .orElseThrow(() -> new IllegalArgumentException("Invoice " + id + " not found."));
        if (invoice.status() == InvoiceStatus.PAID) {
            throw new IllegalStateException("Invoice is already paid.");
        }
        invoice.setStatus(InvoiceStatus.PAID);
        invoice.setPaidDate(LocalDateTime.now(clock));
        repository.update(invoice);
    }
}

Sample Research Output

What code-testing-researcher produces in <TESTAGENT_DIR>/research.md:

# Test Generation Research

## Project Overview
- **Path**: /work/billing
- **Language**: Java 21 (`<maven.compiler.release>21</maven.compiler.release>`)
- **Build Tool**: Maven (wrapper `./mvnw` present)
- **Test Framework**: JUnit 5 (Jupiter 5.10) + Mockito 5.x (detected in pom.xml)
- **Assertion library**: built-in `Assertions` (no AssertJ/Hamcrest in deps)

## Coverage Baseline
- **Initial Line Coverage**: unknown
- **Strategy**: broad
- **Existing Test Count**: 0 tests across 0 files

## Build & Test Commands
- **Compile**: `./mvnw -q test-compile`
- **Test**: `./mvnw -q test`
- **Single class**: `./mvnw -q test -Dtest=InvoiceServiceTest`
- **Single method**: `./mvnw -q test -Dtest=InvoiceServiceTest#calculateTotal_validLineItems_returnsExpectedTotal`

## Project Structure
- Source: `src/main/java/com/contoso/billing/`
- Tests: `src/test/java/com/contoso/billing/` (exists, empty)

## Files to Test

### High Priority
| File | Classes/Methods | Testability | Notes |
|------|-----------------|-------------|-------|
| InvoiceService.java | calculateTotal, getById, markAsPaid | High | Repository dependency mockable via Mockito; clock injection available for time-dependent test |

## Testing Patterns
- No existing patterns; recommend JUnit 5 + Mockito with `@ExtendWith(MockitoExtension.class)`, `@Mock` / `@InjectMocks` fields, `@ParameterizedTest` + `@CsvSource` for table-driven `calculateTotal`, and `Clock.fixed(...)` for `markAsPaid` timestamp.

## Recommendations
- Test class lives in the same package (`com.contoso.billing`) for package-private access if needed
- Inject `Clock.fixed(...)` rather than mocking `LocalDateTime.now(...)` — the service already accepts a Clock

Sample Plan Output

# Test Implementation Plan

## Overview
Generate JUnit 5 + Mockito tests for InvoiceService, covering all three public
methods across happy path, edge case, and error scenarios. Single phase since
there is only one source file.

## Commands
- **Compile**: `./mvnw -q test-compile`
- **Test**: `./mvnw -q test -Dtest=InvoiceServiceTest`

## Phase 1: InvoiceService

### Files to Test

#### 1. InvoiceService.java
- **Source**: `src/main/java/com/contoso/billing/InvoiceService.java`
- **Test File**: `src/test/java/com/contoso/billing/InvoiceServiceTest.java`

**Methods to Test**:
1. `calculateTotal` — pure logic (parameterized)
   - Happy paths: single item w/ tax, multi-quantity zero tax, rounding-half-up
   - Error cases: null invoice → IllegalArgumentException; empty line items → IllegalStateException
2. `getById` — happy + missing
3. `markAsPaid` — happy (verify status + paid date via fixed clock + verify update) + already-paid + missing

Sample Generated Test File

// src/test/java/com/contoso/billing/InvoiceServiceTest.java
package com.contoso.billing;

import java.math.BigDecimal;
import java.time.Clock;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.List;
import java.util.Optional;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class InvoiceServiceTest {

    @Mock
    InvoiceRepository repository;

    @InjectMocks
    InvoiceService sut;

    // --- calculateTotal ---

    @ParameterizedTest(name = "qty={0} unitPrice={1} taxRate={2} -> {3}")
    @CsvSource({
        "1, 100.00, 0.10, 110.00",
        "3, 25.00,  0.00,  75.00",
        "2,  9.99,  0.07,  21.38"
    })
    void calculateTotal_validLineItems_returnsExpectedTotal(
        int quantity, BigDecimal unitPrice, BigDecimal taxRate, BigDecimal expected
    ) {
        Invoice invoice = new Invoice(1, InvoiceStatus.PENDING, taxRate,
            List.of(new LineItem(quantity, unitPrice)));

        BigDecimal total = sut.calculateTotal(invoice);

        assertEquals(0, total.compareTo(expected),
            () -> "expected " + expected + " but got " + total);
    }

    @Test
    @DisplayName("null invoice throws IllegalArgumentException")
    void calculateTotal_nullInvoice_throws() {
        assertThrows(IllegalArgumentException.class, () -> sut.calculateTotal(null));
    }

    @Test
    void calculateTotal_emptyLineItems_throws() {
        Invoice invoice = new Invoice(1, InvoiceStatus.PENDING, BigDecimal.ZERO, List.of());

        IllegalStateException ex = assertThrows(IllegalStateException.class,
            () -> sut.calculateTotal(invoice));
        assertEquals("Invoice has no line items.", ex.getMessage());
    }

    // --- getById ---

    @Test
    void getById_existingId_returnsInvoice() {
        Invoice expected = new Invoice(42, InvoiceStatus.PENDING, BigDecimal.ZERO, List.of());
        when(repository.find(42)).thenReturn(Optional.of(expected));

        assertSame(expected, sut.getById(42));
    }

    @Test
    void getById_missingId_throws() {
        when(repository.find(999)).thenReturn(Optional.empty());

        IllegalArgumentException ex = assertThrows(IllegalArgumentException.class,
            () -> sut.getById(999));
        assertEquals("Invoice 999 not found.", ex.getMessage());
    }

    // --- markAsPaid (uses an injected fixed Clock instead of @InjectMocks) ---

    @Test
    void markAsPaid_pendingInvoice_transitionsToPaidAndPersists() {
        Clock fixed = Clock.fixed(Instant.parse("2025-01-01T12:00:00Z"), ZoneOffset.UTC);
        InvoiceService service = new InvoiceService(repository, fixed);
        Invoice invoice = new Invoice(1, InvoiceStatus.PENDING, BigDecimal.ZERO, List.of());
        when(repository.find(1)).thenReturn(Optional.of(invoice));

        service.markAsPaid(1);

        assertEquals(InvoiceStatus.PAID, invoice.status());
        assertEquals(LocalDateTime.ofInstant(fixed.instant(), ZoneOffset.UTC), invoice.paidDate());
        verify(repository).update(invoice);
    }

    @Test
    void markAsPaid_alreadyPaid_throwsAndDoesNotUpdate() {
        Invoice invoice = new Invoice(1, InvoiceStatus.PAID, BigDecimal.ZERO, List.of());
        when(repository.find(1)).thenReturn(Optional.of(invoice));

        assertThrows(IllegalStateException.class, () -> sut.markAsPaid(1));
        verify(repository, never()).update(any());
    }

    @Test
    void markAsPaid_missingId_throws() {
        when(repository.find(999)).thenReturn(Optional.empty());

        assertThrows(IllegalArgumentException.class, () -> sut.markAsPaid(999));
    }
}

Sample Fix Cycle

When the implementer hits a compile or runtime error, the fixer agent diagnoses and resolves it.

Test output:

[ERROR] No tests found for given includes: [com.contoso.billing.InvoiceServiceTest]

Fixer diagnosis: Surefire only includes **/*Test.class (default). The class is InvoiceServiceTest (correct) but it was created under src/test/java/com/contoso/billing/ with no package declaration. Maven compiles it into the default package, so -Dtest=com.contoso.billing.InvoiceServiceTest doesn't match.

Fix applied: Add package com.contoso.billing; at the top of the test file so it lands in the expected package.

Rebuild + rerun: ./mvnw -q test -Dtest=InvoiceServiceTest → SUCCESS


Another common cycle — wrong Mockito setup:

Test output:

org.mockito.exceptions.misusing.UnnecessaryStubbingException:
Unnecessary stubbings detected.
  1. -> at InvoiceServiceTest.calculateTotal_nullInvoice_throws(InvoiceServiceTest.java:55)

Fixer diagnosis: @MockitoExtension runs in strict mode by default — stubbed calls (when(repository.find(...)).thenReturn(...)) must be used. The test stubbed repository in a @BeforeEach for every test, but calculateTotal_nullInvoice_throws never touches the repository.

Fix applied: Move stubs into the tests that actually need them (as shown in the generated file above), rather than a single shared @BeforeEach.

Rebuild + rerun: SUCCESS

Sample Final Report

## Test Generation Report

**Project**: billing (Java / Maven)
**Strategy**: Direct (single source file in scope)

### Results
| Metric         | Value |
|----------------|-------|
| Tests created  | 8     |
| Tests passing  | 8     |
| Tests failing  | 0     |
| Files created  | 1     |

### Files Created
- `src/test/java/com/contoso/billing/InvoiceServiceTest.java` (8 tests, 3 parameterized cases via @CsvSource)

### Coverage
- InvoiceService.calculateTotal — 3 happy path, 2 error cases
- InvoiceService.getById — happy + missing
- InvoiceService.markAsPaid — happy (fixed Clock) + already-paid + missing

### Build / Test Validation
- `./mvnw -q test-compile`: ✅
- `./mvnw -q test`: ✅ Tests run: 8, Failures: 0, Errors: 0

### Next Steps
- Add AssertJ if the team standardises on it (more expressive assertions)
- Consider Testcontainers for true repository integration tests

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).

Download ZIP

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