71 votes

réglage/démontage (@Avant/@Après) pourquoi nous avons besoin d'eux dans JUnit?

Je crois que nous savons tous que le programme d'installation (@Avant) va s'exécuter avant toute méthode d'essai et tearDown(@Après) est exécutée après la méthode de test.

Nous savons aussi que Junit va créer une instance de Test par la méthode d'essai.

ma question est: que pouvons-nous déplacer méthode de configuration de contenu pour le Constructeur de la classe et de supprimer la méthode de configuration? est-il une raison spécifique pour les conserver méthode de configuration?

61voto

Pascal Thivent Points 295221

Ce (vieux) JUnit meilleures pratiques de l'article il met comme ceci:

Ne pas utiliser le test de cas constructeur pour définir un cas de test

La configuration d'un cas de test dans le le constructeur n'est pas une bonne idée. Considérer:

public class SomeTest extends TestCase
   public SomeTest (String testName) {
      super (testName);
      // Perform test set-up
   }
}

Imaginez que lors de l'exécution de la le programme d'installation, le programme d'installation de code génère une IllegalStateException. En réponse, JUnit jeter un AssertionFailedError, indiquant que le cas de test n'a pas pu être instanciée. Voici un exemple de la résultante de trace de la pile:

junit.framework.AssertionFailedError: Cannot instantiate test case: test1   
    at junit.framework.Assert.fail(Assert.java:143)
    at junit.framework.TestSuite.runTest(TestSuite.java:178)
    at junit.framework.TestCase.runBare(TestCase.java:129)
    at junit.framework.TestResult.protect(TestResult.java:100)
    at junit.framework.TestResult.runProtected(TestResult.java:117)
    at junit.framework.TestResult.run(TestResult.java:103)
    at junit.framework.TestCase.run(TestCase.java:120)
    at junit.framework.TestSuite.run(TestSuite.java, Compiled Code)
    at junit.ui.TestRunner2.run(TestRunner.java:429)

Cette trace de la pile s'avère plutôt peu utile; il indique seulement que le cas de test n'a pas pu être instanciée. Il n'a pas de détails sur le erreur d'origine ou d'emplacement de la place de de l'origine. Ce manque d'information rend il est difficile de déduire de l'exception cause sous-jacente.

Au lieu de mettre les données dans le constructeur, d'effectuer de test de l'installation par primordial setUp(). Toute exception jeté dans setUp() est rapporté correctement. Comparer cette trace de la pile avec l'exemple précédent:

java.lang.IllegalStateException: Oops
    at bp.DTC.setUp(DTC.java:34) 
    at junit.framework.TestCase.runBare(TestCase.java:127)
    at junit.framework.TestResult.protect(TestResult.java:100)
    at junit.framework.TestResult.runProtected(TestResult.java:117)
    at junit.framework.TestResult.run(TestResult.java:103)
    ...

Cette trace de la pile est beaucoup plus instructive; elle montre d'exception a été levée (IllegalStateException) et d'où l'. Qui le rend beaucoup plus facile pour expliquer la configuration de test est un échec.

30voto

BjornS Points 549

Au travail, nous avons découvert quelque chose d'assez intéressant qui répond à votre question. Lorsque vous exécutez une suite de tests, en particulier un grand nombre de tests (200+) JUnit commence à utiliser BEAUCOUP de mémoire, c'est parce que TOUS les tests sont instanciées avant toute méthode de test est exécuté.

Nous sommes tombés sur une "fuite de mémoire" à cause de cela parce que nous avons utilisés pour les ressorts à fil dans certains JPA EntiryManager des objets de notre base de données de tests, c'est devenu UN LOT d'objets et de beaucoup de mémoire et à environ mi-chemin par le biais de tests que nous recevions OutOfMemory exceptions.

À mon humble avis, la meilleure pratique consiste à utiliser l'installation et le démontage d'injecter des dépendances et null toutes les références de classe, cela permettra de faire vos tests de fonctionner plus rapidement et vous faire économiser beaucoup de maux de tête!

Espère que vous avez appris de nos erreurs :)

25voto

Bert F Points 27237

Voici 3 bonnes raisons à ça. En résumé:

  1. Certaines situations peuvent préfèrent reporter la configuration d'appareils de test aussi longtemps que possible, juste avant que le cas de test s'exécute.

  2. Certains des cas de test peut être partie d'un test de profondeur de cas hiérarchie d'héritage. Il peut être préférable de reporter la configuration d'appareils de test jusqu'à ce que la hiérarchie des constructeurs est terminé.

  3. Vous obtenez de meilleurs diagnostics si le code de programme d'installation échoue dans setUp() plutôt que si elle échoue dans le constructeur.

1. Reporter la configuration de luminaires jusqu'à ce que juste avant de cas de test

Conception pour la facilité d'utilisation
http://www.artima.com/weblogs/viewpost.jsp?thread=70189

... Et comme Elliotte Rusty Harold le mettre, si vous allez créer une nouvelle instance cas de test pour chaque méthode de test, "pourquoi diable s'embêter avec une méthode setUp ()?" Vous ne pouvez utiliser que les cas de test constructeur.

J'ai entendu parler de Bruce Eckel remarquer qu'il existe une différence subtile entre la création de votre appareil dans setUp() rapport de la créer dans le cas de test constructeur. JUnit crée tous les cas de test instances à l'avant, et ensuite, pour chaque instance, les appels setup(), la méthode d'essai, et tearDown(). En d'autres termes, la subtile différence est que les constructeurs sont tous invoquée dans le lot, tandis que la méthode setUp() est appelée juste avant chaque méthode de test. Mais cela ne semble pas être utile une différence dans la pratique.

2. Reporter la configuration de luminaires jusqu'à ce que tous les cas de test sont instanciés

ETutorial Java Programmation Extrême - 4.6 montage et le démontage de
http://etutorials.org/Programming/Java+extreme+programming/Chapter+4.+JUnit/4.6+Set+Up+and+Tear+Down/

Vous demandez peut-être pourquoi vous devriez écrire une méthode setUp( ) au lieu de simplement l'initialisation des champs dans un cas de test du constructeur. Après tout, depuis qu'une nouvelle instance de la situation de test est créé pour chacun de ses méthodes de test, le constructeur est toujours appelée avant setUp( ). Dans une grande majorité des cas, vous pouvez utiliser le constructeur au lieu de setUp( ) sans effets secondaires.

Dans le cas où votre cas de test est la partie plus d'une hiérarchie d'héritage, vous pouvez reporter l'initialisation de l'objet jusqu'à ce que les instances de la dérivée [test] les classes sont entièrement construits. C'est une bonne raison technique que vous pouvez utiliser setUp( ) au lieu d'un constructeur pour l'initialisation. À l'aide de setUp( ) et tearDown( ) est aussi bien à des fins de documentation, tout simplement parce qu'il peut rendre le code plus facile à lire.

3. Améliorer les outils de diagnostic en cas d'échec de l'installation

JUnit meilleures pratiques (JavaWorld)
http://www.javaworld.com/jw-12-2000/jw-1221-junit.html

La configuration d'un cas de test dans le constructeur n'est pas une bonne idée. ...

Imaginez [dans le code où l'installation est faite dans le cas du test constructeur] que lors de l'exécution du programme d'installation, le code d'installation déclenche une exception IllegalStateException. En réponse, JUnit jeter un AssertionFailedError, indiquant que le cas de test ne peut pas être instancié. ...

Cette trace de la pile [de une exception dans le code de configuration dans le cas du test constructeur] prouve assez peu; il indique seulement que le cas de test ne peut pas être instancié.

Au lieu de mettre les données dans le constructeur, effectuer l'installation d'essai en remplaçant setUp(). Toute exception jeté dans le setUp() est signalé correctement. ...

Cette trace de la pile [de une exception dans la méthode setUp() à la place du cas de test constructeur] est beaucoup plus instructive; elle montre exception a été levée (IllegalStateException) et à partir d'où. Qui le rend beaucoup plus facile à expliquer la configuration de test est un échec.

6voto

RichN Points 2615

Une coutume coureur comme SpringJUnit4ClassRunner peut être nécessaire d'exécuter certains codes entre le constructeur et l' @Before méthode. Dans ce cas, le coureur peut injecter une dépendance qui l' @Before méthodes besoins. Mais l'injection de dépendance ne peuvent être exécutés qu'après que l'objet est construit.

3voto

Steve B. Points 23227

La raison vous avez besoin de ceci est que, pour de nombreux tests, vous avez souvent besoin d'initialiser l'état avant chaque test de sorte que les tests peuvent tous faire des hypothèses sur l'état de départ, ils sont en cours d'exécution.

Supposons que votre classe de test enveloppe, de dire l'accès à la base. Après chaque test, vous voulez supprimer toutes les modifications de vos tests ont fait de la db - si vous n'avez pas à le faire, chaque test s'exécute sur un légèrement modifiée de la base de données. En outre, un essai donné peut voir un autre ensemble de changements si certains sous-ensemble des tests précédents ont échoué. Par exemple, supposons que test1 un insert, test2 vérifie que vous êtes une lecture précise de la taille de la table. Jour 1, test1 échoue, et 0 est correct. Jour 2, test1 réussit, et 1 est correcte?

BTW, junit prend également en charge @BeforeClass si tu veux faire mondial de l'installation, et l'installation et la teardowns sont facultatifs.

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