Spécifier un ordre à junit 4 tests au niveau de la méthode (pas au niveau de la classe)

Je sais que c’est une mauvaise pratique, mais il faut que ce soit fait, ou je devrai passer au testng . Existe-t-il un moyen, similaire à testSuite de JUnit 3, de spécifier l’ordre des tests à exécuter dans une classe?

Si vous êtes certain de vouloir vraiment faire ceci: il y a peut-être une meilleure façon, mais c’est tout ce que je pourrais trouver …

JUnit4 a une annotation: @RunWith qui vous permet de remplacer le Runner par défaut pour vos tests.

Dans votre cas, vous voudriez créer une sous-classe spéciale de BlockJunit4ClassRunner , et remplacer computeTestMethods() pour renvoyer des tests dans l’ordre dans computeTestMethods() vous souhaitez les exécuter. Par exemple, disons que je veux exécuter mes tests dans l’ordre alphabétique inverse:

 public class OrderedRunner extends BlockJUnit4ClassRunner { public OrderedRunner(Class klass) throws InitializationError { super(klass); } @Override protected List computeTestMethods() { List list = super.computeTestMethods(); List copy = new ArrayList(list); Collections.sort(copy, new Comparator() { public int compare(FrameworkMethod o1, FrameworkMethod o2) { return o2.getName().compareTo(o1.getName()); } }); return copy; } } 
 @RunWith(OrderedRunner.class) public class OrderOfTest { @Test public void testA() { System.out.println("A"); } @Test public void testC() { System.out.println("C"); } @Test public void testB() { System.out.println("B"); } } 

L’exécution de ce test produit:

  C
 B
 UNE 

Pour votre cas spécifique, vous souhaitez un comparateur qui sortingerait les tests par nom dans l’ordre dans lequel vous souhaitez les exécuter. (Je suggère de définir le comparateur en utilisant quelque chose comme la classe Ordering.explicit("methodName1","methodName2").onResultOf(...); Google Guava Ordering.explicit("methodName1","methodName2").onResultOf(...); où onResultOf fournit une fonction qui convertit la méthode FrameworkMet en son nom … vous êtes libre de l’implémenter comme vous le souhaitez.

Je peux voir plusieurs raisons à cela, en particulier lorsque vous utilisez JUnit pour exécuter des tests fonctionnels ou pour tester des objects persistants. Par exemple, considérons un object Article qui est conservé dans une sorte de stockage persistant. Si je souhaite tester la fonctionnalité d’insertion, de mise à jour et de suppression sur l’object Article suivant le principe du test unitaire “tous les tests doivent être réorganisables et ne tester qu’une partie spécifique de la fonctionnalité”, j’aurais trois tests:

  • testInsertArticle()
  • testUpdateArticle()
  • testDeleteArticle()

Cependant, pour pouvoir tester la fonctionnalité de mise à jour, je dois d’abord insérer l’article. Pour tester la fonctionnalité de suppression, je devrais également insérer un article. Ainsi, en pratique, la fonctionnalité d’insertion est déjà testée à la fois dans testUpdateArticle() et testDeleteArticle() . Il est alors tentant de simplement créer une méthode de test testArticleFunctionality() qui fait tout, mais les méthodes comme celle-ci finiront par devenir énormes (et elles ne testeront pas seulement une partie des fonctionnalités de l’object Article ).

Il en va de même pour l’exécution de tests fonctionnels sur, par exemple, une API reposante. JUnit est également idéal pour ces cas si ce n’était pour la commande indéterminée des tests.

Cela dit, j’ai étendu OrderedRunner Michael D pour utiliser les annotations afin de déterminer l’ordre des tests, mais je pensais juste que je devais les partager. Il peut être étendu davantage, par exemple en spécifiant exactement quels tests dépendent de chaque test, mais c’est ce que j’utilise pour l’instant.

C’est comme ça qu’il est utilisé. Cela évite d’avoir recours à des tests de nommage tels que AA_testInsert() , AB_testUpdate() , AC_testDelete() , …, ZC_testFilter() , etc.

 @RunWith(OrderedRunner.class) public class SomethingTest { @Test @Order(order=2) public void testUpdateArticle() { // test update } @Test @Order(order=1) public void testInsertArticle() { // test insert } @Test @Order(order=3) public void testDeleteArticle() { // test delete } } 

Peu importe la façon dont ces tests sont placés dans le fichier, ils seront toujours exécutés en order=1 premier, order=2 seconde et dernier order=3 , peu importe si vous les exécutez depuis Eclipse, en utilisant Ant ou tout autre moyen.

La mise en œuvre suit. Tout d’abord, l’ Order annotation.

 @Retention(RetentionPolicy.RUNTIME) public @interface Order { public int order(); } 

Ensuite, le OrderedRunner modifié.

 public class OrderedRunner extends BlockJUnit4ClassRunner { public OrderedRunner(Class klass) throws InitializationError { super(klass); } @Override protected List computeTestMethods() { List list = super.computeTestMethods(); Collections.sort(list, new Comparator() { @Override public int compare(FrameworkMethod f1, FrameworkMethod f2) { Order o1 = f1.getAnnotation(Order.class); Order o2 = f2.getAnnotation(Order.class); if (o1 == null || o2 == null) return -1; return o1.order() - o2.order(); } }); return list; } } 

A partir de la version 4.11 de JUnit, il est possible d’influencer l’ordre d’exécution des tests en annotant votre classe avec @FixMethodOrder et en spécifiant l’un des MethodSorters disponibles. Voir ce lien pour plus de détails.

En utilisant junit 4.11 la nouvelle annotation @FixMethodOrder permet de définir un ordre spécifique:

 @FixMethodOrder(MethodSorters.NAME_ASCENDING) 

Si vous souhaitez exécuter des tests de junit dans l’ordre “juste comme ils sont présents dans votre code source”, et ne souhaitez pas modifier votre code de test, consultez ma note à ce sujet ici:

Comment exécuter les tests de junit dans l’ordre qu’ils présentent dans votre code source

Mais ce n’est vraiment pas une bonne idée, les tests doivent être indépendants.

Joscarsson et Michael D code dans mon repository github. J’espère qu’ils ne s’en préoccupent pas. Je fournis également la version commandée pour la classe paramétrée. Il est déjà utilisé comme dépendance Maven

   git-xxx https://github.com/crsici/OrderedRunnerJunit4.11/raw/master/    com.sici.org.junit ordered-runner 0.0.1-RELEASE