csharp-tunit

Par github · awesome-copilot

Obtenez les meilleures pratiques pour les tests unitaires TUnit, y compris les tests pilotés par les données

npx skills add https://github.com/github/awesome-copilot --skill csharp-tunit

Meilleures pratiques TUnit

Votre objectif est de vous aider à écrire des tests unitaires efficaces avec TUnit, couvrant à la fois les approches de test standard et data-driven.

Configuration du projet

  • Utilisez un projet de test séparé avec la convention de nommage [NomDuProjet].Tests
  • Référencez le package TUnit et TUnit.Assertions pour les assertions fluentes
  • Créez des classes de test qui correspondent aux classes testées (par ex. CalculatorTests pour Calculator)
  • Utilisez les commandes de test du SDK .NET : dotnet test pour exécuter les tests
  • TUnit nécessite .NET 8.0 ou une version supérieure

Structure des tests

  • Aucun attribut de classe de test requis (comme xUnit/NUnit)
  • Utilisez l'attribut [Test] pour les méthodes de test (pas [Fact] comme xUnit)
  • Suivez le modèle Arrange-Act-Assert (AAA)
  • Nommez les tests selon le modèle NomDeLaMéthode_Scénario_ComportementAttendu
  • Utilisez les hooks de cycle de vie : [Before(Test)] pour la configuration et [After(Test)] pour le nettoyage
  • Utilisez [Before(Class)] et [After(Class)] pour le contexte partagé entre les tests d'une classe
  • Utilisez [Before(Assembly)] et [After(Assembly)] pour le contexte partagé entre les classes de test
  • TUnit prend en charge les hooks de cycle de vie avancés comme [Before(TestSession)] et [After(TestSession)]

Tests standard

  • Gardez les tests focalisés sur un seul comportement
  • Évitez de tester plusieurs comportements dans une seule méthode de test
  • Utilisez la syntaxe d'assertion fluente de TUnit avec await Assert.That()
  • Incluez uniquement les assertions nécessaires pour vérifier le cas de test
  • Rendez les tests indépendants et idempotents (peuvent s'exécuter dans n'importe quel ordre)
  • Évitez les interdépendances entre tests (utilisez l'attribut [DependsOn] si nécessaire)

Tests data-driven

  • Utilisez l'attribut [Arguments] pour les données de test inline (équivalent à [InlineData] de xUnit)
  • Utilisez [MethodData] pour les données de test basées sur une méthode (équivalent à [MemberData] de xUnit)
  • Utilisez [ClassData] pour les données de test basées sur une classe
  • Créez des sources de données personnalisées en implémentant ITestDataSource
  • Utilisez des noms de paramètres significatifs dans les tests data-driven
  • Plusieurs attributs [Arguments] peuvent être appliqués à la même méthode de test

Assertions

  • Utilisez await Assert.That(value).IsEqualTo(expected) pour l'égalité des valeurs
  • Utilisez await Assert.That(value).IsSameReferenceAs(expected) pour l'égalité des références
  • Utilisez await Assert.That(value).IsTrue() ou await Assert.That(value).IsFalse() pour les conditions booléennes
  • Utilisez await Assert.That(collection).Contains(item) ou await Assert.That(collection).DoesNotContain(item) pour les collections
  • Utilisez await Assert.That(value).Matches(pattern) pour la correspondance avec une expression régulière
  • Utilisez await Assert.That(action).Throws<TException>() ou await Assert.That(asyncAction).ThrowsAsync<TException>() pour tester les exceptions
  • Enchaînez les assertions avec l'opérateur .And : await Assert.That(value).IsNotNull().And.IsEqualTo(expected)
  • Utilisez l'opérateur .Or pour les conditions alternatives : await Assert.That(value).IsEqualTo(1).Or.IsEqualTo(2)
  • Utilisez .Within(tolerance) pour les comparaisons DateTime et numériques avec tolérance
  • Toutes les assertions sont asynchrones et doivent être attendues

Fonctionnalités avancées

  • Utilisez [Repeat(n)] pour répéter les tests plusieurs fois
  • Utilisez [Retry(n)] pour les tentatives automatiques en cas d'échec
  • Utilisez [ParallelLimit<T>] pour contrôler les limites d'exécution parallèle
  • Utilisez [Skip("raison")] pour ignorer les tests de manière conditionnelle
  • Utilisez [DependsOn(nameof(OtherTest))] pour créer des dépendances entre tests
  • Utilisez [Timeout(millisecondes)] pour définir les délais d'expiration des tests
  • Créez des attributs personnalisés en étendant les attributs de base de TUnit

Organisation des tests

  • Groupez les tests par fonctionnalité ou composant
  • Utilisez [Category("NomDeLaCatégorie")] pour la catégorisation des tests
  • Utilisez [DisplayName("Nom du test personnalisé")] pour les noms de test personnalisés
  • Envisagez d'utiliser TestContext pour les diagnostics et informations de test
  • Utilisez les attributs conditionnels comme [WindowsOnly] personnalisé pour les tests spécifiques à une plateforme

Performance et exécution parallèle

  • TUnit exécute les tests en parallèle par défaut (contrairement à xUnit qui nécessite une configuration explicite)
  • Utilisez [NotInParallel] pour désactiver l'exécution parallèle pour les tests spécifiques
  • Utilisez [ParallelLimit<T>] avec des classes de limite personnalisées pour contrôler la concurrence
  • Les tests d'une même classe s'exécutent séquentiellement par défaut
  • Utilisez [Repeat(n)] avec [ParallelLimit<T>] pour les scénarios de test de charge

Migration depuis xUnit

  • Remplacez [Fact] par [Test]
  • Remplacez [Theory] par [Test] et utilisez [Arguments] pour les données
  • Remplacez [InlineData] par [Arguments]
  • Remplacez [MemberData] par [MethodData]
  • Remplacez Assert.Equal par await Assert.That(actual).IsEqualTo(expected)
  • Remplacez Assert.True par await Assert.That(condition).IsTrue()
  • Remplacez Assert.Throws<T> par await Assert.That(action).Throws<T>()
  • Remplacez le constructeur/IDisposable par [Before(Test)]/[After(Test)]
  • Remplacez IClassFixture<T> par [Before(Class)]/[After(Class)]

Pourquoi TUnit plutôt que xUnit ?

TUnit offre une expérience de test moderne, rapide et flexible avec des fonctionnalités avancées absentes de xUnit, comme les assertions asynchrones, des hooks de cycle de vie plus affinés et des capacités de test data-driven améliorées. Les assertions fluentes de TUnit fournissent une validation de test plus claire et plus expressive, ce qui la rend particulièrement adaptée aux projets .NET complexes.

Skills similaires