java - 如何在 Eclipse 和 Ant 中使用不同的 Junit TestRunner?

标签 java ant junit jbehave test-runner

我有几个 JBehave 测试想从 Eclipse 和 Ant 运行。在 Eclipse 中,我想看到在图形输出中执行的所有不同故事、场景和步骤的树,所以我向执行此操作的测试添加了一个自定义运行程序:

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

但相反,当使用 Ant 和持续集成服务器运行测试时,我只想将每个完整的故事作为输出中的单个项目来查看。这通常是在没有任何注释的情况下实现的:

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

那么我怎样才能告诉 Ant(junit Ant 任务)使用与 Eclipse 不同的运行器呢? 让事情变得更复杂:目前我在 Eclipse(而不是 Ant)中使用测试套件来运行测试:

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

有什么想法吗?

干杯,蒂尔曼

最佳答案

几周前我做了一些 hack,可以满足您的需求。我意识到,在单元测试运行的情况下由 Eclipse 执行的 java 命令总是包含一个包在它的名字中。因此,如果这返回 true,则可能您正在 Eclipse 下运行测试:

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

我知道,这不是 100% 的解决方案,但通常有效,而且聊胜于无

我为您创建并测试了一个 Runner+Annotation 对:

注释:

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

默认情况下,它使用 JUnit4 作为 defaultrunner,这实际上是 JUnit4 的默认设置。

Runner,它使用了注解的信息:

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

还有一个用法示例:

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

因此,此测试将在 Eclipse 中使用 JUnit4 运行器运行,并在 Eclipse 外部进行参数化。

关于java - 如何在 Eclipse 和 Ant 中使用不同的 Junit TestRunner?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13309392/

相关文章:

java - 在 Replacetoken ant 任务中使用 build.properties 的值

java - JUnit Ant 任务不会输出到屏幕

java - 使用 Spring 进行 JUnit 测试

java - 使用 jsoup 获取 html 内联样式属性值

Java Hibernate 标准平均值 : BigDecimal instead of Double

java - 重写 .equals() 方法(== 在比较字符串时返回 true)!

xml - 使用 ANT 替换整个 XML 标签

java - 如何在单元测试中创建 Bundle

java - 使用 Play 框架进行 Junit 测试

java - Languagetool 示例 : java. lang.NoSuchMethodError : org. apache.xerces.impl.xs.XMLSchemaLoader.loadGrammar