💻 Développement

dev-unit-test-generator

Génère des tests unitaires complets pour tout langage et framework.

⚡ Installation & lancement en 1 commande

Copiez-collez dans votre terminal : le skill s'installe dans ~/.claude/skills et Claude Code se lance directement dessus.

macOS / Linux
curl -fsSL https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.sh | sh -s -- dev-unit-test-generator --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } dev-unit-test-generator -Launch"

🚀 Déjà installé ?

claude "/dev-unit-test-generator"

Ou tapez /dev-unit-test-generator dans une session Claude Code, ou décrivez simplement votre besoin — le skill se déclenche automatiquement via le skill-router.

🔑 Déclencheurs automatiques

Le skill s'active automatiquement quand votre demande contient :

test unitaireunit testtester mon codejestxunitpytestmochaJUnitécrire des testscouverture de tests

📦 Installation manuelle

git clone https://github.com/khalilbenaz/claude-skills-collection.git cp -r claude-skills-collection/skills/dev-unit-test-generator ~/.claude/skills/

Payload du plugin : skills/dev-unit-test-generator · source éditable : dev-skills/unit-test-generator

📖 Manuel

Unit Test Generator

Workflow

Étape 1 — Analyser le code à tester

Étape 2 — Choisir le bon framework

LangageFramework principalAssertion / Mock
TypeScript / JSJest ou Vitest (ESM natif)@testing-library, vi.mock
Pythonpytestpytest-mock, unittest.mock
C# / .NETxUnitFluentAssertions, Moq / NSubstitute
JavaJUnit 5AssertJ, Mockito
Gotesting stdlibtestify/assert, testify/mock
Rust#[cfg(test)] intégrémockall si besoin
Critère de décision : si le projet a déjà un framework installé, l'utiliser ; si greenfield, préférer Vitest (TS), pytest (Python), xUnit (C#), JUnit 5 (Java).

Étape 3 — Identifier tous les cas de test

Pour chaque méthode publique, couvrir systématiquement :

  1. Happy path — entrée valide, résultat nominal.
  2. Edge casesnull, undefined, chaîne vide, liste vide, zéro, négatif, max value.
  3. Error cases — exception attendue, code d'erreur métier, état invalide.
  4. Interactions — appels aux dépendances (mock appelé N fois avec tels args).

Étape 4 — Mocker les dépendances

Principe : isoler la SUT (System Under Test) de tout ce qui n'est pas elle.

# Python — pytest-mock
def test_get_user_returns_none_when_not_found(mocker):
    repo = mocker.MagicMock()
    repo.find_by_id.return_value = None
    svc = UserService(repo)
    assert svc.get_user(99) is None
    repo.find_by_id.assert_called_once_with(99)
// C# — Moq + FluentAssertions
[Fact]
public void GetUser_ShouldReturnNull_WhenNotFound()
{
    var repo = new Mock<IUserRepository>();
    repo.Setup(r => r.FindById(99)).Returns((User?)null);
    var svc = new UserService(repo.Object);

    var result = svc.GetUser(99);

    result.Should().BeNull();
    repo.Verify(r => r.FindById(99), Times.Once);
}
// TypeScript — Vitest
import { vi, describe, it, expect } from 'vitest';
import { UserService } from './UserService';

describe('UserService.getUser', () => {
  it('returns null when user not found', async () => {
    const repo = { findById: vi.fn().mockResolvedValue(null) };
    const svc = new UserService(repo as any);
    expect(await svc.getUser(99)).toBeNull();
    expect(repo.findById).toHaveBeenCalledWith(99);
  });
});

Étape 5 — Écrire avec le pattern AAA

Arrange → Act → Assert  (une seule assertion logique par test)

Nommage : Should_<résultat>_When_<condition> ou <méthode>_<état>_<attendu>.

Étape 6 — Tests paramétrés pour les variations de données

# pytest
@pytest.mark.parametrize("amount,expected", [
    (0,     False),
    (-1,    False),
    (0.01,  True),
    (10_000, True),
])
def test_is_valid_amount(amount, expected):
    assert is_valid_amount(amount) == expected
// xUnit
[Theory]
[InlineData(0,      false)]
[InlineData(-1,     false)]
[InlineData(0.01,   true)]
[InlineData(10_000, true)]
public void IsValidAmount_ShouldMatchExpected(decimal amount, bool expected)
    => Assert.Equal(expected, PaymentValidator.IsValidAmount(amount));
// Vitest / Jest
it.each([
  [0,      false],
  [-1,     false],
  [0.01,   true],
  [10_000, true],
])('isValidAmount(%s) → %s', (amount, expected) => {
  expect(isValidAmount(amount)).toBe(expected);
});

Étape 7 — Vérifier la couverture

# Python
pytest --cov=src --cov-report=term-missing --cov-fail-under=80

# TypeScript (Vitest)
vitest run --coverage          # génère coverage/index.html

# .NET
dotnet test --collect:"XPlat Code Coverage"
reportgenerator -reports:coverage.cobertura.xml -targetdir:coverageReport

# Java (Maven + JaCoCo)
mvn test jacoco:report          # target/site/jacoco/index.html

Objectif minimal : 80 % lignes + 70 % branches sur le code métier. Ne pas poursuivre la couverture sur les DTOs, générés, migrations.

Étape 8 — Refactoring des tests


Garde-fous — anti-patterns à éviter

Anti-patternPourquoi c'est problématiqueCorrection
Tester des méthodes privées directementCouplage fort à l'implémentationTester via l'interface publique
Un seul test "dieu" qui couvre toutDiagnostics impossibles, maintenance difficile1 test = 1 comportement
Mock de tout (y compris la SUT elle-même)On ne teste plus rien de réelMocker uniquement les dépendances externes
Assert.True(result != null) flouMessage d'échec inutileresult.Should().NotBeNull() / assertNotNull(result, "msg")
Tests order-dependent (shared mutable state)Flaky selon l'ordre d'exécutionRéinitialiser l'état dans beforeEach
Faux positifs sur les exceptionstry/catch silencieux ou ThrowsAny trop largeVérifier le type exact + le message si critique
Tester des tiers (bibliothèques externes)Pas votre responsabilitéWrapper les tiers et tester le wrapper
Noms génériques (test1, testOK)Impossible de diagnostiquer sans lire le corpsConvention Should_X_When_Y obligatoire

Bonnes pratiques 2026