2

Purpose: Run parameterized tests within xtext/xtend context.

Progress: So far I have achieved getting it to run, but it is appearing wrong in the junit window.

Issues: The failure trace and results of both tests appear in the last test, as shown in the figure below. The first test, marked by the red pen, is sort of unresolved and does not contain any failure trace.

junit window

Here is the test 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);
    }
}

ParameterizedXtextRunner (Inspiration from here: 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)
    }

And finally XtextParametersRunnerFactory:

class XtextParametersRunnerFactory implements ParametersRunnerFactory {
    override createRunnerForTestWithParameters(TestWithParameters test) throws InitializationError {
        new ParameterizedXtextRunner(test)
    }
}
Casper Thule Hansen
  • 1,510
  • 2
  • 19
  • 36

2 Answers2

2

By looking at the XtextRunner class it inherits from BlockJUnit4ClassRunner. Parameterized does not extend this runner, but ParentRunner. However, so does BlockJUnit4ClassRunner Therefore we implemented it as below:

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

And used the code from XtextRunner and put it into the new runner -- it is necessary to extract InjectorProviders from Xtext as well

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

}

Creating a test:

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

}
Casper Thule Hansen
  • 1,510
  • 2
  • 19
  • 36
0

due to OSGi import package constraits and deprecation I use this adoption of the original code:

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

}
user2078148
  • 591
  • 1
  • 4
  • 13