JUnit: So vermeiden Sie "keine ausführbaren Methoden" in Test-Utils-Klassen

117

Ich habe von JUnit3.8 zu JUnit4.4 gewechselt. Ich führe meine Tests mit ant aus. Alle meine Tests werden erfolgreich ausgeführt, aber die Testdienstprogrammklassen schlagen mit dem Fehler "Keine ausführbaren Methoden" fehl. Das Muster, das ich verwende, besteht darin, alle Klassen mit dem Namen * Test * in den Testordner aufzunehmen.

Ich verstehe, dass der Läufer keine Methode finden kann, die mit dem @ Test-Attribut versehen ist. Sie enthalten jedoch keine solchen Anmerkungen, da diese Klassen keine Tests sind. Überraschenderweise beschwert es sich beim Ausführen dieser Tests in Eclipse nicht über diese Klassen.

In JUnit3.8 war dies überhaupt kein Problem, da diese Dienstprogrammklassen TestCase nicht erweiterten und der Runner nicht versuchte, sie auszuführen.

Ich weiß, dass ich diese spezifischen Klassen im Junit-Ziel in Ant Script ausschließen kann. Ich möchte die Build-Datei jedoch nicht bei jeder neuen Dienstprogrammklasse ändern, die ich hinzufüge. Ich kann die Klassen auch umbenennen (aber den Klassen gute Namen zu geben war immer mein schwächstes Talent :-))

Gibt es eine elegante Lösung für dieses Problem?

LiorH
quelle
Funktionieren Ihre Tests in Eclipse / NetBeans / Ihrer Lieblings-IDE?
Guerda
Ich benutze Eclipse. Eigentlich gibt es dort kein Problem, irgendwie versucht Eclipse nicht, diese Klassen auszuführen. Ich frage mich wie?
LiorH
Ich weiß nicht, ob wir Ihre Frage verstanden haben. Bitte lesen Sie Ihre Frage erneut und fügen Sie möglicherweise weitere Informationen hinzu.
Guerda
1
@ Guerda: Die Frage scheint mir ziemlich klar. Seine Ant-Aufgabe besteht darin, Klassen zu finden, die keine Tests enthalten, da der Filter die Utility-Klasse aufnimmt. Daher meine Antwort, die ich immer noch für absolut relevant halte.
Jon Skeet
LiorH: Danke für die Klarstellung, meine Antwort ist Verschwendung :)
Guerda

Antworten:

49

Angenommen, Sie haben die Kontrolle über das Muster, mit dem Testklassen gefunden werden, würde ich vorschlagen, es so zu ändern, dass es übereinstimmt *Testund nicht *Test*. Auf diese Weise TestHelperwird nicht abgestimmt, aber FooTestwird.

Jon Skeet
quelle
1
Ich denke nicht, dass es helfen würde, weil er zu JUnit 4.4 gewechselt ist und das sollte keine Rolle spielen.
Guerda
2
Sie scheinen den Punkt meiner Antwort verfehlt zu haben. Er hat einen Namensfilter, um die Klassen zu bestimmen, die als Tests betrachtet werden sollen. Wenn er den Filter wechselt, kann er die Hilfsklassen leicht ausschließen.
Jon Skeet
1
Ihr Vorschlag ist gültig, ich habe jedoch meine Testklassen überprüft und einige beginnen mit Test und andere enden mit Test. Keine klare Unterscheidung zwischen Utility-Klassen und realen Testklassen. Halten Sie die von Ihnen vorgeschlagene Konvention für eine gute Praxis? (dh Utils beginnen mit Test und Tests enden mit Test)
LiorH
4
Es ist fast eine Konvention, dass Sie die Testfallklassen mit * Test versehen. Möglicherweise müssen Sie eine Umgestaltung vornehmen, indem Sie die Testklassen entsprechend umbenennen und die Helfer umbenennen, damit sie diese Suffix-Konvention nicht verwenden.
Spoike
2
Ich stimme Spoike zu - wenn Sie anhand des Klassennamens nicht erkennen können, ob es sich um einen Test oder einen Helfer handelt, sollten Sie die Klasse umbenennen. Die Konvention lautet eher: "Die Klasse ist genau dann ein Test, wenn sie mit Test endet." Dienstprogrammklassen können mit Test beginnen oder nicht - es spielt keine Rolle.
Jon Skeet
142

Kommentieren Sie Ihre util-Klassen mit @Ignore. Dies führt dazu, dass JUnit nicht versucht, sie als Tests auszuführen.

JoelPM
quelle
6
Eigentlich sollte es nicht. @Ignore dient zum vorübergehenden Deaktivieren von Tests.
Alice Young
1
Entschuldigung, aber das ist eine schlechte Idee. Sie möchten Ihren Produktionscode mit testbezogenen Anmerkungen versehen, nur weil diese möglicherweise mit einem Testmuster übereinstimmen? Die richtige Antwort besteht darin, die Klassennamen zu korrigieren, wenn sie den Mustervergleich für Tests auslösen. Stellen Sie sicher, dass das Muster nur Klassen findet, die mit Test ENDEN. Das ist ein allgemein akzeptiertes Muster
Kevin M
Ja, das ist schlecht und ich habe es erst bemerkt, nachdem ich eine weitere positive Bewertung abgegeben habe, die ich nicht entfernen kann. Machen Sie Ihre Basisklasse abstrakt, dann ignoriert JUnit sie. Siehe die Antwort von @ gmoore unten.
Ryan Shillington
83

Mein spezieller Fall hat das folgende Szenario. Unsere Tests

public class VenueResourceContainerTest extends BaseTixContainerTest

alle erstrecken sich

BaseTixContainerTest

und JUnit versuchte BaseTixContainerTest auszuführen. Der arme BaseTixContainerTest hat nur versucht, den Container einzurichten, den Client einzurichten, Pizza zu bestellen und sich zu entspannen ... Mann.

Wie bereits erwähnt, können Sie die Klasse mit Anmerkungen versehen

@Ignore

Dies führte jedoch dazu, dass JUnit diesen Test als übersprungen meldete (im Gegensatz zu vollständig ignoriert).

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

Das hat mich irgendwie irritiert.

Also habe ich BaseTixContainerTest abstrakt gemacht und jetzt ignoriert JUnit es wirklich.

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
gmoore
quelle
7
Viel besser als@Ignore
Neworld
Ich versuchte , den @Ignore Ansatz und dachte, na ja , das ist gut, dann lese ich diese Antwort und schlug mir in die Stirn, „Of natürlich !“
Dnuttle
38

Um zu verhindern, dass JUnit Ihre Testbasisklasse instanziiert, machen Sie es einfach

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

(@Ignore meldet es als ignoriert, was ich für vorübergehend ignorierte Tests reserviere .)

froh42
quelle
3
JUnit-Läufer versuchen häufig, auch abstrakte Klassen zu instanziieren, und schlagen dann mit einem Instanziierungsfehler fehl.
Holly Cummins
Funktioniert perfekt für meine Basis-
Testklassen
3
Dies funktioniert aufgrund des Namens (es endet nicht mit Test), nicht aufgrund des abstrakten Modifikators. Ändern Sie den Klassennamen in MyBaseClassTest und es wird versucht, zu instanziieren, wie von @HollyCummins erwähnt (und fehlgeschlagen)
Hutch
In meinem Fall sollte es sein protected abstract class.
Mystic Lin
18
  1. Wenn dies Ihre Basistestklasse ist, zum Beispiel AbstractTest, und alle Ihre Tests dies erweitern, definieren Sie diese Klasse als abstrakt
  2. Wenn es sich um eine Util-Klasse handelt, entfernen Sie besser * Test aus der Umbenennung der Klasse in MyTestUtil oder Utils usw.
Raghu K Nair
quelle
10

Seien Sie vorsichtig, wenn Sie die Code-Vervollständigung einer IDE verwenden, um den Import für hinzuzufügen @Test.

Es muss zum Beispiel sein import org.junit.Testund nicht import org.testng.annotations.Test. Wenn Sie Letzteres tun, wird der Fehler "Keine ausführbaren Methoden" angezeigt.

Sridhar Sarnobat
quelle
Dies sollte eher ein Kommentar als eine Antwort sein.
Swaranga Sarma
3
Ich verstehe nicht warum. Es ist eine gültige Lösung.
Sridhar Sarnobat
4
Intellij Idea 2017 hat mich durch den Import durcheinander gebracht org.junit.jupiter.api.Test! aber dank dir ist es jetzt gelöst
AmiNadimi
Vielen Dank, ich war verwirrt, als ich das Problem "Keine ausführbaren Methoden" bekam.
Peter S.
7

Ant wird jetzt mit dem skipNonTestsAttribut geliefert, das genau das tun soll, wonach Sie suchen. Sie müssen Ihre Basisklassen nicht in abstrakt ändern oder ihnen Anmerkungen hinzufügen.

mc1arke
quelle
2
Es sieht so aus, als ob das skipNonTestsAttribut nur in Ant 1.9+ verfügbar ist, was schade ist, da es unglaublich nützlich aussieht. Es werden auch abstrakte Test-Superklassen ausgeschlossen.
Holly Cummins
4

Was ist mit dem Hinzufügen einer leeren Testmethode zu diesen Klassen?

public void avoidAnnoyingErrorMessageWhenRunningTestsInAnt() {
    assertTrue(true); // do nothing;
}
akuhn
quelle
8
aber das erhöht fälschlicherweise die Anzahl der Tests, die wir haben :) nicht, dass es eine große Sache ist
Sudarshan
1

In Ihrer Testklasse, wenn geschrieben import org.junit.jupiter.api.Test; lösche es und schreibe import org.junit.Test; In diesem Fall hat es auch bei mir funktioniert.

Illuminaten
quelle
1
Erstaunlicherweise hat es funktioniert. Ich habe manuell in der Windows-Befehlszeile ausgeführt. Ein weiteres Problem ist jedoch, dass @BeforeAllund @AfterAllnicht ausgeführt werden.
BingLi224
Anscheinend hat JUnit4 funktioniert (mit @BeforeClassund @AfterClass, aber JUnit5 nicht. Referenz: junit.org/junit5/docs/current/user-guide/#migrating-from-junit4
BingLi224
0

Ich hatte auch ein ähnliches Problem ("keine ausführbaren Methoden ...") beim Ausführen des einfachsten einfachen Codes (Verwenden von @Test, @Before usw.) und fand die Lösung nirgendwo. Ich habe Junit4 und Eclipse SDK Version 4.1.2 verwendet. Mein Problem wurde mit dem neuesten Eclipse SDK 4.2.2 behoben. Ich hoffe, dies hilft Menschen, die mit einem ähnlichen Problem zu kämpfen haben.

Rahul Vig
quelle