Test default values and expressions of Mojos using Maven Plugin Testing Harness: - unit-testing

I have a problem using the Maven Plugin Testing Harness (2.0-alpha1): When I want to test my Mojo, the default values and expressions for parameters are not applicable.
I have the following parameter:
/**
* <p>The output file to write the settings to.</p>
*
* #parameter default-value="${project.build.directory}/myProperties.properties" expression="${properties.file}"
*/
private String file;
When I run my unit tests this property is always null. I tried to inject a MavenProjectStub which returns ${project.build.directory} successfully but this is not applied to my Mojo parameter.
Is there any way to enable default values and expressions like ${project.build.directory} inside my Mojos during the tests?

So it looks like they added lookupConfiguredMojo for just this use case. It took me a while to figure out how to call that because you need a properly configured MavenProject to use it. Here's what worked for me:
File pomFile = ...
MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest();
ProjectBuildingRequest buildingRequest = executionRequest.getProjectBuildingRequest();
ProjectBuilder projectBuilder = this.lookup(ProjectBuilder.class);
MavenProject project = projectBuilder.build(pomFile, buildingRequest).getProject();
MyMojo mojo = (MyMojo) this.lookupConfiguredMojo(project, "my-goal");
...

I hit a bunch of issues including this when testing my plugin. Each problem only took a few lines to fix but finding them wasn't easy. The pointers here helped!
I've combined them in a
BetterAbstractMojoTestCase.java class. It contains the magic lines which solved the half-dozed issues I hit; and it gives a lookupConfiguredMojo(File pom, String goal) method for your issue here.

I've had this very same problem and couldn't find any solution, so I decided to fix it myself. I've checked out the source code for the latest version of the maven-plugin-testing-harness (which is 2.0-alpha-1 at the moment) and placed it in my own github repository.
You will have to checkout the code from there and build it locally.
The only change you need to make in your project is replace the dependency in your POM. I used my own domain/groupId name instead of the Apache one just to avoid any conflicts (and confusion) with future Apache releases.
This is what you need to put in your POM:
<dependency>
<groupId>com.menttis.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
<version>2.0.1</version>
<scope>test</scope>
</dependency>
And this is the repository where you can grab the code from: https://github.com/grighetto/maven-plugin-testing-harness

For version 3+:
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.5</version>
<scope>provided</scope>
</dependency>
spent a while confused about this myself before realising I was mixing the annotation syntax with the javadoc syntax.
#Parameter(property = "project.build.directory")
private String projectBuildDir;
Then concatenate your file name with that value to complete the path in your code.

Related

How to tell Liquibase to ignore a db.changelog*.xml?

I would like liquibase to create a set of unit testing functions ONLY if the database is being created in a DEV environment.
I know I could create a "changeset" tag with a "context" attribute for every unit test function but I'd like to avoid that if possible.
What would be ideal is using "context" with the "includeAll" tag, like:
<includeAll path="./sql/UnitTest/" context="dev" />
but sadly that is not supported.
OR since I have several changelogs:
db.changelog.xml
include db.changelog-tables.xml
include db.changelog-functions.xml
...
include db.changelog-unit_test_functions.xml
If I could tell LiquiBase to skip running "db.changelog-unit_test_functions.xml" based on a command line parameter that would also work.
However, the "context" attribute is not allowed in the "include" element.
<include file="./sql/db.changelog-unit-test.xml" context="dev" />
I tried to attach a "preconditions" test to db.changelog-unit-test.xml but that fails ALL db.changelogs execution.
Does anyone have any clever ideas on how I can avoid writing a granular db.changelog-unit-test.xml?
Thanks!
Context in include or includeAll is working from 3.5
Pay attention to your xsd definition in your file - you need to have at lease http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd there, otherwise your file will not be validate even when running version newer then 3.5

Use the same project for EMF model and edit code?

Can I somehow use the same Eclipse plug-in project for both a generated EMF model and the corresponding generated EMF Edit code?
Normally these two components reside in two different projects, the EMF Edit one with the suffix .edit to its name. I find this superfluous, since there is so little code in the Edit project, and it is so closely related to the model code.
I have tried setting both the modelDirectory and the editDirectory Gen Model attributes to (different) directories in the same project, but that seems to lead to endless confusion and build problems. I think maybe the two generation steps overwrite each others project setting files.
After some more experimentation it seems like it works fine to have EMF and EMF Edit generated code in the same project.
The things I had to do to make it work are the following:
Setting the genmodel property modelDirectory and editDirectory to the same directory. Otherwise I got a build error saying "The type ... is already defined in ...".
Setting the genmodel property bundleManifest="false". Otherwise the plug-in ID is overwritten by the generation process.
Apart from this I also set updateClasspath="false" to avoid that the generation process messes around with that.
The automatic updates to the manifest and plugin.xml files seem to be the following:
Set plug-in ID
Add exported packages
Add EMF extensions to plugin.xml
2 and 3 needs to be performed manually if they are desired. That would involve adding entries to plugin.xml similar to these:
<extension point="org.eclipse.emf.ecore.generated_package">
<!-- #generated model -->
<package
uri="somePackage"
class="somePackage.SomePackage"
genModel="model/model.xcore"/>
</extension>
<extension point="org.eclipse.emf.edit.itemProviderAdapterFactories">
<!-- #generated model -->
<factory
uri="somePackage"
class="somePackage.someClass"
supportedTypes=
"org.eclipse.emf.edit.provider.IEditingDomainItemProvider
org.eclipse.emf.edit.provider.IStructuredItemContentProvider
org.eclipse.emf.edit.provider.ITreeItemContentProvider
org.eclipse.emf.edit.provider.IItemLabelProvider
org.eclipse.emf.edit.provider.IItemPropertySource"/>
</extension>

Gradle groovy plugin's test is not picking up test resources

Probably a stupid question.
I'm writing a unit test for my gradle plugin. I understand that gradle custom plugin has groovy plugin applied by default, so plugin/src/test/resources will be included by default as my test resources.
Facts:
Test class location: plugin/src/test/groovy/foo/bar/Test.groovy
Test resource location: plugin/src/test/resources/foo/bar/myfile
I'm trying to access myfile from Test.groovy via
new File(this.class.getResource(".").toURI())
When debugging the above code resolves to this directory and myfile is not in there.
plugin/build/classes/test/foo/bar
myfile can however be found at
plugin/build/resources/test/foo/bar/myfile
Question: How do I access myfile from Test.groovy? Is this a standard behavior from groovy plugin?
UPDATE
What I wanted to get in my original use case was the directory because I have multiple resources (it was lost in the translation to this SO question). It seems like the resource is resolved correctly when I specify myfile like what Peter says. So:
new File(this.class.getResource(".").toURI()) --> plugin/build/classes/test/foo/bar
new File(this.class.getResource("myfile").toURI()) --> plugin/build/resources/test/foo/bar/myfile
I was adopting this hack before finally fixing it with explicit resource names: https://code.google.com/p/android/issues/detail?id=64887#c13
Instead of ., use myfile. If that doesn't help, try getClass().classLoader.getResource("foo/bar/myfile").

Is it possible to include Maven dependency using conditions?

I need Maven to include every dependency that has a specific groupId, version and type (for example only wars). Is it possible? Is there any plugin for this? Any pattern expression?
Something like this that I can do in my pom.xml:
<dependency>
<groupId>an.exact.group.id</groupId>
<!-- No artifactId specified-->
<version>*-SNAPSHOT</version> <!-- a pattern here for version -->
<type>war</type>
</dependency>
I don't want exactly like the above code. But, the result I wish is to have in the classpath all the artifactIds that respect the mentionned tags.
Thank you a lot!
Not sure how to do it from POM directly but you can always create a java main class, read your pom , append the necessary dependencies , and the print out a new POM file with all the details.
Use rest api to get the details on the versions.
http://search.maven.org/#api
e.g.
http://search.maven.org/#search|gav|1|g:"com.google. inject"%20AND%20a:"guice"
Mimics clicking the link for all versions of groupId "com.google. inject" and artifactId "guice." Returns sorted list of all versions of an artifact.

List all available models in EMF application

I'm working on a project consisting of two Eclipse plugin projects. One is an EMF project and contains the metamodel for the application. The other one is the acctual plugin working on that metamodel.
I'm now looking for a way to list all types of models available in the metamodel project. Since I basically need all generated classes I could use reflections to iterate through the metamodel package but I'd prefer an easier way if there is one.
The models are already listed as extensions in the plugin.xml like this:
<plugin>
<extension point="org.eclipse.emf.ecore.generated_package">
<package
uri="MyModel"
class="org.myproject.metamodel.MyModel.MyModelPackage"
genModel="model/MetaModel.genmodel"/>
</extension>
</plugin>
where the class MyModelPackage extends EPackage and org.myproject.metamodel.MyModel also contains all the other generated classes I need to list. I'm guessing that I can use that information but I still don't know how.
Update
The project I'm working on is based on EMFStore. Running it offers the EMFStore perspective. If I have the Navigator view with a project I can right click on that project and select New Model Element. This opens a dialog where all the model elements from my metamodel are listed so it is possible. It must be done somewhere in EMFStore or one of it's dependencies. I looked through the source code but can't seem to find where it's done.
The plugin.xml of the project org.eclipse.emf.emfstore.perspective refers to the class org.eclipse.emf.emfstore.emfperspective.EMFStorePerspective which I can't find in the sources. I imported the project via the Eclipse Import Plug-Ins and Fragments functionality and it has no source folder. In the EMFStore git repositories I can't even find that project.
Update
I now got the registry that contains the generated packages using EPackage.Registry.INSTANCE. Unfortunately it contains more than the EPackages from the one project containing the metadata (org.myproject.metamodel). Now I'm just looking for a proper way to filter it, but still can't get the hang of it.
Update
As the filtering is not part of my original question I accepted the answer by #SpaceTrucker. For those who are curious, this is how I've done it now:
Registry registry = EPackage.Registry.INSTANCE;
for (String key : new HashSet<String>(registry.keySet())) {
EPackage ePackage = registry.getEPackage(key);
if (ePackage.getClass().getName().startsWith("org.myproject.metamodel")) {
//do stuf
}
}
I found no way to filter for the project but luckily all the packages start with the same prefix.
EPackages may be registered via an EPackage.Registry. There seems to be a globally used instance available via ECorePlugin.getDefaultRegistryImplementation(). However I'm not 100% sure on that.
MoDisco comes with a EMF Model Browser, where you are also able to select any registered EMF model. So you also could have a look at those sources.