JUnit: comment éviter «aucune méthode exécutable» dans les classes d'utils de test

118

Je suis passé à JUnit4.4 depuis JUnit3.8. J'exécute mes tests en utilisant ant, tous mes tests s'exécutent avec succès mais les classes d'utilitaires de test échouent avec l'erreur "Aucune méthode exécutable". Le modèle que j'utilise consiste à inclure toutes les classes avec le nom * Test * sous le dossier de test.

Je comprends que le coureur ne trouve aucune méthode annotée avec l'attribut @Test. Mais ils ne contiennent pas une telle annotation car ces classes ne sont pas des tests. Étonnamment, lors de l'exécution de ces tests dans eclipse, il ne se plaint pas de ces classes.

Dans JUnit3.8, ce n'était pas du tout un problème puisque ces classes d'utilitaires n'étendaient pas TestCase, donc le coureur n'a pas essayé de les exécuter.

Je sais que je peux exclure ces classes spécifiques dans la cible junit dans le script ant. Mais je ne veux pas changer le fichier de construction à chaque nouvelle classe d'utilitaire que j'ajoute. Je peux aussi renommer les classes (mais donner de bons noms aux classes a toujours été mon talent le plus faible :-))

Existe-t-il une solution élégante à ce problème?

LiorH
la source
Vos tests fonctionnent-ils dans Eclipse / NetBeans / votre IDE préféré?
guerda
J'utilise eclipse. En fait, il n'y a aucun problème, eclipse n'essaye pas d'exécuter ces classes. Je me demande comment?
LiorH
Je ne sais pas si nous avons compris votre question. Veuillez relire votre question et ajouter probablement des informations supplémentaires.
guerda
1
@guerda: La question me semble assez claire. Sa tâche Ant consiste à trouver des classes qui ne contiennent pas de tests, car le filtre récupère la classe utilitaire. D'où ma réponse, que je crois toujours tout à fait pertinente.
Jon Skeet
LiorH: Merci pour la clarification, donc ma réponse est gaspillage :)
guerda

Réponses:

50

En supposant que vous contrôliez le modèle utilisé pour trouver les classes de test, je vous suggère de le changer pour qu'il corresponde *Testplutôt que *Test*. De cette façon TestHelperne sera pas égalé, mais le FooTestsera.

Jon Skeet
la source
1
Je ne pense pas que cela aiderait, car il est passé à JUnit 4.4 et cela ne devrait pas avoir d'importance.
guerda
2
Vous semblez avoir manqué le point de ma réponse. Il dispose d'un filtre de nom pour déterminer les classes à considérer comme des tests. S'il change le filtre, il peut facilement exclure les classes d'assistance.
Jon Skeet
1
Votre suggestion est valide, mais j'ai vérifié mes classes de tests et certaines commencent par Test et d'autres se terminent par Test. pas de distinction claire entre les classes d'utilité et les classes de test réelles. Pensez-vous que la convention que vous avez suggérée est une bonne pratique? (c'est-à-dire que les utils commencent par Test et les tests se terminent par Test)
LiorH
4
C'est presque une convention que vous suffixez les classes de testcase avec * Test. Vous devrez peut-être refactoriser en renommant les classes de test de manière appropriée et également renommer les helpers afin qu'ils n'utilisent pas cette convention de suffixe.
Spoike
2
Je suis d'accord avec Spoike - si vous ne pouvez pas dire à partir du nom de la classe s'il s'agit d'un test ou d'un assistant, vous devez renommer la classe. La convention est plutôt "la classe est un test si et seulement si elle se termine par Test." Les classes d'utilité peuvent ou non commencer par Test - cela n'a pas d'importance.
Jon Skeet
142

Annotez vos classes util avec @Ignore. Cela empêchera JUnit d'essayer de les exécuter en tant que tests.

JoelPM
la source
6
En fait, non, ça ne devrait pas. @Ignore sert à désactiver temporairement les tests.
Alice Young
1
Désolé mais c'est une mauvaise idée. Vous souhaitez commencer à annoter votre code de production avec des annotations liées aux tests simplement parce qu'elles peuvent correspondre à un modèle de test? La bonne réponse est de corriger les noms de classe s'ils déclenchent la correspondance de modèle pour les tests. Et assurez-vous que le modèle ne trouve que les classes qui se terminent par Test. C'est un modèle communément accepté
Kevin M
Oui, c'est mauvais et je ne m'en suis rendu compte qu'après avoir contribué à un autre vote positif que je ne peux pas supprimer. Rendez votre classe de base abstraite, puis JUnit l'ignorera. Voir la réponse de @ gmoore ci-dessous.
Ryan Shillington
83

Mon cas spécifique a le scénario suivant. Nos tests

public class VenueResourceContainerTest extends BaseTixContainerTest

tous s'étendent

BaseTixContainerTest

et JUnit essayait d'exécuter BaseTixContainerTest. Le pauvre BaseTixContainerTest essayait juste de configurer le conteneur, de configurer le client, de commander une pizza et de se détendre ... mec.

Comme mentionné précédemment, vous pouvez annoter la classe avec

@Ignore

Mais cela a amené JUnit à signaler ce test comme ignoré (par opposition à complètement ignoré).

Tests run: 4, Failures: 0, Errors: 0, Skipped: 1

Cela m'a énervé.

J'ai donc fait de BaseTixContainerTest un résumé, et maintenant JUnit l'ignore vraiment.

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
gmoore
la source
7
Bien mieux que@Ignore
neworld
J'ai essayé l'approche @Ignore et j'ai pensé, eh bien c'est bien, puis j'ai lu cette réponse et je me suis giflé au front: "Bien sûr !"
navette du
38

Pour empêcher JUnit d'instancier votre classe de base de test, faites-le simplement

public abstract class MyTestBaseClass { ... whatever... }

(@Ignore le signale comme ignoré, ce que je réserve pour les tests temporairement ignorés.)

froh42
la source
3
Les exécuteurs JUnit essaient souvent d'instancier également des classes abstraites, puis échouent avec une erreur d'instanciation.
Holly Cummins
Fonctionne parfaitement pour mes classes de test de base
ruX
3
Cela fonctionne à cause du nom (il ne se termine pas par Test), pas à cause du modificateur abstrait. Changez le nom de la classe en MyBaseClassTest et il essaiera de s'instancier comme mentionné par @HollyCummins (et échouera)
Hutch
Dans mon cas, ça devrait l'être protected abstract class.
Mystic Lin
18
  1. S'il s'agit de votre classe de test de base, par exemple AbstractTest et que tous vos tests l'étendent, définissez cette classe comme abstraite
  2. Si c'est la classe Util, mieux vaut supprimer * Test de la classe renommer c'est MyTestUtil ou Utils etc.
Raghu K Nair
la source
10

Soyez prudent lorsque vous utilisez la complétion de code d'un IDE pour ajouter l'importation pour @Test.

Cela doit être import org.junit.Testet non import org.testng.annotations.Test, par exemple. Si vous faites ce dernier, vous obtiendrez l'erreur "aucune méthode exécutable".

Sridhar Sarnobat
la source
Cela devrait être un commentaire plutôt qu'une réponse.
Swaranga Sarma
3
Je ne vois pas pourquoi. C'est une solution valable.
Sridhar Sarnobat
4
Intellij Idea 2017 dérangeait mon esprit en important à la org.junit.jupiter.api.Testplace! mais grâce à vous c'est résolu maintenant
AmiNadimi
Merci beaucoup, j'étais confus lors de l'obtention du problème "pas de méthodes exécutables".
Peter S.
7

Ant est maintenant livré avec l' skipNonTestsattribut qui a été conçu pour faire exactement ce que vous semblez rechercher. Inutile de changer vos classes de base en abstraites ou d'y ajouter des annotations.

mc1arke
la source
2
Il semble que l' skipNonTestsattribut n'est disponible que dans ant 1.9+, ce qui est dommage, car il semble incroyablement utile. Cela exclura également les superclasses de test abstraites.
Holly Cummins
4

Qu'en est-il d'ajouter une méthode de test vide à ces classes?

public void avoidAnnoyingErrorMessageWhenRunningTestsInAnt() {
    assertTrue(true); // do nothing;
}
Akuhn
la source
8
mais cela augmente faussement le nombre de tests que nous avons :) pas que ce soit un gros problème
Sudarshan
1

Dans votre classe de test si écrit import org.junit.jupiter.api.Test; supprimez-le et écrivez import org.junit.Test; Dans ce cas, cela m'a aussi fonctionné.

illuminatos
la source
1
étonnamment, cela a fonctionné. J'ai exécuté manuellement dans la ligne de commande Windows. cependant, un autre problème est que @BeforeAllet @AfterAllne sont pas exécutés.
BingLi224
apparemment, JUnit4 a fonctionné (avec @BeforeClasset @AfterClass, mais pas JUnit5. Référence: junit.org/junit5/docs/current/user-guide/#migrating-from-junit4
BingLi224
0

J'étais également confronté à un problème similaire ("pas de méthodes exécutables ..") sur l'exécution du morceau de code le plus simple (en utilisant @Test, @Before etc.) et je n'ai trouvé la solution nulle part. J'utilisais Junit4 et Eclipse SDK version 4.1.2. J'ai résolu mon problème en utilisant le dernier SDK Eclipse 4.2.2. J'espère que cela aidera les personnes aux prises avec un problème un peu similaire.

Rahul Vig
la source