Is it possible to generate a test class using Gradle? - java

Gradle provides a default App.java java source file and its test class at the time of creation of project.
I created java class under main:
/src/main/java/some/package/algo/Sort.java
I would like to create a test class that corresponds to it.
/test/main/java/some/package/algo/SortTest.java
I can do that manually but is it possible that Gradle or any gradle command does it for me whenever I create a new regular Java Source file.
I am not using IDE and IDE provide such options.
Similarly any gradle command, If I have a test file than Gradle create java source file under main source.

task createTestForSource {
inputs.dir 'src/main/java'
outputs.dir 'src/test/java'
doLast {
fileTree('src/main/java').visit { FileVisitDetails fvd ->
if (!fvd.directory) {
String sourcePath = fvd.relativePath.asPath
String testPath = sourcePath.replace('.java', 'Test.java')
File testFile = file("src/test/java/$testPath")
if (!testFile.exists()) {
testFile.parentFile.mkdirs()
testFile.text = // do your magic here
}
}
}
}
}

Related

gradle javaexec error "'apiElements' directly is not allowed"- Gradle 5.4.1

I am new to Gradle and trying to migrate an existing system build from ant to Gradle.
As part of this I need to run a java program on every file in a directory. Directory contains xml files and the java code will parse and convert .xml to .java files (and these Java files would be build to generate class and package in final jar) after performing some business specific transformation.
below is a function I wrote in Gradle
private runJavaFile(String dirPath) {
FileTree tree = fileTree(dir: dirPath, include: '**/*.xml')
tree.each {
def xmlfile = it.path
def javaFile = it.path.replaceFirst(".xml", ".java")
javaexec { //// getting error on this line
classpath configurations.all
main = 'XmlToJavaParser'
args = ["$xmlfile", "$javaFile", 'Java']
}
}
}
I am calling this function from a Gradle task by passing the dir path which contains the xml files to be parsed.
While running the task, I am getting below error:
> Resolving configuration 'apiElements' directly is not allowed
Any help would be appreciated.
Let me know if any more information is needed.
In Gradle, a configuration represents a group of artifacts and their dependencies. You typically have several configurations depending on what you want to do. For instance, you could have one where you declare which dependencies are needed for compilation, which are only needed at runtime, or which are needed for running a particular Java application.
In your case, you are saying that the classpath to the XmlToJavaParser class is "all configurations combined" and that doesn't really make sense. You are also not allowed to do that as some configurations from the Java plugin are not resolvable like this, which is why you get an error.
So to fix it, you should declare your own configuration for XmlToJavaParser. You can then declare dependencies for it like you normally do. Example (using the Groovy DSL):
configurations {
xmlJavaParser {
canBeResolved = true
canBeConsumed = false
}
}
dependencies {
xmlJavaParser "org.example:xml-java-parser:1.0" // or whatever you need
}
private runJavaFile(String dirPath) {
// ...
javaexec {
classpath = configurations.xmlJavaParser // The configuration is referenced here
main = 'XmlToJavaParser'
args = ["$xmlfile", "$javaFile", 'Java']
}
}
There are also other ways to go about it. But the main point is to not use configurations.all as a classpath.

Is there any way to automatically setting windows path in a string in groovy?

My project root directory is:
D:/Project/Node_Project
I am using a gradle plugin to install nodejs temporarily in my project root directory so that some nodejs command can run in the project while the thoject builds. The plugin is as below:
plugins {
id "com.github.node-gradle.node" version "2.2.4"
}
node {
download = true
version = "10.10.0"
distBaseUrl = 'https://nodejs.org/dist'
workDir = file("${project.buildDir}/nodejs")
}
So, nodejs is getting installed inside the project in the location:
D:/Project/Node_Project/build/nodejs/node-v10.10.0-win-x64
Now, I am using a .execute(String[] "path to set at environment variable", String path of file to be executed which is in the project root directory) method to run a windows command with node dependency. Code below:
cmd = "node connect.js"
def process = cmd.execute(["PATH=${project.projectDir}/build/nodejs/node-v10.10.0-win-x64"],null)
In the above .execute method, is there a way to auto-populate the "build/nodejs/node-v10.10.0-win-x64" part of the string instead of hardcoding it into the method?
Something like:
def process = cmd.execute(["PATH=${project.projectDir}/.*"],null)
Syntax of .execute method:
https://docs.groovy-lang.org/latest/html/groovy-jdk/java/lang/String.html#execute(java.lang.String[],%20java.io.File)
All the codes are inside "build.gradle" file. Please help!
I asked why you don't just write a task of type NodeTask, but I understand that you like to run a it in the background, which you can't do with that.
You could list the content of a directory and use that as part of the command. But you could also just grab it from the extension provided by the plugin.
This is not documented and it might break in future releases of the plugin, but you can do something like this (Groovy DSL):
task connectJS {
dependsOn nodeSetup
doFirst {
def connectProcess = "$node.variant.nodeExec $projectDir/src/js/connect.js".execute()
// Blocking readers (if async, pipe to a log file instead)
connectProcess.in.eachLine { logger.info(it) }
connectProcess.err.eachLine { logger.err(it) }
}
}

Reusing resource from gradle

ALL,
Lets say I have a JAVA project with the gradle.
In the buidl.gradle file I have a property defined like this:
packageName = "svc.pvtbroker" //name of the package
Is there a simple way I can use this "packageName" inside the Java source code?
TIA!!
You can generate either a java file or a resource and add the generated folder to either the resources or compiled sources.
Eg: let's say we wanted the packageName available via a static method at runtime
task generateJava {
// set inputs/outputs for up to date checks
inputs.property('packageName', project.property('packageName'))
outputs.dir "$buildDir/generated/java"
doLast {
File f = file("$buildDir/generated/java/GradleProperties.java"
f.parentFile.mkdirs()
f.text =
"""
public class GradleProperties {
public static String getPackageName() {
return \"${packageName}\";
}
}
"""
}
}
// add the dir to the java sources
sourceSets.main.java.srcDir "$buildDir/generated/java"
// wire the task into the DAG
compileJava.dependsOn generateJava
Inside .app gradle declare your property like this:
defaultConfig {
...
buildConfigField("String", "API_KEY", "123456789")
}
then import your property in your java source code in this way:
import static yourpackage.BuildConfig.API_KEY;
SUGGEST
I also declare my keys inside gradle.properties
API_KEY_INSIDE_GRADLE_PROPERTIES="123456789"
in this way you can use BuildConfigField like this:
defaultConfig {
...
buildConfigField("String", "API_KEY", API_KEY_INSIDE_GRADLE_PROPERTIES)
}
Hope it helps.

Make custom Gradle task, that generates code, run on IDE import

Since there is no Gradle plugin for axis2 (a wsdl code generator), I called an Ant task in a custom Gradle task.
As of now ./gradlew build generates the code, and ./gradlew clean deletes it. Also, the code is only generated if changes in the input file(s) or in the output directory are detected.
The only problem I'm having is that the code is not generated automatically when the project is imported into an IDE.
How do I need to change the build.gradle.kts below in order to have the IDEs (currently IntelliJ, but I would also like support for Eclipse) generate the code on import?
plugins {
id("base") // needed for delete
}
val axis2 by configurations.creating
dependencies {
axis2("org.apache.axis2:axis2-ant-plugin:$axis2Version")
axis2("org.apache.axis2:axis2-xmlbeans:$axis2Version")
}
val wsdl2Java by tasks.registering {
group = "build"
description = "Creates Java classes and resources from WSDL schema."
inputs.files(fileTree("$projectDir/src/main/resources/wsdl"))
outputs.dir("$projectDir/generated/")
doLast {
ant.withGroovyBuilder {
"echo"("message" to "Generating Classes from WSDL!")
"taskdef"("name" to "codegen", "classname" to "org.apache.axis2.tool.ant.AntCodegenTask", "classpath" to axis2.asPath)
"codegen"(
"wsdlfilename" to "$projectDir/src/main/resources/wsdl/MP12N-H-HOST-WEB-SOAP.wsdl",
"output" to "$projectDir/generated/",
"targetSourceFolderLocation" to "src/main/java",
"targetResourcesFolderLocation" to "src/main/resources",
"packageName" to "de.hanel.com.jws.main",
"databindingName" to "xmlbeans")
}
}
}
val deleteGenerated by tasks.registering(Delete::class) {
delete("$projectDir/generated/")
}
tasks {
compileJava {
dependsOn(wsdl2Java)
}
clean {
dependsOn(deleteGenerated)
}
}
java {
sourceSets["main"].java {
srcDir("generated/src/main/java")
}
sourceSets["main"].resources {
srcDir("generated/src/main/resources")
}
}
You can mark any task or run configuration to be activated before/after Gradle import or IDE make:
I have a working solution now. Both Eclipse and IntelliJ generate the source code on import.
First we add the IDE-specific plugins.
apply {
plugin("idea")
plugin("eclipse")
}
Then we get the corresponding IDE tasks and add our own task, that was defined in val wsdl2Java, as dependency
// find by name (in tasks container), since a module is also called 'idea'
project.tasks.findByName("idea")?.dependsOn(wsdl2Java)
project.tasks.findByName("eclipse")?.dependsOn(wsdl2Java)
The only problem is that apparently Eclipse can't handle
java {
sourceSets["main"].java {
srcDir("generated/src/main/java")
}
sourceSets["main"].resources {
srcDir("generated/src/main/resources")
}
}
But that's a different question.
UPDATE
The code block below tells Eclipse to include the generated sources
eclipse {
classpath {
plusConfigurations.add(configurations.findByName("compile"))
}
}
and this tells IntelliJ to mark the generated, and already included, sources as generated
idea {
module {
generatedSourceDirs.add(file("generated/src/main/java"))
}
}

Initialization Error expected a file cucumber to run a .jar

I have an automation test that I use Cucumber, Junit and I can run with Java Application.
Runner Class:
#RunWith(Cucumber.class)
#CucumberOptions(strict = false, features = "src/main/java/FaixaVS_NaoCadastrado/FaixaVS_NaoCadastrado/FaixaVS_NaoCadastrado.feature", glue = { "StepDefinition" }, format = { "pretty",
"json:C:/Automação Receba Em Casa/Evidências/FVS_NaoCadastrado/Relatório/cucumber.json" }, tags = { "~#ignore" })
public class Runner {
}
Jar Class:
public class Jar {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(Runner.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
}
}
I can run it inside Eclipse as Java Application, but when I Export it like a Runnable jar and run it I receive the follow massage from CMD:
C:\Users\c.guiao.de.oliveira>java -jar
C:\Users\c.guiao.de.oliveira\Desktop\FVS_NaoCadastrado.jar
initializationError(FaixaVS_NaoCadastrado.FaixaVS_NaoCadastrado.Runner):
Expected a file URL:rsrc:cucumber-java-1.2.3.jar
Can you help me?
Few options:
Verify that the path you are using to get resource is correct. I
encounter tests that IntelliJ (that is not case sensitive when it
comes to resource path) executed successfully and maven clean
install failed.
Verify that cucumber dependencies are part of the jar. It can work in IntelliJ if you mistakenly added it to the classpath instead of adding it to the pom.xml file.

Categories