2012-11-09 17 views
5

Mam kilka testów JBehave, które chcę uruchomić z Eclipse i Ant. W Eclipse Chcę zobaczyć drzewa wszystkich różne historie, scenariusze i kroki, które są wykonywane w twórczości graficznej, więc dodałem niestandardową biegacza do testów, które wykonuje to:Jak korzystać z różnych Junit TestRunner w Eclipse i Ant?

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

Ale przeciwnie, gdy uruchomiony testy z Antem i serwerem Continuous Integration Chcę zobaczyć tylko całą historię jako pojedynczy element na wyjściu. Uzyskuje się to zazwyczaj bez jakiejkolwiek adnotacji:

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

Więc jak mogę powiedzieć Ant (JUnit Ant zadanie), aby użyć innego biegacza niż Eclipse? Żeby było bardziej skomplikowane: Obecnie używam zestawu testowego w Eclipse (nie w Ant), aby uruchomić testy:

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

jakieś pomysły?

Cheers Tilmann

Odpowiedz

6

Zrobiłem kilka włamać się kilka tygodni temu, że zmieści się swoich potrzeb. Zdałem sobie sprawę, że polecenie java, które jest wykonywane przez Eclipse w przypadku testu jednostkowego zawiera zawsze pakiet w jego nazwie. Więc jeśli ten oddaje prawdziwe, prawdopodobnie używasz test pod Eclipse:

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

wiem, jego rozwiązanie nie 100 procent, ale zwykle pracuje, a jej lepiej niż nic.

ja stworzony i przetestowany parę Runner + notatek dla Ciebie:

adnotacji:

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; 
} 

domyślnie używa JUnit4 jak defaultrunner, co jest naprawdę domyślny dla JUnit4.

biegacz, który wykorzystuje informacje z adnotacją:

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

a przykładem użytkowaniu:

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

więc test ten będzie działał z JUnit4 runner w Eclipse, z Sparametryzowane poza Eclipse.

+0

Jeśli nie podoba ci się wpis środowiska, możesz również uzyskać ślad wątku i wyszukać w nim niektóre klasy specyficzne dla zaćmienia. –

+2

To świetnie, dziękuję bardzo! I działa prawie perfekt. Jedyną rzeczą, którą zmieniłem, było sprawdzenie adnotacji w hierarchii superklasy, jeśli nie znalazłem jej w klasie. – Gandalf

+0

Następnie dokonaj edycji mojego wpisu, a następnie inni mogą również wprowadzić tę zmianę. –

Powiązane problemy