xtext 参数化的 xtext runner

xtext parameterized xtext runner

目的: 运行 xtext/xtend 上下文中的参数化测试。

进度: 到目前为止,我已经实现了 运行,但它在 junit window.

中出现错误

问题: 两次测试的失败痕迹和结果都出现在最后一次测试中,如下图所示。 用红笔标记的第一个测试有点未解决,不包含任何失败痕迹。

这里是测试class:

@RunWith(typeof(Parameterized))
@InjectWith(SemanticAdaptationInjectorProvider)
@Parameterized.UseParametersRunnerFactory(XtextParametersRunnerFactory)
class CgCppAutoTest extends AbstractSemanticAdaptationTest {

    new (List<File> files)
    {
        f = files;
    }

    @Inject extension ParseHelper<SemanticAdaptation>
    @Inject extension  ValidationTestHelper

    @Parameters(name = "{index}")
    def static Collection<Object[]> data() {
        val files = new ArrayList<List<File>>();
        listf("test_input", files);
        val test = new ArrayList();
        test.add(files.get(0));
        return Arrays.asList(test.toArray(), test.toArray());
    }

    def static void listf(String directoryName, List<List<File>> files) {
        ...
    }

    var List<File> f;

    @Test def allSemanticAdaptations() {
        System.out.println("fail");
        assertTrue(false);
    }
}

ParameterizedXtext运行ner(灵感来自这里:https://www.eclipse.org/forums/index.php?t=msg&th=1075706&goto=1726802&):

class ParameterizedXtextRunner extends XtextRunner {
    val Object[] parameters;
    val String annotatedName;
    new(TestWithParameters test) throws InitializationError {
        super(test.testClass.javaClass)
        parameters = test.parameters;
        annotatedName = test.name;
    }
    override protected getName() {
        return super.name + annotatedName;
    }
    override protected createTest() throws Exception {
        val object = testClass.onlyConstructor.newInstance(parameters)
        val injectorProvider = getOrCreateInjectorProvider
        if (injectorProvider != null) {
            val injector = injectorProvider.injector
            if (injector != null)
                injector.injectMembers(object)
        }
        return object;
    }
    override protected void validateConstructor(List<Throwable> errors) {
        validateOnlyOneConstructor(errors)
    }

最后是 XtextParameters运行nerFactory:

class XtextParametersRunnerFactory implements ParametersRunnerFactory {
    override createRunnerForTestWithParameters(TestWithParameters test) throws InitializationError {
        new ParameterizedXtextRunner(test)
    }
}

通过查看 XtextRunner class 它继承自 BlockJUnit4ClassRunner。 参数化不扩展这个跑步者,但是 父母亚军。但是,BlockJUnit4ClassRunner 也是如此 因此我们实现如下:

public class XtextParametersRunnerFactory implements ParametersRunnerFactory {
    @Override
    public Runner createRunnerForTestWithParameters(TestWithParameters test) throws InitializationError {
        return new XtextRunnerWithParameters(test);
    }
}

并使用了 XtextRunner 中的代码并将其放入新的运行器中——还需要从 Xtext 中提取 InjectorProviders

public class XtextRunnerWithParameters extends BlockJUnit4ClassRunnerWithParameters {
    public XtextRunnerWithParameters(TestWithParameters test) throws InitializationError {
        super(test);
    }

    @Override
    public Object createTest() throws Exception {
        Object object = super.createTest();
        IInjectorProvider injectorProvider = getOrCreateInjectorProvider();
        if (injectorProvider != null) {
            Injector injector = injectorProvider.getInjector();
            if (injector != null)
                injector.injectMembers(object);
        }
        return object;
    }

    @Override
    protected Statement methodBlock(FrameworkMethod method) {
        IInjectorProvider injectorProvider = getOrCreateInjectorProvider();
        if (injectorProvider instanceof IRegistryConfigurator) {
            final IRegistryConfigurator registryConfigurator = (IRegistryConfigurator) injectorProvider;
            registryConfigurator.setupRegistry();
            final Statement methodBlock = superMethodBlock(method);
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    try {
                        methodBlock.evaluate();
                    } finally {
                        registryConfigurator.restoreRegistry();
                    }
                }
            };
        }else{
            return superMethodBlock(method);
        }
    }

    protected Statement superMethodBlock(FrameworkMethod method) {
        return super.methodBlock(method);
    }

    protected IInjectorProvider getOrCreateInjectorProvider() {
        return InjectorProviders.getOrCreateInjectorProvider(getTestClass());
    }

    protected IInjectorProvider getInjectorProvider() {
        return InjectorProviders.getInjectorProvider(getTestClass());
    }

    protected IInjectorProvider createInjectorProvider() {
        return InjectorProviders.createInjectorProvider(getTestClass());
    }

}

正在创建测试:

@RunWith(typeof(Parameterized))
@InjectWith(SemanticAdaptationInjectorProvider)
@Parameterized.UseParametersRunnerFactory(XtextParametersRunnerFactory)
class xxx
{
    @Inject extension ParseHelper<SemanticAdaptation>
    @Inject extension  ValidationTestHelper
 // Here goes standard parameterized stuff

}

由于 OSGi 导入包的限制和弃用,我使用这个采用的原始代码:

package de.uni_leipzig.pkr.handparser.tests.runners;

import org.eclipse.xtext.testing.IInjectorProvider;
import org.eclipse.xtext.testing.IRegistryConfigurator;
import org.eclipse.xtext.testing.XtextRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters;
import org.junit.runners.parameterized.TestWithParameters;

import com.google.inject.Injector;

public class XtextRunnerWithParameters extends BlockJUnit4ClassRunnerWithParameters {

    public static class MyXtextRunner extends XtextRunner {

        public MyXtextRunner(Class<?> testClass) throws InitializationError {
            super(testClass);
        }

        public IInjectorProvider getOrCreateInjectorProvider() {
            return super.getOrCreateInjectorProvider();
        }
    }

    private MyXtextRunner xtextRunner;

    public XtextRunnerWithParameters(TestWithParameters test) throws InitializationError {
        super(test);
        xtextRunner = new MyXtextRunner(test.getTestClass().getJavaClass());
    }

    @Override
    public Object createTest() throws Exception {
        Object object = super.createTest();
        IInjectorProvider injectorProvider = xtextRunner.getOrCreateInjectorProvider();
        if (injectorProvider != null) {
            Injector injector = injectorProvider.getInjector();
            if (injector != null)
                injector.injectMembers(object);
        }
        return object;
    }

    @Override
    protected Statement methodBlock(FrameworkMethod method) {
        IInjectorProvider injectorProvider = xtextRunner.getOrCreateInjectorProvider();
        if (injectorProvider instanceof IRegistryConfigurator) {
            final IRegistryConfigurator registryConfigurator = (IRegistryConfigurator) injectorProvider;
            registryConfigurator.setupRegistry();
            final Statement methodBlock = superMethodBlock(method);
            return new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    try {
                        methodBlock.evaluate();
                    } finally {
                        registryConfigurator.restoreRegistry();
                    }
                }
            };
        } else {
            return superMethodBlock(method);
        }
    }

    protected Statement superMethodBlock(FrameworkMethod method) {
        return super.methodBlock(method);
    }

}