21 votes

Spécifier l'ordre d'exécution d'un scénario de test JUnit

J'ai un cas de test dans lequel j'ajoute une entité, je la mets à jour et je la supprime. L'ordre d'exécution est donc important. Je veux que ce soit :

  1. Créer
  2. Mise à jour
  3. Supprimer

Curieusement, pour un seul cas de test (sur 15), JUnit l'exécute dans l'ordre suivant :

  1. Supprimer
  2. Mise à jour
  3. Créer .

Comment puis-je demander à JUnit de les exécuter dans un ordre spécifique ? Dans d'autres cas, JUnit fonctionne parfaitement (exécution en série). Et pourquoi JUnit se comporte-t-il bizarrement dans ce cas précis ?

Vous trouverez ci-dessous un extrait de code pertinent :

    private static Date date;
    private static int entity;
    static Parking p;
    public ParkingTests(String name) {
       super(name);
    }
    public void testAdd() throws Exception {
           //Add code here
    }
    public void testUpdate() throws Exception {
            //update code here
    }
    public void testDelete() throws Exception {
            //delete code here
    }
  }

C'est de plus en plus bizarre. J'exécute de nombreux cas de test dans le cadre d'une suite. Si je n'exécute que le cas Parking, l'ordre est maintenu. Si je l'exécute avec d'autres, il est parfois maintenu, parfois non !

19voto

Kuldeep Jain Points 3017

En règle générale, les tests junit (méthodes de test) ne doivent pas dépendre les uns des autres. Ce qui suit est tiré de junit FAQ

Chaque test s'exécute dans son propre dispositif de test afin d'isoler les tests de l'environnement de travail. des modifications apportées par les autres tests. En d'autres termes, les tests ne partagent pas l'état des objets de la monture de test. dans le montage de test. Comme les tests sont isolés, ils peuvent être exécutés dans n'importe quel ordre...... L'ordre d'invocation des méthodes de test n'est pas garanti.

Ainsi, si vous souhaitez effectuer des opérations d'initialisation courantes, vous pouvez le faire dans la méthode annotée par @Before et le nettoyage dans la méthode annotée avec @After . Ou bien, si cette initialisation n'est pas nécessaire pour toutes les méthodes de votre classe de test, vous pouvez la placer dans des méthodes privées et les appeler de manière appropriée à partir de vos tests.

Par ailleurs, si vous souhaitez toujours commander des tests, vous pouvez consulter les sites suivants TestNG .

19voto

DNA Points 16180

Votre type de situation es maladroit, car il n'est pas souhaitable de continuer à dupliquer le travail afin d'isoler les tests (voir ci-dessous) - mais notez que la plupart de la duplication peut être retirée en setUp y tearDown ( @Before , @After ), de sorte que vous n'avez pas besoin de beaucoup de code supplémentaire. À condition que les tests ne soient pas si lents que vous cessiez de les exécuter souvent, il est préférable de gaspiller un peu d'unité centrale au nom de la propreté des tests.

public void testAdd() throws Exception {
      // wipe database
      // add something
      // assert that it was added
}
public void testUpdate() throws Exception {
      // wipe database
      // add something
      // update it
      // assert that it was updated
}
public void testDelete() throws Exception {
      // wipe database
      // add something
      // delete it
      // assert that it was deleted
}

L'autre solution consiste à tout regrouper dans un seul test avec plusieurs assertions, mais cela est plus difficile à comprendre et à maintenir, et donne un peu moins d'informations lorsqu'un test échoue :

public void testCRUD() throws Exception {
      // wipe database
      // add something
      // assert that it was added
      // update it
      // assert that it was updated
      // delete it 
      // assert that it was deleted
}

Il est difficile de tester des bases de données, des collections ou tout autre type de stockage, car un test peut toujours avoir une incidence sur les autres tests en laissant des déchets dans la base de données ou la collection. Même si vos tests ne s'appuient pas explicitement les uns sur les autres, ils peuvent toujours interférer les uns avec les autres, en particulier si l'un d'entre eux échoue.

Dans la mesure du possible, utilisez une nouvelle instance pour chaque test, ou effacez les données, idéalement de la manière la plus simple possible - par exemple, pour une base de données, l'effacement d'une table entière a plus de chances de réussir qu'une suppression très spécifique que vous pourriez accidentellement malencontreusement effectuer.

Mise à jour : Il est généralement préférable d'effacer les données au début du test, de sorte qu'un échec n'affecte pas le test suivant.

12voto

eis Points 14687

Si vous souhaitez avoir un ordre d'exécution pour vos tests, JUnit 4.11 le prend désormais en charge par le biais d'une annotation. Voir ce fil pour plus de détails - en gros, vous utiliseriez

@FixMethodOrder

pour garantir une certaine commande de test de cette manière. Cette pratique est toutefois déconseillée.

7voto

Joshua Wilson Points 1403

Si vous utilisez Java 7 alors vous devez savoir que Junit obtient la liste de tous les tests en utilisant "Method[] getDeclaredMethods()" de java.lang.Class. Vous pouvez lire dans la javadoc de cette méthode ou dans les docs de Junit que : " Les éléments du tableau renvoyé ne sont pas triés et ne sont pas dans un ordre particulier. "mais dans les implémentations précédentes de jvm, la liste des méthodes était ordonnée comme elle l'était dans le code source.

Ceci a été pris à partir de ce blog et il fournit une solution de contournement.

5voto

mudd Points 51

En général, JUnit ne garantit pas l'ordre des cas de test. L'ordre alphabétique n'est pas garanti, ni l'ordre dans le fichier. Si l'ordre des tests était important, l'un d'entre eux dépendrait de la sortie du précédent. Que se passerait-il si le premier test échouait ? Devrions-nous même nous préoccuper des tests ultérieurs (et dépendants) ? Probablement pas.

Donc, si nous avions ceci :

@Test
public void first(){...}

@Test
public void second() {...}

@Test
public void third() {...}

Nous ne savons pas dans quel ordre ils seront présentés. Puisque nous espérons qu'ils se dérouleront dans l'ordre, et que nous ne devrions probablement pas prendre la peine de nous présenter en deuxième ou troisième position si le(s) précédent(s) a (ont) échoué, nous pouvons faire ceci à la place :

@Test
public void firstThree(){
    first();
    second();
    third();
}

public void first(){...}
public void second() {...}
public void third() {...}

Remarquez que nous n'avons qu'un seul @Test cette fois-ci, et qu'il garantit l'ordre.

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