Question

Parfois, je rencontre un test unitaire qui n’affirme rien. L'exemple particulier que j'ai rencontré ce matin consistait à tester l'enregistrement d'un fichier journal lorsqu'une condition était remplie. L’hypothèse était que si aucune erreur n’était générée, le test était réussi.

Personnellement, cela ne me pose pas de problème, mais cela semble être un peu une "odeur de code". pour écrire un test unitaire auquel aucune assertion n'est associée.

Je me demandais ce que pensaient les gens à ce sujet?

Était-ce utile?

La solution

Ce serait la manière officielle de le faire:

// Act
Exception ex = Record.Exception(() => someCode());

// Assert
Assert.Null(ex);

Autres conseils

Il s’agit simplement d’un test très minimal et doit être documenté en tant que tel. Il vérifie seulement qu'il n'explose pas lorsqu'il est exécuté. Le pire dans les tests de ce type est qu’ils présentent un faux sentiment de sécurité. Votre couverture de code va augmenter, mais c'est illusoire. Très mauvaise odeur.

S'il n'y a pas d'assertion, ce n'est pas un test.

Cesser d’être paresseux - cela prendra peut-être un peu de temps pour comprendre comment obtenir l’affirmation, mais cela vaut la peine de savoir qu’il a fait ce que vous espériez.

Ils sont connus sous le nom de tests de détection de la fumée et sont courants. Ce sont des contrôles de base de la santé mentale. Mais ils ne devraient pas être les seuls types de tests que vous avez. Vous auriez toujours besoin d'une sorte de vérification dans un autre test.

Un tel test sent. Il convient de vérifier que le fichier a été écrit, du moins que l’heure modifiée a peut-être été mise à jour.

J'ai vu pas mal d'essais écrits de cette façon qui ont fini par ne rien tester du tout, c'est-à-dire que le code ne fonctionnait pas, mais il n'a pas explosé non plus.

Si vous souhaitez explicitement que le code testé ne lève pas d'exception et que vous souhaitiez explicitement appeler ce fait (tests en tant que document d'exigences), il vous faudrait alors procéder de la manière suivante:

try
{
  unitUnderTest.DoWork()
}
catch
{
  Assert.Fail("code should never throw exceptions but failed with ...")
}

... mais ça sent encore un peu pour moi, probablement parce qu'il essaie de prouver un négatif.

En un sens, vous faites une assertion implicite: le code ne lève pas d'exception. Bien sûr, il serait plus utile de saisir le fichier et de trouver la ligne appropriée, mais je suppose que quelque chose vaut mieux que rien.

En général, cela se produit fréquemment lors des tests d’intégration, mais le simple fait que quelque chose ait abouti est suffisant. Dans ce cas, je suis cool avec ça.

Je suppose que si je le voyais maintes et maintes fois dans les tests unitaires , je serais curieux de savoir à quel point les tests étaient vraiment utiles.

EDIT: Dans l'exemple donné par l'OP, il existe un résultat testable (résultat du fichier journal), donc si on suppose que si aucune erreur n'a été générée, cela a fonctionné.

Ce peut être une bonne solution pragmatique, surtout si l’alternative n’est pas du tout un test.

Le problème est que le test réussirait si toutes les fonctions appelées étaient no-ops. Mais parfois, il est tout simplement impossible de vérifier que les effets secondaires correspondent à ce que vous attendiez. Dans un monde idéal, il y aurait assez de temps pour rédiger les chèques pour chaque test ... mais je n'y vis pas.

Ce modèle est également utilisé pour intégrer des tests de performance dans les tests unitaires, car il permet de les exécuter facilement à chaque version. Les tests n’affirment rien, mais mesurent la durée du test et enregistrent cela.

J'ai déjà vu quelque chose comme cela auparavant et je pense que cela a été fait uniquement pour maintenir les numéros de couverture de code. Ce n'est probablement pas vraiment tester le comportement du code. Dans tous les cas, je conviens que cela (l’intention) devrait être documenté dans le test pour plus de clarté.

Le nom du test doit documenter ceci.

void TestLogDoesNotThrowException(void) {
    log("blah blah");
}

Comment le test vérifie-t-il que le journal est écrit sans assertion?

Je dois admettre que je n'ai jamais écrit de test unitaire pour vérifier que je me connectais correctement. Mais j’y ai réfléchi et je suis tombé sur cette discussion de comment cela pourrait être fait avec JUnit et Log4J. Ce n’est pas trop joli, mais il semble que cela fonctionnerait.

Les tests doivent toujours affirmer quelque chose, sinon que prouvez-vous et comment pouvez-vous reproduire de manière cohérente la preuve que votre code fonctionne?

Nous faisons cela tout le temps. Nous nous moquons de nos dépendances à l'aide de JMock, donc je suppose que dans un sens, le framework JMock fait l'assertion pour nous ... mais cela ressemble à autre chose. Nous souhaitons tester un contrôleur:

Class Controller {
  private Validator validator;

  public void control(){
    validator.validate;
  }

  public setValidator(Validator validator){ this.validator = validator; }
}

Désormais, lorsque nous testons Controller, nous ne souhaitons pas tester Validator car il comporte ses propres tests. nous avons donc un test avec JMock juste pour nous assurer que nous appelons valider:

public void testControlShouldCallValidate(){
  mockValidator.expects(once()).method("validate");
  controller.control;
}

Et c'est tout, il n'y a pas d '"affirmation". pour voir mais quand vous appelez le contrôle et le & valider & valider " méthode n’est pas appelée, le framework JMock vous lève une exception (quelque chose comme "la méthode attendue n’est pas appelée" ou quelque chose).

Nous les avons partout. C’est un peu en arrière puisque vous configurez votre assertion, ALORS appelez la méthode testée.

J'utilise parfois mon framework de choix de tests unitaires (NUnit) pour construire des méthodes qui servent de points d'entrée dans des parties spécifiques de mon code. Ces méthodes sont utiles pour définir les performances, la consommation de mémoire et la consommation de ressources d’un sous-ensemble du code.

Ces méthodes ne sont certainement pas des tests unitaires (même si elles sont marquées avec l'attribut [Test] ) et sont toujours signalées comme étant ignorées et explicitement documentées lorsqu'elles sont entrées dans le contrôle de source.

J'utilise aussi parfois ces méthodes comme points d'entrée pour le débogueur Visual Studio. J'utilise Resharper pour entrer directement dans le test, puis dans le code que je veux déboguer. Ces méthodes ne permettent pas d'atteindre le contrôle de source, ou acquièrent leurs propres assertions.

Mon " real " Les tests unitaires sont construits au cours de cycles TDD normaux, et ils affirment toujours quelque chose, bien que pas toujours directement. Parfois, les assertions font partie du cadre moqueur et parfois, je peux reformuler des affirmations similaires en une seule méthode. Les noms de ces méthodes refactorisées commencent toujours par le préfixe "Assert". pour le rendre évident pour moi.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top