2012-11-09 15 views
5

Ho un paio di test JBehave che voglio eseguire da Eclipse e Ant. In Eclipse Voglio vedere un albero di tutte le diverse storie, scenari e passaggi che vengono eseguite nel output grafico, così ho aggiunto un corridore personalizzato per i test che fa questo:Come utilizzare diversi Junit TestRunner in Eclipse e Ant?

@RunWith(de.codecentric.jbehave.junit.monitoring.JUnitReportingRunner.class) 
public class MyStoryTest extends org.jbehave.core.junit.JUnitStories 
{ 
    // ... 
} 

Ma al contrario durante l'esecuzione i test con Ant e nel server di Continuous Integration voglio vedere solo tutta la storia come un singolo elemento nell'output. Normalmente ciò viene ottenuto senza alcuna annotazione:

public class MyStoryTest extends JUnitStories 
{ 
    // ... 
} 

Così come posso dire Ant (JUnit compito Ant) per utilizzare un corridore diverso da Eclipse? Per rendere le cose più complicate: Al momento io uso una suite di test in Eclipse (non in Ant) per eseguire i test:

@RunWith(org.junit.extensions.cpsuite.ClasspathSuite.class) 
@org.junit.extensions.cpsuite.ClassnameFilters("foo.mypackage.tests.*") 
public class MyStoriesTestSuite 
{ 
    // Nothing more to say ;) 
} 

Tutte le idee?

Cheers, Tilmann

risposta

6

ho qualche trucco un paio di settimane fa, che può soddisfare le vostre esigenze. Mi sono reso conto che il comando java, che viene eseguito da Eclipse in caso di un test di unità, contiene sempre un pacchetto nel suo nome. Quindi, se questo restituisce vero, probabilmente si sta eseguendo il test sotto Eclipse:

System.getProperty("sun.java.command").contains("org.eclipse.jdt") 

Lo so, la sua soluzione non al 100 per cento, ma solito funziona, e il suo meglio di niente.

ho creato e testato un paio Runner + annotazione per voi:

Annotazione:

package org.junit.annotation; 

import java.lang.annotation.Documented; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

import org.junit.runner.Runner; 
import org.junit.runners.JUnit4; 

@Retention(RetentionPolicy.RUNTIME) 
@Documented 
@Target(ElementType.TYPE) 
public @interface RunWithInEnvironment { 
    Class<? extends Runner> eclipse(); 
    Class<? extends Runner> defaultRunner() default JUnit4.class; 
} 

Di default usa JUnit4 come defaultrunner, che in realtà è l'impostazione predefinita per JUnit4.

The Runner, che utilizza le informazioni della nota:

package org.junit.runners; 

import static org.junit.Assert.assertNotNull; 
import static org.junit.Assert.fail; 

import java.lang.reflect.Constructor; 
import java.lang.reflect.InvocationTargetException; 

import org.junit.annotation.RunWithInEnvironment; 
import org.junit.runner.Description; 
import org.junit.runner.Runner; 
import org.junit.runner.notification.RunNotifier; 

public class EnvironmentDependentRunner extends Runner { 
    protected Class<?> testClass; 
    protected Runner delegate; 

    public EnvironmentDependentRunner(Class<?> testClass) { 
     super(); 
     this.testClass = testClass; 
     RunWithInEnvironment annotation = findAnnotationInClassHierarchy(testClass); 
     assertNotNull(EnvironmentDependentRunner.class.getSimpleName() + " can be used only with test classes, that are annotated with " + RunWithInEnvironment.class.getSimpleName() + " annotation somewhere in their class hierarchy!", annotation); 
     Class<? extends Runner> delegateClass = null; 
     if (System.getProperty("sun.java.command").contains("org.eclipse.jdt") && annotation.eclipse() != null) { 
      delegateClass = annotation.eclipse(); 
     } 
     else { 
      delegateClass = annotation.defaultRunner(); 
     } 
     try { 
      Constructor<? extends Runner> constructor = delegateClass.getConstructor(Class.class); 
      delegate = constructor.newInstance(testClass); 
     } catch (NoSuchMethodException e) { 
      fail(delegateClass.getName() + " must contain a public constructor with a " + Class.class.getName() + " argument."); 
     } catch (SecurityException e) { 
      throw new RuntimeException("SecurityException during instantiation of " + delegateClass.getName()); 
     } catch (InstantiationException e) { 
      throw new RuntimeException("Error while creating " + delegateClass.getName()); 
     } catch (IllegalAccessException e) { 
      throw new RuntimeException("Error while creating " + delegateClass.getName()); 
     } catch (IllegalArgumentException e) { 
      throw new RuntimeException("Error while creating " + delegateClass.getName()); 
     } catch (InvocationTargetException e) { 
      throw new RuntimeException("Error while creating " + delegateClass.getName()); 
     } 
    } 

    private RunWithInEnvironment findAnnotationInClassHierarchy(Class<?> testClass) { 
     RunWithInEnvironment annotation = testClass.getAnnotation(RunWithInEnvironment.class); 
     if (annotation != null) { 
      return annotation; 
     } 

     Class<?> superClass = testClass.getSuperclass(); 
     if (superClass != null) { 
      return findAnnotationInClassHierarchy(superClass); 
     } 

     return null; 
    } 

    @Override 
    public Description getDescription() { 
     return delegate.getDescription(); 
    } 

    @Override 
    public void run(RunNotifier arg0) { 
     delegate.run(arg0); 
    } 
} 

E un esempio utilizzo:

@RunWithInEnvironment(eclipse=JUnit4.class, defaultRunner=Parameterized.class) 
@RunWith(EnvironmentDependentRunner.class) 
public class FooTest { 
... 
} 

Quindi questo test verrà eseguito con JUnit4 corridore in Eclipse, con Parametrizzato all'esterno di Eclipse.

+0

Se non ti piace la voce di ambiente, puoi anche ottenere la traccia del thread e cercare alcune classi specifiche di eclissi. –

+2

È fantastico, grazie mille! E funziona quasi perfetto. L'unica cosa che ho cambiato è stata cercare l'annotazione lungo la gerarchia delle super classi se non trovata in una classe. – Gandalf

+0

Quindi si prega di fare una modifica del mio post, e quindi gli altri possono avere questo cambiamento pure. –

Problemi correlati