Frage

Gibt es eine Möglichkeit, meine eigenen benutzerdefinierten Testfall-Namen zu setzen, wenn parametrisierte Tests in JUnit4 mit?

Ich möchte den Standard ändern - [Test class].runTest[n] -. Um etwas Sinnvolles

War es hilfreich?

Lösung

Diese Funktion es in JUnit gemacht hat 4.11 .

Verwenden Sie den Namen parametrisierte Tests ändern, sagen Sie:

@Parameters(name="namestring")

namestring ist eine Zeichenfolge, den folgenden speziellen Platzhalter aufweisen kann:

  • {index} - der Index dieser Gruppe von Argumenten. Der Standard namestring ist {index}.
  • {0} - der erste Parameterwert aus diesem Aufruf des Tests
  • .
  • {1} - der zweite Parameterwert
  • und so weiter

Der endgültige Name des Tests wird der Name des Testverfahrens, gefolgt von der namestring in Klammern, wie unten dargestellt.

Zum Beispiel (aus dem Unit-Test für die Parameterized Anmerkung angepasst):

@RunWith(Parameterized.class)
static public class FibonacciTest {

    @Parameters( name = "{index}: fib({0})={1}" )
    public static Iterable<Object[]> data() {
        return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 },
                { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } });
    }

    private final int fInput;
    private final int fExpected;

    public FibonacciTest(int input, int expected) {
        fInput= input;
        fExpected= expected;
    }

    @Test
    public void testFib() {
        assertEquals(fExpected, fib(fInput));
    }

    private int fib(int x) {
        // TODO: actually calculate Fibonacci numbers
        return 0;
    }
}

werden Namen wie testFib[1: fib(1)=1] und testFib[4: fib(4)=3] geben. (Der testFib Teil des Namens ist der Methodenname des @Test).

Andere Tipps

bei JUnit Blick 4.5, dessen Läufer eindeutig nicht akzeptiert, dass, wie die Logik in einem privaten Klasse innerhalb der Parameterized Klasse begraben ist. Sie können nicht die JUnit Parameterized Läufer verwenden, und erstellen Sie Ihre eigenen statt, die das Konzept des Namen verstehen würde (was führt zu der Frage, wie Sie einen Namen festlegen könnten ...).

Aus JUnit Sicht wäre es schön, wenn anstelle von (oder zusätzlich zu) einen Zuwachs gerade vorbei, würden sie die durch Komma getrennte Argumente übergeben. TestNG tut dies. Wenn die Funktion für Sie wichtig ist, können Sie auf der Yahoo-Mailingliste Kommentar zu www.junit.org verwiesen wird.

ich auf das gleiche Problem vor kurzem kam, als JUnit 4.3.1 verwenden. Ich implementierte eine neue Klasse, die sich Parameterized LabelledParameterized genannt. Es wurde mit JUnit 4.3.1, 4.4 und 4.5 getestet. Es rekonstruiert die Beschreibung Instanz der Stringdarstellung des ersten Arguments jeden Parameter aus der Array @Parameter Methode. Sie können den Code für diese sehen:

http://code.google.com/p/migen/source/browse/trunk/java/src/.../LabelledParameterized.java?r=3789

und ein Beispiel für seine Verwendung bei:

http://code.google.com/p/migen/source/browse/trunk/java/src/.../ServerBuilderTest.java?r=3789

Die Testbeschreibungsformate schön in Eclipse das ist, was ich da dies wollte viel einfacher macht nicht bestandene Tests zu finden! Ich werde wahrscheinlich weiter verfeinern und zu dokumentieren, die Klassen in den nächsten Tagen / Wochen. Lass fallen '?' Teil der URLs, wenn Sie die bleeding edge. : -)

Um es zu nutzen, alles, was Sie tun müssen, ist diese Klasse (GPL v3) zu kopieren und ändern @RunWith (Parameterized.class) zu @RunWith (LabelledParameterized.class), um das erste Element Ihrer Parameterliste unter der Annahme, ist eine sinnvolle Label .

Ich weiß nicht, ob irgendwelche späteren Versionen von JUnit-Adresse dieses Problem aber selbst wenn sie es taten, kann ich nicht JUnit aktualisieren, da alle meine Co-Entwickler aktualisieren müssten und wir haben eine höhere Priorität als Nachrüsten. Daraus ergibt sich die Arbeit in der Klasse von mehreren Versionen von JUnit übersetzbar sein.


Hinweis: gibt es einige Reflexion Schmu, so dass es in den verschiedenen Versionen JUnit läuft wie oben aufgeführt. Die Version speziell für JUnit 4.3.1 kann hier und für JUnit 4.4 und 4.5, hier .

Mit Parameterized als Modell, schrieb ich meine eigene benutzerdefinierte Testläufer / Suite - nur etwa dauerte eine halbe Stunde. Es ist leicht von darrenp der LabelledParameterized, dass es lässt Sie explizit eher einen Namen angeben, als auf den ersten Parameter des toString() angewiesen zu sein.

Es ist auch nicht verwenden Arrays, weil ich Arrays hassen. :)

public class PolySuite extends Suite {

  // //////////////////////////////
  // Public helper interfaces

  /**
   * Annotation for a method which returns a {@link Configuration}
   * to be injected into the test class constructor
   */
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.METHOD)
  public static @interface Config {
  }

  public static interface Configuration {
    int size();
    Object getTestValue(int index);
    String getTestName(int index);
  }

  // //////////////////////////////
  // Fields

  private final List<Runner> runners;

  // //////////////////////////////
  // Constructor

  /**
   * Only called reflectively. Do not use programmatically.
   * @param c the test class
   * @throws Throwable if something bad happens
   */
  public PolySuite(Class<?> c) throws Throwable {
    super(c, Collections.<Runner>emptyList());
    TestClass testClass = getTestClass();
    Class<?> jTestClass = testClass.getJavaClass();
    Configuration configuration = getConfiguration(testClass);
    List<Runner> runners = new ArrayList<Runner>();
    for (int i = 0, size = configuration.size(); i < size; i++) {
      SingleRunner runner = new SingleRunner(jTestClass, configuration.getTestValue(i), configuration.getTestName(i));
      runners.add(runner);
    }
    this.runners = runners;
  }

  // //////////////////////////////
  // Overrides

  @Override
  protected List<Runner> getChildren() {
    return runners;
  }

  // //////////////////////////////
  // Private

  private Configuration getConfiguration(TestClass testClass) throws Throwable {
    return (Configuration) getConfigMethod(testClass).invokeExplosively(null);
  }

  private FrameworkMethod getConfigMethod(TestClass testClass) {
    List<FrameworkMethod> methods = testClass.getAnnotatedMethods(Config.class);
    if (methods.isEmpty()) {
      throw new IllegalStateException("@" + Config.class.getSimpleName() + " method not found");
    }
    if (methods.size() > 1) {
      throw new IllegalStateException("Too many @" + Config.class.getSimpleName() + " methods");
    }
    FrameworkMethod method = methods.get(0);
    int modifiers = method.getMethod().getModifiers();
    if (!(Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
      throw new IllegalStateException("@" + Config.class.getSimpleName() + " method \"" + method.getName() + "\" must be public static");
    }
    return method;
  }

  // //////////////////////////////
  // Helper classes

  private static class SingleRunner extends BlockJUnit4ClassRunner {

    private final Object testVal;
    private final String testName;

    SingleRunner(Class<?> testClass, Object testVal, String testName) throws InitializationError {
      super(testClass);
      this.testVal = testVal;
      this.testName = testName;
    }

    @Override
    protected Object createTest() throws Exception {
      return getTestClass().getOnlyConstructor().newInstance(testVal);
    }

    @Override
    protected String getName() {
      return testName;
    }

    @Override
    protected String testName(FrameworkMethod method) {
      return testName + ": " + method.getName();
    }

    @Override
    protected void validateConstructor(List<Throwable> errors) {
      validateOnlyOneConstructor(errors);
    }

    @Override
    protected Statement classBlock(RunNotifier notifier) {
      return childrenInvoker(notifier);
    }
  }
}

Und ein Beispiel:

@RunWith(PolySuite.class)
public class PolySuiteExample {

  // //////////////////////////////
  // Fixture

  @Config
  public static Configuration getConfig() {
    return new Configuration() {
      @Override
      public int size() {
        return 10;
      }

      @Override
      public Integer getTestValue(int index) {
        return index * 2;
      }

      @Override
      public String getTestName(int index) {
        return "test" + index;
      }
    };
  }

  // //////////////////////////////
  // Fields

  private final int testVal;

  // //////////////////////////////
  // Constructor

  public PolySuiteExample(int testVal) {
    this.testVal = testVal;
  }

  // //////////////////////////////
  // Test

  @Ignore
  @Test
  public void odd() {
    assertFalse(testVal % 2 == 0);
  }

  @Test
  public void even() {
    assertTrue(testVal % 2 == 0);
  }

}

von junit4.8.2, können Sie Ihre eigene MyParameterized Klasse erstellen, indem Sie einfach parametrisierte Klasse kopieren. ändern, um den getName () und Testname () Methods in TestClassRunnerForParameters.

Sie sollten auch versuchen, JUnitParams: http://code.google.com/p/junitparams /

Sie können eine Methode, wie erstellen

@Test
public void name() {
    Assert.assertEquals("", inboundFileName);
}

Während ich hätte es nicht die ganze Zeit, es wäre nützlich, genau herauszufinden, welche Testnummer 143 ist.

Ich mache umfangreichen Gebrauch von statischem Import für Assert und Freunde, so ist es leicht für mich Behauptung neu zu definieren:

private <T> void assertThat(final T actual, final Matcher<T> expected) {
    Assert.assertThat(editThisToDisplaySomethingForYourDatum, actual, expected);
}

Zum Beispiel könnten Sie ein „Namen“ Feld Ihre Testklassen hinzufügen, im Konstruktor initialisiert, und das Versagen Test anzuzeigen. gibt es nur in als die ersten Elementen des Parameter-Array für jeden Test. Dies hilft auch, die Daten beschriften:

public ExampleTest(final String testLabel, final int one, final int two) {
    this.testLabel = testLabel;
    // ...
}

@Parameters
public static Collection<Object[]> data() {
    return asList(new Object[][]{
        {"first test", 3, 4},
        {"second test", 5, 6}
    });
}

Nichts davon arbeiten für mich, also habe ich die Quelle für Parameterized und modifizierte es einen einen neuen Test Läufer schaffen. Ich habe nicht viel zu ändern, aber es funktioniert !!!

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.junit.Assert;
import org.junit.internal.runners.ClassRoadie;
import org.junit.internal.runners.CompositeRunner;
import org.junit.internal.runners.InitializationError;
import org.junit.internal.runners.JUnit4ClassRunner;
import org.junit.internal.runners.MethodValidator;
import org.junit.internal.runners.TestClass;
import org.junit.runner.notification.RunNotifier;

public class LabelledParameterized extends CompositeRunner {
static class TestClassRunnerForParameters extends JUnit4ClassRunner {
    private final Object[] fParameters;

    private final String fParameterFirstValue;

    private final Constructor<?> fConstructor;

    TestClassRunnerForParameters(TestClass testClass, Object[] parameters, int i) throws InitializationError {
        super(testClass.getJavaClass()); // todo
        fParameters = parameters;
        if (parameters != null) {
            fParameterFirstValue = Arrays.asList(parameters).toString();
        } else {
            fParameterFirstValue = String.valueOf(i);
        }
        fConstructor = getOnlyConstructor();
    }

    @Override
    protected Object createTest() throws Exception {
        return fConstructor.newInstance(fParameters);
    }

    @Override
    protected String getName() {
        return String.format("%s", fParameterFirstValue);
    }

    @Override
    protected String testName(final Method method) {
        return String.format("%s%s", method.getName(), fParameterFirstValue);
    }

    private Constructor<?> getOnlyConstructor() {
        Constructor<?>[] constructors = getTestClass().getJavaClass().getConstructors();
        Assert.assertEquals(1, constructors.length);
        return constructors[0];
    }

    @Override
    protected void validate() throws InitializationError {
        // do nothing: validated before.
    }

    @Override
    public void run(RunNotifier notifier) {
        runMethods(notifier);
    }
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public static @interface Parameters {
}

private final TestClass fTestClass;

public LabelledParameterized(Class<?> klass) throws Exception {
    super(klass.getName());
    fTestClass = new TestClass(klass);

    MethodValidator methodValidator = new MethodValidator(fTestClass);
    methodValidator.validateStaticMethods();
    methodValidator.validateInstanceMethods();
    methodValidator.assertValid();

    int i = 0;
    for (final Object each : getParametersList()) {
        if (each instanceof Object[])
            add(new TestClassRunnerForParameters(fTestClass, (Object[]) each, i++));
        else
            throw new Exception(String.format("%s.%s() must return a Collection of arrays.", fTestClass.getName(), getParametersMethod().getName()));
    }
}

@Override
public void run(final RunNotifier notifier) {
    new ClassRoadie(notifier, fTestClass, getDescription(), new Runnable() {
        public void run() {
            runChildren(notifier);
        }
    }).runProtected();
}

private Collection<?> getParametersList() throws IllegalAccessException, InvocationTargetException, Exception {
    return (Collection<?>) getParametersMethod().invoke(null);
}

private Method getParametersMethod() throws Exception {
    List<Method> methods = fTestClass.getAnnotatedMethods(Parameters.class);
    for (Method each : methods) {
        int modifiers = each.getModifiers();
        if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))
            return each;
    }

    throw new Exception("No public static parameters method on class " + getName());
}

public static Collection<Object[]> eachOne(Object... params) {
    List<Object[]> results = new ArrayList<Object[]>();
    for (Object param : params)
        results.add(new Object[] { param });
    return results;
}
}

würde Eine Abhilfe zu fangen und Nest, alle Throwables in ein neues Throwable mit einer benutzerdefinierten Nachricht, die alle Informationen über die Parameter enthält. Die Nachricht würde in dem Stack-Trace angezeigt. Das funktioniert, wenn ein Test für alle Behauptungen, Fehler und Ausnahmen nicht, da sie alle Subklassen von Throwable sind.

Mein Code sieht wie folgt aus:

@RunWith(Parameterized.class)
public class ParameterizedTest {

    int parameter;

    public ParameterizedTest(int parameter) {
        super();
        this.parameter = parameter;
    }

    @Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] { {1}, {2} });
    }

    @Test
    public void test() throws Throwable {
        try {
            assertTrue(parameter%2==0);
        }
        catch(Throwable thrown) {
            throw new Throwable("parameter="+parameter, thrown);
        }
    }

}

Der Stack-Trace des ausgefallenen Tests:

java.lang.Throwable: parameter=1
    at sample.ParameterizedTest.test(ParameterizedTest.java:34)
Caused by: java.lang.AssertionError
    at org.junit.Assert.fail(Assert.java:92)
    at org.junit.Assert.assertTrue(Assert.java:43)
    at org.junit.Assert.assertTrue(Assert.java:54)
    at sample.ParameterizedTest.test(ParameterizedTest.java:31)
    ... 31 more

Überprüfen Sie heraus JUnitParams als dsaff erwähnt, arbeitet ant mit parametrisierte Testmethode Beschreibungen im HTML-Bericht zu erstellen.

Dies war nach LabelledParameterized Dem Versuch, und festgestellt, dass es, obwohl es mit Eclipse funktioniert es nicht mit Ameise funktioniert so weit wie der HTML-Bericht betrifft.

Cheers,

Da die Zugriff auf Parameter (zum Beispiel mit "{0}" immer der toString() Darstellung gibt, würde man Abhilfe sein, um eine anonyme Implementierung zu machen und außer Kraft setzt toString() jeweils. Zum Beispiel:

public static Iterable<? extends Object> data() {
    return Arrays.asList(
        new MyObject(myParams...) {public String toString(){return "my custom test name";}},
        new MyObject(myParams...) {public String toString(){return "my other custom test name";}},
        //etc...
    );
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top