2008-12-22 6 views

Respuesta

3

junit4 ahora allows specifying a name attribute a la anotación con parámetros, de tal manera que se puede especificar un patrón de nomenclatura de los métodos toString índice y de los argumentos. Ej .:

@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 } }); 
} 
5

Creo que no hay nada construido en en jUnit 4 para hacer esto.

Implementé una solución. He construido mi propia clase Parameterized basado en el ya existente:

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

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

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

    // TODO: single-class this extension 

    private static class TestClassRunnerForParameters extends TestClassMethodsRunner { 
     private final Object[] fParameters; 

     private final Class<?> fTestClass; 

     private Object instance; 

     private final int fParameterSetNumber; 

     private final Constructor<?> fConstructor; 

     private TestClassRunnerForParameters(Class<?> klass, Object[] parameters, int i) throws Exception { 
      super(klass); 
      fTestClass = klass; 
      fParameters = parameters; 
      fParameterSetNumber = i; 
      fConstructor = getOnlyConstructor(); 
      instance = fConstructor.newInstance(fParameters); 
     } 

     @Override 
     protected Object createTest() throws Exception { 
      return instance; 
     } 

     @Override 
     protected String getName() { 
      String name = null; 
      try { 
       Method m = getNameMethod(); 
       if (m != null) 
        name = (String) m.invoke(instance); 
      } catch (Exception e) { 
      } 
      return String.format("[%s]", (name == null ? fParameterSetNumber : name)); 
     } 

     @Override 
     protected String testName(final Method method) { 
      String name = null; 
      try { 
       Method m = getNameMethod(); 
       if (m != null) 
        name = (String) m.invoke(instance); 
      } catch (Exception e) { 
      } 
      return String.format("%s[%s]", method.getName(), (name == null ? fParameterSetNumber : name)); 
     } 

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

     private Method getNameMethod() throws Exception { 
      for (Method each : fTestClass.getMethods()) { 
       if (Modifier.isPublic((each.getModifiers()))) { 
        Annotation[] annotations = each.getAnnotations(); 
        for (Annotation annotation : annotations) { 
         if (annotation.annotationType() == Name.class) { 
          if (each.getReturnType().equals(String.class)) 
           return each; 
          else 
           throw new Exception("Name annotated method doesn't return an object of type String."); 
         } 
        } 
       } 
      } 
      return null; 
     } 
    } 

    // TODO: I think this now eagerly reads parameters, which was never the 
    // point. 

    public static class RunAllParameterMethods extends CompositeRunner { 
     private final Class<?> fKlass; 

     public RunAllParameterMethods(Class<?> klass) throws Exception { 
      super(klass.getName()); 
      fKlass = klass; 
      int i = 0; 
      for (final Object each : getParametersList()) { 
       if (each instanceof Object[]) 
        super.add(new TestClassRunnerForParameters(klass, (Object[]) each, i++)); 
       else 
        throw new Exception(String.format("%s.%s() must return a Collection of arrays.", fKlass.getName(), getParametersMethod().getName())); 
      } 
     } 

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

     private Method getParametersMethod() throws Exception { 
      for (Method each : fKlass.getMethods()) { 
       if (Modifier.isStatic(each.getModifiers())) { 
        Annotation[] annotations = each.getAnnotations(); 
        for (Annotation annotation : annotations) { 
         if (annotation.annotationType() == Parameters.class) 
          return each; 
        } 
       } 
      } 
      throw new Exception("No public static parameters method on class " + getName()); 
     } 
    } 

    public MyParameterized(final Class<?> klass) throws Exception { 
     super(klass, new RunAllParameterMethods(klass)); 
    } 

    @Override 
    protected void validate(MethodValidator methodValidator) { 
     methodValidator.validateStaticMethods(); 
     methodValidator.validateInstanceMethods(); 
    } 

} 

Para ser utilizado como:

@RunWith(MyParameterized.class) 
public class ParameterizedTest { 
    private File file; 
    public ParameterizedTest(File file) { 
     this.file = file; 
    } 

    @Test 
    public void test1() throws Exception {} 

    @Test 
    public void test2() throws Exception {} 

    @Name 
    public String getName() { 
     return "coolFile:" + file.getName(); 
    } 

    @Parameters 
    public static Collection<Object[]> data() { 
     // load the files as you want 
     Object[] fileArg1 = new Object[] { new File("path1") }; 
     Object[] fileArg2 = new Object[] { new File("path2") }; 

     Collection<Object[]> data = new ArrayList<Object[]>(); 
     data.add(fileArg1); 
     data.add(fileArg2); 
     return data; 
    } 
} 

Esto implica que una instancia de la clase de prueba anterior. Espero que esto no cause ningún error ... Supongo que debería probar las pruebas :)

+1

FYI: Esta respuesta sigue siendo correcta para JUnit 4.0, pero, afortunadamente, es posible agregar nombres personalizados en JUnit 4.11. Ver http://stackoverflow.com/a/10143872/103814 – NobodyMan

0

No hay indicios de que esta característica esté o vaya a implementarse. Pediría esta característica porque es bueno tenerla.

+1

Ya no es cierto. –

2

Una solución sin código aunque no tan cómoda es pasar suficiente información de contexto para identificar la prueba en los mensajes de confirmación. Todavía verá que testYY [0] falló, pero el mensaje detallado le dice cuál fue.

assertEquals("Not the expected decision for the senator " + this.currentSenatorName + " and the law " + this.votedLaw, 
expectedVote, actualVote); 
1

Si JUnitParams library utilizar (ya que tengo described here), las pruebas con parámetros tendrán sus parámetros Stringified como sus propios nombres de las pruebas por defecto.

Por otra parte, you can see in their samples, que JUnitParams también le permite tener un nombre de prueba personalizada mediante @TestCaseName:

@Test 
@Parameters({ "1,1", "2,2", "3,6" }) 
@TestCaseName("factorial({0}) = {1}") 
public void custom_names_for_test_case(int argument, int result) { } 

@Test 
@Parameters({ "value1, value2", "value3, value4" }) 
@TestCaseName("[{index}] {method}: {params}") 
public void predefined_macro_for_test_case_name(String param1, String param2) { } 
Cuestiones relacionadas