97 votes

Ce qui Fait un Bon Test de l'Unité?

Je suis sûr que la plupart d'entre vous sont en écrivant beaucoup de tests automatisés et que vous avez également exécuter dans certains pièges courants lors de tests unitaires.

Ma question est pensez-vous suivez toutes les règles de conduite pour l'écriture de tests afin d'éviter des problèmes à l'avenir? Pour être plus précis: Quelles sont les propriétés de bons tests unitaires ou comment écrivez-vous vos tests?

Langue agnostique suggestions sont encouragés.

93voto

Gishu Points 59012

Permettez-moi de commencer par brancher des sources - Pragmatique de Tests Unitaires en Java avec JUnit (Il y a une version avec C#-Nunit trop.. mais j'ai celui-ci.. sa agnostique, pour la plupart. Recommandé).

De bons Tests devrait être UN VOYAGE (Le acronymn n'est pas assez collant - je avoir une impression de la triche dans le livre que j'avais pour s'en sortir assurez-vous que j'ai obtenu ce droit..)

  • Automatique : l'Invocation de tests ainsi que les résultats de vérification de réussite/d'ÉCHEC devrait être automatique
  • Approfondie: la Couverture; Bien que les bugs ont tendance à se regrouper autour de certaines régions dans le code, assurez-vous de tester tous les chemins de clés et scénarios.. l'Utilisation d'outils si vous devez savoir non testé régions
  • Reproductible: les Tests devraient produire les mêmes résultats à chaque fois ... à chaque fois. Les Tests ne doivent pas compter sur incontrôlables params.
  • Indépendant: Très important.
    • Les Tests doivent tester qu'une seule chose à la fois. Plusieurs affirmations sont d'accord, tant qu'ils sont tous les tests d'une fonction/comportement. Lorsqu'un test échoue, il doit localiser l'emplacement du problème.
    • Les Tests ne doivent pas compter les uns sur les autres - Isolé. Aucune des hypothèses au sujet de l'ordre de l'exécution des tests. Assurer la "table rase" avant chaque test en utilisant le programme d'installation/démontage de façon appropriée
  • Professionnel: Dans le long terme, vous aurez comme beaucoup de test de code de la production (si pas plus), donc de respecter la même norme de la bonne conception de votre code de test. Bien compte des méthodes de classes avec l'intention de révéler les noms, Pas de duplication, les tests avec les bons noms, etc.

  • Bon, les tests exécution Rapide. un test qui prend plus d'une demi-seconde pour exécuter.. doit être travaillé sur. Le plus de la suite de test prend pour une course.. le moins souvent, il sera exécuté. Le plus de changements de dev va essayer de se faufiler entre les courses. si quoi que ce soit casse.. il faudra plus de temps à comprendre que le changement était le coupable.

Mise à jour 2010-08:

  • Lisible : Cela peut être considéré comme faisant partie de la formation Professionnelle - toutefois, il ne peut pas être assez souligné. Un test à l'acide serait de trouver quelqu'un qui ne fait pas partie de votre équipe et lui demander de déterminer le comportement en cours de test au sein d'un couple de minutes. Les Tests doivent être maintenus, tout comme la production de code afin de le rendre facile à lire, même si cela prend plus d'effort. Les Tests doivent être symétrique (un modèle) et concis (test d'un comportement à un moment). Utiliser une convention d'appellation cohérente (par exemple, la TestDox style). Évitez d'encombrer le test avec "accessoires de détails".. devenir un minimaliste.

En dehors de ces, la plupart des autres sont des lignes directrices qui coupe vers le bas sur le bas de la prestation de travail: par exemple, " Ne pas tester le code que vous ne possédez pas (par exemple, les Dll de tiers). N'allez pas sur le test de getters et setters. Gardez un œil sur le rapport coût-bénéfice ou d'un défaut de probabilité.

42voto

Sören Kuklau Points 9445
  1. Ne pas écrire ginormous tests. Comme "unité" dans "test unitaire" suggère, faire de chacun comme atomique et isolé que possible. Si vous devez, créez les conditions préalables à l'aide des objets fantaisie, plutôt que de les recréer trop typique de l'environnement de l'utilisateur manuellement.
  2. Ne pas tester des choses que de toute évidence le travail. Éviter de tester les classes à partir d'un fournisseur tiers, en particulier celle alimentant le noyau de l'Api du framework code. E. g., ne pas tester l'ajout d'un élément dans le fournisseur de la classe Hashtable.
  3. Envisagez d'utiliser un outil de couverture de code comme NCover pour aider à la découverte de bord des cas, vous n'avez pas encore de test.
  4. Essayez d'écrire le test avant la mise en œuvre. Pensez à l'essai, comme plus d'un cahier des charges que votre application va adhérer. Cf. aussi behavior-driven development, un plus spécifiques de la branche de développement piloté par les tests.
  5. Être cohérent. Si vous écrivez des tests pour certains de votre code, il est à peine utile. Si vous travaillez dans une équipe, et de certains ou de tous les autres ne sont pas d'écrire des tests, il n'est pas très utile non plus. Laissez-vous convaincre et tous les autres de l'importance (et de gain de temps, propriétés) de l'essai, ou de ne pas les déranger.

41voto

womp Points 71924

La plupart des réponses ici semblent l'adresse de l'unité de tester les meilleures pratiques en général (quand, où, pourquoi et quoi), plutôt qu'à écrire les tests eux-mêmes (comment). Puisque la question semble assez spécifique sur le "comment", je pensais que je poste ce, prises à partir d'un "brown bag" présentation que j'ai réalisée dans mon entreprise.

Womp 5 des Lois de l'Écriture de Tests:


1. L'utilisation de long, descriptif de la méthode de test des noms.

   - Map_DefaultConstructorShouldCreateEmptyGisMap()
   - ShouldAlwaysDelegateXMLCorrectlyToTheCustomHandlers()
   - Dog_Object_Should_Eat_Homework_Object_When_Hungry()

2. Écrire vos tests dans un Arrangement/Act/Affirmer un style.

  • Bien que cette stratégie de l'organisation a été autour pendant un certain temps et appelé beaucoup de choses, l'introduction de la "AAA" de l'acronyme a récemment un excellent moyen pour obtenir ce travers. De faire de tous vos tests compatible avec AAA style rend facile à lire et à maintenir.

3. Toujours fournir un message d'échec avec vos Affirmations.

Assert.That(x == 2 && y == 2, "An incorrect number of begin/end element 
processing events was raised by the XElementSerializer");
  • Un simple mais enrichissante pratique qui rend évident dans votre coureur de l'application de ce qui a échoué. Si vous ne fournissez pas un message, vous devriez obtenir quelque chose comme "s'Attendre à vrai, était faux" dans votre échec de sortie, ce qui fait que vous avez à aller lire le test pour savoir quel est le problème.

4. Commentaire la raison pour laquelle le test – quelle est l'hypothèse d'affaires?

  /// A layer cannot be constructed with a null gisLayer, as every function 
  /// in the Layer class assumes that a valid gisLayer is present.
  [Test]
  public void ShouldNotAllowConstructionWithANullGisLayer()
  {
  }
  • Cela peut sembler évident, mais ce la pratique permettra de protéger l'intégrité de vos tests de personnes qui n'ont pas comprendre la raison derrière le test dans la première place. J'ai vu beaucoup de les tests d'obtenir supprimé ou modifié ont été parfaitement bien, tout simplement parce que la personne n'a pas compris la les hypothèses que le test a été la vérification.
  • Si le test est trivial ou la méthode le nom est suffisamment clair, il peut être permis de laisser la commentaire off.

5. Chaque test doit toujours revenir à l'état de toutes les ressources qu'il touche

  • Mocker, si possible, afin d'éviter ressources réelles.
  • Le nettoyage doit être effectué à l'essai niveau. Les Tests ne doivent avoir aucun la dépendance sur l'ordre d'exécution.

17voto

Mendelt Points 21583

Garder ces objectifs à l'esprit (adapté du livre xUnit des Modèles de Test par Meszaros)

  • Les Tests devraient réduire le risque, de ne pas l'introduire.
  • Les Tests doivent être faciles à exécuter.
  • Les Tests doivent être faciles à entretenir que le système évolue autour d'eux

Quelques trucs pour rendre cela plus facile:

  • Tests ne doivent échouer à cause de l' l'une des raisons.
  • Les Tests ne devraient tester un truc
  • Minimiser les dépendances des tests (pas de dépendances sur fichiers, bases de données, l'interface utilisateur etc.)

N'oubliez pas que vous pouvez faire de l'insertion des tests avec votre xUnit cadre trop , mais garder l'insertion des tests unitaires et de tests distincts

9voto

Jay Bazuzi Points 20462

Certaines propriétés d'une grande unité de tests:

  • Lorsqu'un test échoue, il doit être immédiatement évident de savoir où se trouve le problème. Si vous devez utiliser le débogueur pour traquer le problème, vos tests ne sont pas granulaire assez. Avoir exactement une affirmation par test permet ici.

  • Lorsque vous refactoriser, pas de tests doit échouer.

  • Les Tests doivent courir si vite que vous n'hésitez jamais à les exécuter.

  • Tous les tests doivent passer toujours; pas de non-déterministe résultats.

  • Les tests unitaires doivent être bien compte, tout comme votre code de production.

@Alotor: Si vous êtes suggérant qu'une bibliothèque ne devrait avoir que des tests unitaires à son API externe, je suis en désaccord. Je veux des tests unitaires pour chaque classe, y compris les classes que je ne l'exposez pas à des appelants externes. (Cependant, si je ressens le besoin d'écrire des tests pour les méthodes privées, alors j'ai besoin de refactoriser.)


EDIT: Il y avait un commentaire à propos de la duplication causée par "une affirmation par test". Plus précisément, si vous avez un peu de code pour définir un scénario, et que vous souhaitez faire plusieurs affirmations à ce sujet, mais seulement une affirmation par test, vous pouvez dupliquer l'installation à travers de multiples tests.

Je ne prends pas cette approche. Au lieu de cela, j'utilise des appareils de test par scénario. Voici un exemple grossier:

[TestFixture]
public class StackTests
{
    [TestFixture]
    public class EmptyTests
    {
        Stack<int> _stack;

        [TestSetup]
        public void TestSetup()
        {
            _stack = new Stack<int>();
        }

        [TestMethod]
        [ExpectedException (typeof(Exception))]
        public void PopFails()
        {
            _stack.Pop();
        }

        [TestMethod]
        public void IsEmpty()
        {
            Assert(_stack.IsEmpty());
        }
    }

    [TestFixture]
    public class PushedOneTests
    {
        Stack<int> _stack;

        [TestSetup]
        public void TestSetup()
        {
            _stack = new Stack<int>();
            _stack.Push(7);
        }

        // Tests for one item on the stack...
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X