Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » TMF (Xtext) » Parameterized unit test(Parameterized unit test example to validate some files)
Parameterized unit test [message #1726787] Wed, 16 March 2016 13:45 Go to next message
Mihai Traistariu is currently offline Mihai TraistariuFriend
Messages: 6
Registered: March 2016
Junior Member
Hi,
Sorry if I ask a dummy question or if there is already an answer on another topic (I did search for it but didn't find anything), I'm a newbie with xtext.
I created a grammar for my language and I want to create an unit test suite to validate all the files in one folder. According to tutorial, I created a small test for one file like this :


package my.package.tests

import org.junit.runner.RunWith
import org.eclipse.xtext.junit4.XtextRunner
import org.eclipse.xtext.junit4.InjectWith
import com.google.inject.Inject
import org.eclipse.xtext.junit4.util.ParseHelper
import org.eclipse.xtext.junit4.validation.ValidationTestHelper
import org.junit.Test
import java.nio.file.Files
import my.package.parser.mylang.Procedure
import java.nio.file.Paths

@RunWith(typeof(XtextRunner))
@InjectWith(typeof (MyLangInjectorProvider))
class MyLangParsingTestFullFolder{
	@Inject extension ParseHelper<Procedure> modelParserHelper
	@Inject extension ValidationTestHelper
	@Test
	def testProcedureParser(){
		val fileContent = new String(Files.readAllBytes(Paths.get("c:\\RunTests\\Files\\_TEST")))
		var model=modelParserHelper.parse(fileContent)
		model.assertNoErrors()
	}
}


Now, instead of having one test for each file I would like to have a parameterized unit test, to get all the files from that folder and execute the test for each one. Is there a "ParameterizedXtextRunner" (I did find something like this, but it is deprecated) or something similar? Can anybody give me an example of such test?

Thank you
Re: Parameterized unit test [message #1726798 is a reply to message #1726787] Wed, 16 March 2016 15:06 Go to previous messageGo to next message
Christian Dietrich is currently offline Christian DietrichFriend
Messages: 14665
Registered: July 2009
Senior Member
No there is no such thing. This sound like a perfect use case for the Xpect
framework


Twitter : @chrdietrich
Blog : https://www.dietrich-it.de
Re: Parameterized unit test [message #1726802 is a reply to message #1726798] Wed, 16 March 2016 15:16 Go to previous messageGo to next message
Thomas Fritsch is currently offline Thomas FritschFriend
Messages: 28
Registered: April 2013
Location: Germany
Junior Member
Why not simply using method list() of java.io.File?
	@Test
	def testParser() {
		val folder = new File("c:\\RunTests\\Files")
		for (fileName : folder.list) {
			val fileContent = new String(Files.readAllBytes( 
                                                           Paths.get(folder.absolutePath, fileName)))
			val model = fileContent.parse
			model.assertNoErrors
		}
	}
Re: Parameterized unit test [message #1726804 is a reply to message #1726802] Wed, 16 March 2016 15:21 Go to previous messageGo to next message
Moritz Eysholdt is currently offline Moritz EysholdtFriend
Messages: 161
Registered: July 2009
Location: Kiel, Germany
Senior Member
true, the first version of Xpect was actually called "ParameterizedXtextRunner". But then it became more powerful and moved to http://www.xpect-tests.org/
Re: Parameterized unit test [message #1726821 is a reply to message #1726787] Wed, 16 March 2016 16:27 Go to previous messageGo to next message
Anton Kosyakov is currently offline Anton KosyakovFriend
Messages: 9
Registered: March 2016
Junior Member
@Thomas it will be nice to have a separate method per file, so you have an overview over all files.

@Mihai with junit 4.12 you can do something like that:

@FinalFieldsConstructor
@RunWith(Parameterized)
@InjectWith(MyDslInjectorProvider)
@Parameterized.UseParametersRunnerFactory(XtextParametersRunnerFactory)
class MyDslParsingTest {

	@Parameterized.Parameters
	def static Iterable<Integer> data() {
		return #[1, 2, 3]
	}

	val int i

	@Inject
	ParseHelper<Model> parseHelper

	@Test
	def void loadModel() {
		val result = parseHelper.parse('''
			Hello Xtext_«i»!
		''')
		println(EmfFormatter.objToStr(result))
	}

}

class XtextParametersRunnerFactory implements ParametersRunnerFactory {

	override createRunnerForTestWithParameters(TestWithParameters test) throws InitializationError {
		new ParameterizedXtextRunner(test)
	}

}

class ParameterizedXtextRunner extends XtextRunner {

	val Object[] parameters

	new(TestWithParameters test) throws InitializationError {
		super(test.testClass.javaClass)
		parameters = test.parameters
	}

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

}


Get professional support from the Xtext committers at www.typefox.io.
Re: Parameterized unit test [message #1726873 is a reply to message #1726821] Thu, 17 March 2016 08:22 Go to previous messageGo to next message
Mihai Traistariu is currently offline Mihai TraistariuFriend
Messages: 6
Registered: March 2016
Junior Member
Thank you very much for your answers.
@Thomas : I could use list() but I would like to have one test for each file, to see complete results and have more flexibility
@Anton : This was my idea as well, to write my own runner. I will give it a try starting from your example. Although, I thing there should be a better solution, this is why I started this thread.
@Christian/Moritz : Yes, I saw the deprecated API of "org.eclipse.xtext.junit4.parameterized" package and I saw it points to Xpect. But I didn't find a detailed tutorial and an example of a parameterized test (or something similar). Can you please give me an example and/or point me to a tutorial to see how it is recommended to structure the projects when working with Xpect ?

[Updated on: Thu, 17 March 2016 09:34]

Report message to a moderator

Re: Parameterized unit test [message #1792815 is a reply to message #1726787] Tue, 24 July 2018 10:54 Go to previous messageGo to next message
Elie Richa is currently offline Elie RichaFriend
Messages: 72
Registered: February 2016
Member
Hello there,

I've been trying to use the solution proposed above, but I'm getting errors because of access restrictions on the JUnit library

Access restriction: The type ParametersRunnerFactory is not accessible due to restriction on required project...


I was able to get around that problem by adding project-specific compiler preferences to report accesses to forbidden API elements as warnings rather than errors.

That worked in Eclipse (both build and run), but not in Maven. Compilation in Maven works fine because Tycho uses the project-specific compiler preferences, but I get an exception at runtime when Surefire tries to run the test.

initializationError(org.my.xtext.tests.FilesTest)  Time elapsed: 0.001 sec  <<< ERROR!
java.lang.TypeNotPresentException: Type [unknown] not present
        at sun.reflect.annotation.TypeNotPresentExceptionProxy.generateException(TypeNotPresentExceptionProxy.java:46)
        at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:84)
        at com.sun.proxy.$Proxy4.value(Unknown Source)
        at org.junit.runners.Parameterized.getParametersRunnerFactory(Parameterized.java:259)
        at org.junit.runners.Parameterized.<init>(Parameterized.java:244)
        ...
        at org.eclipse.equinox.launcher.Main.run(Main.java:1499)
        at org.eclipse.equinox.launcher.Main.main(Main.java:1472)
Caused by: java.lang.NoClassDefFoundError: org/junit/runners/parameterized/ParametersRunnerFactory
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
        at org.eclipse.osgi.internal.loader.ModuleClassLoader.defineClass(ModuleClassLoader.java:276)
        at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.defineClass(ClasspathManager.java:655)
        at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findClassImpl(ClasspathManager.java:578)
        at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClassImpl(ClasspathManager.java:538)
        at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:525)
        at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:328)
        at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:368)
        at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:446)
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:395)
        ...
        at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:653)
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:590)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1499)
        at org.eclipse.equinox.launcher.Main.main(Main.java:1472)
Caused by: java.lang.ClassNotFoundException: org.junit.runners.parameterized.ParametersRunnerFactory cannot be found by org.my.xtext.tests_1.0.0.qualifier
        at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:484)
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:395)
        at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:387)
        at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:150)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
        at org.eclipse.osgi.internal.loader.ModuleClassLoader.defineClass(ModuleClassLoader.java:276)
        ...
        at org.eclipse.equinox.launcher.Main.basicRun(Main.java:590)
        at org.eclipse.equinox.launcher.Main.run(Main.java:1499)
        at org.eclipse.equinox.launcher.Main.main(Main.java:1472)


I checked that this invocation is using the right JUnit JAR (4.12.0) which indeed contains this class. So...

Is this a runtime enforcement of the access restriction?
Is there a way to overcome it?
Why isn't this class API-accessible in the first place? I.e. am I doing something wrong?

Thanks!

--
Elie


Elie Richa, Ph.D
Software Engineer, AdaCore
https://www.adacore.com
Re: Parameterized unit test [message #1792817 is a reply to message #1792815] Tue, 24 July 2018 11:08 Go to previous message
Elie Richa is currently offline Elie RichaFriend
Messages: 72
Registered: February 2016
Member
Ok I actually just found the solution myself...

It turns out adding org.junit.runners.parameterized to the Import-Package section of MANIFEST.MF solves both the build and run problems. I'm not sure what the semantics of Import-Package is and why it happens to fix the problem, but it does. So there you go, for future encounters of that issue :)

Cheers


Elie Richa, Ph.D
Software Engineer, AdaCore
https://www.adacore.com
Previous Topic:How can I make JvmModelInferrer insert an import statement in the generated Java code?
Next Topic:Multiple LanguageServers vs one JVM process
Goto Forum:
  


Current Time: Sat Apr 20 05:29:29 GMT 2024

Powered by FUDForum. Page generated in 0.03344 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top