Bei Verwendung des parametrisierten Runners gibt es keine Möglichkeit, nur eine Testmethode einer Testklasse auszuführen.
Zum Beispiel bei der Ausführung in Maven: mvn test -Dtest=TesClass#testName
Bei Verwendung des parametrisierten Läufers werden keine Tests ausgeführt.
Das wäre toll, diese Funktion zu haben, denn für die Entwicklung ist es üblich, dass die Entwickler versuchen, nur den Test auszuführen, an dem sie gerade arbeiten.
Dies zu beheben wäre großartig, da wir am Ende UTs in großen Testklassen kommentieren müssen, was unerwünscht ist.
Das Maven Surefire Plugin erlaubt die Angabe von Globs (siehe http://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html). Hast du das probiert?
Ja, so würden wir es gerne nutzen, aber es funktioniert nicht. Sagen Sie, dass dies ein Problem des todsicheren Plugins ist und nicht von junit?
@diogoeag Ich glaube, es ist ein Problem mit dem Surefire-Plugin. Sie können dies überprüfen, indem Sie eine Klasse mit einer main-Methode schreiben, die JUnitCore verwendet, um die Tests einer Klasse auszuführen, die @Parameterized
und Ihre main-Methode einen Filter anwenden lässt, um einen der Tests auszuwählen
Hallo Kevin,
Schauen Sie sich diese beiden Beispiele an:
Erster Test ohne Parametrierung:
package org;
import org.junit.Test;
import org.junit.internal.requests.FilterRequest;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.manipulation.Filter;
public class NoParameterTest {
public static void main(String[] args) {
new JUnitCore().run(FilterRequest.aClass(NoParameterTest.class).filterWith(new Filter() {
<strong i="8">@Override</strong>
public boolean shouldRun(Description description) {
System.out.println("Should run test: classname[" + description.getClassName() + "] method name[" + description.getMethodName() + "]");
return description != null && description.getMethodName() != null && description.getMethodName().equals("test");
}
<strong i="9">@Override</strong>
public String describe() {
return null;
}
}).getRunner());
}
<strong i="10">@Test</strong>
public void test() {
System.out.println("Running Test: test");
}
<strong i="11">@Test</strong>
public void test2() {
System.out.println("Running Test: test2");
}
}
Ausgang
Should run test: classname[org.NoParameterTest] method name[test]
Should run test: classname[org.NoParameterTest] method name[test2]
Running Test: test
Zweiter Test mit parametriertem:
package org;
import org.junit.Test;
import org.junit.internal.requests.FilterRequest;
import org.junit.runner.Description;
import org.junit.runner.JUnitCore;
import org.junit.runner.RunWith;
import org.junit.runner.manipulation.Filter;
import org.junit.runners.Parameterized;
import java.util.Arrays;
import java.util.Collection;
@RunWith(Parameterized.class)
public class ParameterTest {
public static void main(String[] args) {
new JUnitCore().run(FilterRequest.aClass(ParameterTest.class).filterWith(new Filter() {
<strong i="18">@Override</strong>
public boolean shouldRun(Description description) {
System.out.println("Should run test: classname[" + description.getClassName() + "] method name[" + description.getMethodName() + "]");
return description != null && description.getMethodName() != null && description.getMethodName().equals("test");
}
<strong i="19">@Override</strong>
public String describe() {
return null;
}
}).getRunner());
}
@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[]{"Paramter 1"}, new Object[]{"Parameter 2"});
}
private String localParameter;
public ParameterTest(String parameter) {
this.localParameter = parameter;
}
<strong i="20">@Test</strong>
public void test() {
System.out.println("Running Test: test");
System.out.println("Parameter: " + localParameter);
}
<strong i="21">@Test</strong>
public void test2() {
System.out.println("Running Test: test2");
System.out.println("Parameter: " + localParameter);
}
}
Ausgang
Should run test: classname[[0]] method name[null]
Should run test: classname[[1]] method name[null]
Die vom Parametrierten an den Filter übergebene Beschreibung ist nicht korrekt, oder?
@diogoeag Danke für das Codebeispiel. Mit welcher JUnit-Version hast du das probiert? Ich denke, wir haben ein verwandtes Problem in 4.12 behoben, aber ich bin mir nicht sicher.
@kcooney , ich habe mit dem aktuellen Master 4.12-SNAPSHOT getestet und auch mit 4.11. Beide haben das gleiche Problem.
Vielen Dank. Um dies zu beheben, wären Änderungen erforderlich, die nicht abwärtskompatibel sind. Meilenstein auf 5.0 setzen
Nur um dies zu verdeutlichen, müsste dies nur zu BlockJUnit4ClassRunnerWithParameters gehen und die Überschreibung der #testName-Methode entfernen. Das ersetzt die Standardeinstellung
protected String testName(FrameworkMethod method) {
return method.getName();
}
von
<strong i="9">@Override</strong>
protected String testName(FrameworkMethod method) {
return method.getName() + getName();
}
Und die Konsequenz wäre, dass das Reporting der Tests nicht den Parameternamen im testHeader hätte (zumindest waren nur diese Tests fehlgeschlagen)?
@diogoeag, aber möchten wir nicht den Parameternamen in der Beschreibung?
Ich denke, die Korrekturen würden am besten auf dem Beschreibungs-Builder vorgenommen, an dem wir für JUnit 5.0 arbeiten.
@kcooney Ja, um richtig zu sein, sollten wir den Parameternamen in der Beschreibung haben, aber die Beschreibung sollte den
Haben Sie Schätzungen zum Zieldatum bis 5.0?
Ich habe nach der Verwendung von getDisplayName gesucht, um mit dem Fix einen Pull-Request an 5.0 zu senden, es wird jedoch 23-mal im Projekt verwendet (Quellen und Tests) und ich habe nicht die ausreichenden Kenntnisse der JUnit-Quelle, um eine solche Änderung vorzunehmen. In der Zwischenzeit werde ich eine Gabel für meinen persönlichen Gebrauch mit dieser Zwischenlösung für mich machen. Die Parameternamen zu haben ist nicht entscheidend, aber die Möglichkeit, einzelne Tests auszuführen, spart uns viele Stunden bei vielen Entwicklern, die Tests in unserer Quelle ausführen.
Vielen Dank
Wenn jemand Zugriff auf diesen temporären Fix haben muss: https://github.com/feedzai/junit/commit/be41d2980227d86915d9c8b6f800070a0ef1ff7a
@diogoeag
Sieh dir das an. Würde es in todsicheren 2.18 helfen?
https://github.com/apache/maven-surefire/pull/46
@ Tibor17 Ich bin mir nicht sicher. Denn shoudlRun wird die Beschreibung auch verwenden. Ich kenne die Codebasis nicht genug, um zu wissen, ob es funktioniert. Teste es nur. Mein Beispielcode kann auch einer der Tests für Ihren Fix sein. Bei parametrisierten Tests besteht das Problem, den Testnamen zu ändern.
@diogoeag
In todsicherem MethodFilter sollten Sie in der Lage sein, eine Bedingung wie folgt anzugeben:
String filterBy = JunitVersion < 5.0 & <strong i="7">@RunWith</strong> = Parameterized.class ? methodName + className : methodName
Wenn Sie die JUnit-Probleme tolerieren möchten, können Sie Hotfix im Maven Surefire-Projekt selbst festlegen.
@diogoeag Wir haben noch kein Zieldatum für JUnit 5.0, aber es wäre wahrscheinlich die Veröffentlichung nach dem 4.12. Wir konzentrieren uns derzeit darauf, 4.12 aus der Tür zu bekommen
@kcooney danke. Wir werden in der Zwischenzeit unsere interne Version verwenden.
Hallo, was ist mit diesem Problem? Gibt es eine Problemumgehung für die Verwendung von Parameterized.class und die Möglichkeit, einen einzelnen Test mit Maven Surefire auszuführen? Oder müssen wir die 5.0-Version darauf warten?
@Fanch - es gibt keinen aktuellen Fix. Wir dachten, wir würden dies auch bei der ImmutableDescription-Arbeit beheben, an der wir arbeiteten, aber diese Bemühungen wurden aufgegeben.
Ich denke, es wäre in Ordnung, getName()
aus testName()
zu entfernen, weil es sowieso überflüssig ist.
@junit-team/junit-committers Was denkst du?
Solange alle Description
Instanzen für einen partameterisierten Test eindeutig sind.
Wir könnten die eindeutige ID in der Beschreibung festlegen, um sie eindeutig zu machen. Ich frage mich jedoch, ob / warum sie im gesamten Unterbaum eindeutig sein müssen?
Ja, Description
Instanzen müssen eindeutig sein. Das ist alles, was an den Listener übergeben wird, um auf einen Testbeginn und -ende zu verweisen. Um einen Baum, wie Sie ihn gezeigt haben, zu erstellen und ihn während des Testlaufs zu aktualisieren, müssen Sie wissen, welcher Test gestartet wurde.
Punkt genommen. Ich denke, wir sollten Description
eine neue Factory-Methode hinzufügen, die eine Testbeschreibung mit einer eindeutigen eindeutigen ID erstellt. Wir könnten dann den aktuellen Namen als eindeutige ID übergeben und nur den Namen der Methode als Anzeigenamen verwenden. Was denken Sie?
@marcphilipp es gibt bereits eine Methode in Description zum Erstellen einer Testbeschreibung mit einer bestimmten eindeutigen ID: https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/runner/ Beschreibung.java#L109
Ich glaube nicht, dass Description
eindeutige IDs _generieren_ sollte. Könnte Parameterized
keinen deterministischen Wert an Description.createTestDescription()
?
In Description gibt es bereits eine Methode zum Erstellen einer Testbeschreibung mit einer bestimmten eindeutigen ID: https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/runner/Description. java#L109
Ja, aber dieser hat keinen Klassenparameter. Wir brauchen also einen anderen.
Ich glaube nicht, dass
Description
eindeutige IDs _generieren_ sollte. KönnteParameterized
keinen deterministischen Wert anDescription.createTestDescription()
?
Das meinte ich nicht. Ich meinte, dass Parameterized
method.getName() + getName()
als eindeutige ID und method.getName()
als Namen _pass_ sollte.
SGTM.
Auch wenn wir die Idee, unveränderliche Beschreibungsinstanzen für JUnit 4 zu haben, aufgegeben haben, sollten wir einen Builder hinzufügen, um so viele statische Erstellungsmethoden zu vermeiden?
Sicher! 👍
Gibt es Schätzungen wann es behoben wird?
Dieser Fehler blockiert einen verwandten Fehler von JUnit5
https://github.com/junit-team/junit5/issues/549
@SqAutoTestTeam daran arbeitet niemand aktiv. Ich habe den Beschreibungs-Builder-Zweig kürzlich aktualisiert, damit ein ehrgeiziger Mitwirkender von dort aus beginnen kann. Alternativ könnten wir Description
weitere statische Methode hinzufügen.
Um dies zu beheben, wären neue APIs in der Beschreibung erforderlich. Wir möchten nicht, dass JUnit 5 diese neuen APIs benötigt (derzeit würde JUnit 5 auf fast jeder Version von JUnit 4.x funktionieren).
@diogoeag
Haben Sie dieses Kapitel in Surefire gelesen?
http://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html#Multiple_Formats_in_One
Das Filtern von parametrisierten Tests funktioniert seit Version 2.19
. In Ihrem Fall ist es -Dtest=TesClass#testName[*]
statt -Dtest=TesClass#testName
.
@kcooney und @marcphilipp ,
Was halten Sie davon, den _fix_ in https://github.com/junit-team/junit5/pull/1018/files#diff -42ed8b618527eb1521dbe3cd9100e949R48 auf JUnit 4 "zurückzuportieren"?
@sbrannen das sieht nach einer vernünftigen Änderung aus. Ich möchte nur sicherstellen, dass wir, wenn wir diese Änderungen zurückportieren, JUnit 4.13 nicht mit JUnit 5 inkompatibel machen oder Projekte mit JUnit 4-Stil-Tests auf 4.13 aktualisieren müssen, bevor sie ihre JUnit 4-Stil-Tests mit dem ausführen können JUnit 5-Runner-APIs.
@kcooney ,
das sieht nach einer vernünftigen änderung aus.
👍
Ich möchte nur sicherstellen, dass wir, wenn wir diese Änderungen zurückportieren, JUnit 4.13 nicht mit JUnit 5 inkompatibel machen oder Projekte mit JUnit 4-Stil-Tests auf 4.13 aktualisieren müssen, bevor sie ihre JUnit 4-Stil-Tests mit dem ausführen können JUnit 5-Runner-APIs.
In JUnit 4 würde die Änderung nur auf eine einzige Zeile in Filter#matchMethodDescription(Description)
, und wir können den gleichen _fix_ in JUnit Vintage beibehalten wie jetzt, so dass VintageTestEngine
weiterhin mit JUnit 4.12 funktionieren würde .
Also, es sei denn, ich übersehe etwas, das sollte Kompatibilitätsprobleme vermeiden.
Was denken Sie?
@sbrannen SGTM
Hilfreichster Kommentar
@diogoeag
Haben Sie dieses Kapitel in Surefire gelesen?
http://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html#Multiple_Formats_in_One
Das Filtern von parametrisierten Tests funktioniert seit Version
2.19
. In Ihrem Fall ist es-Dtest=TesClass#testName[*]
statt-Dtest=TesClass#testName
.