How to scan maven plugin dependency? - maven

In my project I attached commons-lang3 to plugin and commons-io to project:
<build>
<plugins>
<plugin>
<groupId>#project.groupId#</groupId>
<artifactId>#project.artifactId#</artifactId>
<version>#project.version#</version>
(...)
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
</dependencies>
Within my custom plugin (within my mojo), I can find commons-io
#Component
private MavenProject project;
(...)
project.getDependecies(); // [{groupId=commons-io, artifactId=commons-io...
How to find commons-lang3?

Using the Maven API, from the MavenProject you can get the Build instance and from it then the list of configured plugins, from each Plugin object you can then have its dependencies as following:
#Component
private PluginDescriptor pluginDescriptor;
(...)
List<Plugin> plugins = project.getBuild().getPlugins();
for (Plugin p : plugins) {
if (p.getId().equals(pluginDescriptor.getId())) {
List<Dependency> pluginDependencies = p.getDependencies();
// your logic here
break;
}
}
If you really want to cover every case, you can also scan the plugins configured in the currently active profiles as following:
List<Profile> profiles = project.getActiveProfiles();
for (Profile p : profiles) {
// from personal experience, don't forget this check!
if (p.getBuild() != null) {
checkAsShownAbove(p.getBuild().getPlugins());
}
}
Hope that helps.

As commons-lang3 is declared as a dependency only for a specific plugin, it is not available during compilation. You have to explicitly define commons-lang3 as a dependency (if its not getting included as a transitive dependency) similar to how you have defined commons-io.

Related

how to create the executable jar file for cucumber project with serenity-gradle -not maven project [duplicate]

I have a project with cucumber and maven also I am using the JUnit.
I am able to run and build my project successfully from Eclipse.
Now I want to run the test from command line in another system which does(should) not have eclipse or cucumber installed. I have an idea that we can create a JAR from jar we can run the tests by java cli commands.
Below are the combinations I am trying to run my tests from , also I am pasting the pom.xml and RunCukesTest.java file..
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pmc</groupId>
<artifactId>se</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>storeEnabler</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-testng</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.52.0</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.11-beta3</version>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.8.0</version>
</dependency>
</dependencies>
<build>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/java</directory>
</testResource>
<testResource>
<directory>${project.basedir}/src/test/resource</directory>
</testResource>
</testResources>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<fork>true</fork>
<executable>C:\Program Files\Java\jdk1.8.0_60\bin\javac.exe</executable>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.18</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.18</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>cucumber.api.cli.Main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
RunCukesTest.java
package se.stepDefinations;
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
#RunWith(Cucumber.class)
#CucumberOptions(features = "src/test/resource/features/Printing.feature:117", plugin = { "pretty",
"html:target/cucumber-html-report" }, glue = { "se.stepDefinations" }, tags = {})
public class RunCukesTest {
public static void main(String[] args) throws Exception {
}
}
I have added JUNIT Jar in Class path.
I am generating jars in 2 ways,
1) Exporting JAR using - > Project ->Export -> JAR File
Selecting MAIN Class in the last step as : RunCukesTest as I have defined main method here for the entry point(do we require this main method in this class???)
After the export , I am running below command ,
1.1 java -jar xyz.jar
I get error : NoClassDef found : org/junit/runner/JUnitCore
So I ran it this way :
1.2 java -cp xyz.jar;junit-4.12.jar org.junit.runner.JUnitCore
It said,
JUnit version 4.12
Time:0.001
OK(0 tests)
It still didnt work , So I appended the RunCukesTest file namespace at the last,
1.3 java -cp xyz.jar;junit-4.12.jar org.junit.runner.JUnitCore se.stepDefinations.RunCukesTest
It gave me error :Type cucumber.api.junit.Cucumber not present
2) So I gave up on the option for Export of jar and I am trying now to use the JAR from the maven Build.
I selected the POM to run with Maven Build and it created 2 jars in the target folder ,
1 with name xyz-0.0.1-SNAPSHOT with 16kb another with 2nd with
xyz-0.0.1-SNAPSHOT-jar-with-dependencies with 33mb
1) I ran the bigger file with dependencies using
java -jar xyz-0.0.1-SNAPSHOT-jar-with-dependencies.jar
It gave me message :
Got no path to feature directory
2) So I tried appending the namespace to RunCukesTest file,
java -jar xyz-0.0.1-SNAPSHOT-jar-with-dependencies.jar se.stepDefinations.RunCukesTest
I received an error : not a file or directory found
, as of course as the error says , it is trying to find a feature inside the target folder.
Again , I want to run the JAR independent of any such project file dependencies in any other computer like an executable.
Any help would be appreciated. Thanks.
I would divide the problem you are thinking of in two parts.
Create an executable jar
Run Cucumber from your own main method
Creating an executable jar using Maven can be done in different ways. One way of doing it is described here:
http://www.thinkcode.se/blog/2011/03/05/create-an-executable-jar-from-maven
It is a small example that only focuses on executing something from a command line like this:
java -jar executable-example.jar
The example contains all dependencies. They are all bundled in the same jar. No need for any additional jars.
Next step would be to execute Cucumber from a main method. My approach would be to write a main that executes the Cucumber main method used for the command line version of Cucumber. The main method used to run cucumber from a command line lives in the cucumber-java library. You will find it at cucumber.api.cli.Main
Running a main method from another main method is done like this:
public static void main(String[] args) throws Throwable {
String[] arguments = {"foo", "bar"};
cucumber.api.cli.Main.main(arguments);
}
where arguments are the command line arguments you always want to execute Cucumber with.
Given these two steps, you should be able to execute Cucumber from your own executable jar wherever you are able to execute a jar at all.
Notice that you are mixing library version for Cucumber in your pom. I would use the latest version of all libraries. Compare cucumber-java, cucumber-testng and cucumber-junit. The latest Cucumber version is 1.2.4. I would use it for all of them.
More information about running Cucumber from a command line can be found here: https://cucumber.io/docs/cucumber/api/#from-the-command-line
I'd like to extend the accepted answer to support Gradle, since this might be helpful for someone.
Given this is your project's structure
.root
src/
main/
java/ --> Put your .java files here
CukesRunner.java --> This is your main file
resources
features/ --> Put your .feature files here
The build.gradle file should look like something like this:
apply plugin: 'java'
sourceSets {
main {
java {
srcDirs = ['src/main/java']
}
resources {
srcDirs = ['src/main/resources']
}
}
}
dependencies {
// Include your dependencies here
compile '...'
}
configurations {
cucumberRuntime {
extendsFrom compile
}
}
jar {
from {
// Package all dependencies in the .jar
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
}
manifest {
// Indicate the main class for the .jar file
attributes 'Main-Class': 'CukesRunner'
}
}
Then you can customize your CukesRunner.java just like the accepted answer suggested, but making sure to call for the features you compressed together with your jar file:
public class CukesRunner {
public static void main(String[] args) throws Throwable {
final String[] arguments = new String[]{
"--glue", "<my Java classes packages reference>",
"classpath:features" // This will look for the classpath inside the jar file
};
cucumber.api.cli.Main.main(arguments);
}
}
#SpringBootApplication
public class Application {
public static void main(final String[] args) throws Throwable {
// SpringApplication.run(TestApplication.class, args);
JUnitCore.main(CucumberTest.class.getCanonicalName());
}
}

Spring Cloud Contract org.junit.ComparisonFailure: expected: <[200]> but was:<[401]> while running tests

I need to converted a maven based Spring Cloud Contract 2.0.0.RELEASE dependencies to Gradle based proejct. Here is pom.xml.
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud-contract.version>2.0.0.RELEASE</spring-cloud-contract.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Edgware.SR4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-contract-verifier</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<packageWithBaseClasses>com.globallogic.springfluxdemo.cdc</packageWithBaseClasses>
<testMode>EXPLICIT</testMode>
</configuration>
</plugin>
</plugins>
</build>
But using gradle init I have converted maven project to gradle one. But it doesn't work well. Later I added contract plugin in build.gradle. Here is build.gradle.
apply plugin: 'io.spring.dependency-management'
apply plugin: 'spring-cloud-contract'
dependencyManagement {
imports {
mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Edgware.SR4'
}
}
contracts {
testMode = "EXPLICIT"
baseClassForTests = 'com.startwithjava.springwebfluxcontract.cdc'
}
}
In contract groovy dsl
import org.springframework.cloud.contract.spec.Contract
Contract.make {
description "Get Person Object"
request {
method GET()
url value("/mono")
headers {
contentType(applicationJson())
header('''Accept''', '''application/json''')
}
}
response {
status 200
bodyMatchers{
jsonPath('$.id', byType())
jsonPath('$.name', byType())
}
headers { contentType(applicationJson()) }
body (''' {
"id": 1,
"name": "Raj"
}''')
}
}
But facing issue while gradle build, it say that 401 status return instead of 200.
There was some misconfiguration for baseClassForTests under contract. I have placed the package instead of classname.
contracts{
testMode = 'EXPLICIT'
baseClassForTests = 'com.startwithjava.springwebfluxcontract.cdc.PersonRestBase'
}

You can implement missing steps with the snippets below

>## This my Pom.xml file structure ##
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cucumberExcecise</groupId>
<artifactId>Cucumber_Practice</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.7.0</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-java</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-jvm-deps</artifactId>
<version>1.0.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>info.cukes</groupId>
<artifactId>cucumber-junit</artifactId>
<version>1.2.5</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
## Feature File:##
Feature: Login Feature
Scenario: Login as a authenticated user
Given User is on Home Page
**Step Definition code:**
#Given("User is on Home Page$")
public void user_is_on_homepage() {
// Write code here that turns the phrase above into concrete actions
System.setProperty("webdriver.chrome.driver", "E:\\Downloads\\chromedriver_win32\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.get("http://sample.com");
}
**Runner Class:**
#RunWith(Cucumber.class)
#CucumberOptions(strict = true,features = "src/test/resources/featureFiles/sample.feature", glue = {
"src/test/java/com/stepDefinitions/Step.java" })
public class TestRunner {
}
**Whenever running Runner class its showing below error:**
1 Scenarios ([33m1 undefined[0m)
1 Steps ([33m1 undefined[0m)
0m0.000s
You can implement missing steps with the snippets below:
#Given("^User is on Home Page$")
public void user_is_on_Home_Page() throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
in your Testrunner class you have to put some stuff, or rather it has certain annotations (the class itself is empty)
You have to tell where the Feature files are and where the steps files are (the .java files, this comes in the "glue")
You can also specify tags (then you annotate your features or scenarios with #something to run these )
And there are other options that deal with things like reports.
an example would be:
package steps;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;
#RunWith(Cucumber.class)
#CucumberOptions(features = "src/test/resources/"
, monochrome = false
, format = { "pretty", "html:target/results" }
, glue = { "steps" }
, strict = true
, tags = {"#RT-interact"}
)
public class TestRunner {
}
There are many tutorials such as http://www.automationtestinghub.com/cucumber-test-runner-class-junit/ where you can find more info.

No tests are executed while using junit Categories

I am trying to run tests based on categories but doesn't seem to work. I have spring boot application
Pom.xml is
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.17</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
And I have defined categories as well
package com.in28minutes.springboot.controller;
public interface FastTests {
}
and junit is just to test
package com.in28minutes.springboot.controller;
import org.junit.Test;
import org.junit.experimental.categories.Category;
public class B {
#Category({ FastTests.class })
#Test
public void c() {
System.out.println("Hello \n\n\n\n\n");
}
}
but when I try to run maven command
mvn test -Dgroups="com.in28minutes.springboot.controller.FastTests"
no tests are executed. I assume it should execute test from class B.

Jigsaw test dependencies in classpath: why is the superclass in another JAR not accessible?

I am currently testing to migrate an existing Java 8 (Maven) project to Java 9 / Jigsaw, using jdk9-ea+147 and maven-compiler-plugin 3.6.0.
I have converted the src directory to a module and left the test directory non-modular.
During testCompile I get an unexpected error:
error: build() in ExtractedArtifactStoreBuilder is defined in an inaccessible class or interface
Of course I have checked that both the ExtractedArtifactStoreBuilder is public. build() is inherited from its (public) superclass and public as well. The code compiles and runs fine in JDK 8.
ExtractArtifactStoreBuilder is defined in a different 3rd partry JAR than its superclass, but Maven correctly puts both in the classpath. Confusingly, the superclass has the same classname (but resides in a different package)
As far as I can see, I should be able to access public inherited methods in my test code. So is this a bug in the jdk9 early access version?
Edit: hoping for better comprehensibility, here is a little abstraction of the involved JARs and classes, with less confusing naming and unimportant stuff left out (for the actual dependencies, see below):
process.jar
public ProcessStoreBuilder
public ProcessStoreBuilder download(...) // returns "this"
public ... build()
mongo.jar
public MongoStoreBuilder extends ProcessStoreBuilder
src/test/java/ExampleTest
mongoStoreBuilder.download(...).build()
// ^ breaks at compile time, saying that
// ProcessStoreBuilder#build() is not accessible
I have been able to reproduce the behavior in a minimal setup:
pom.xml (excerpt)
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>9</source>
<target>9</target>
<debug>true</debug>
<optimize>true</optimize>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<version>1.50.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.process</artifactId>
<version>1.50.0</version>
<scope>test</scope>
</dependency>
</dependencies>
src/main/java/module-info.java
module com.mycompany.example.testdependencyexample {}
src/test/java/ExampleTest.java (excerpt)
#Before
public void setUp() throws Exception {
// both `download` and `build` are inherited from the superclass
// the following does work
// de.flapdoodle.embed.mongo.config.ExtractedArtifactStoreBuilder
ExtractedArtifactStoreBuilder easb = new ExtractedArtifactStoreBuilder();
easb.download(new DownloadConfigBuilder().build());
easb.build();
// but this does not
// download returns the same instance but has the superclass as return type
// de.flapdoodle.embed.process.store.ExtractedArtifactStoreBuilder
// the compiler can't see the `build` method of the superclass
new ExtractedArtifactStoreBuilder()
.download(new DownloadConfigBuilder().build())
.build();
}

Resources