configure Robolectric to write logs (tests output) into external file - android-gradle-plugin

I'm adding the following code to build.gradle :
android{
testOptions {
unitTests.all {
systemProperty 'robolectric.logging', '/path/to/file/robolectric.log'
systemProperty 'robolectric.logging.enabled', 'true'
}
}
}
The file /path/to/file/robolectric.log has 777 permissions.
The robolectric.logging.enabled=true is working because I started to see the output when I had configured with robolectric.logging=stdout (like here)
Questions:
1) How to configure Robolectric to write the output into a file ?
2) How to configure Robolectric to write the output into something like build/output/robolectric.log? The test cases are executed by Jenkins and I would like to have the option to have the robotic logging for each execution.

Related

Gradle Kotlin FileCollection JavaExec classpath

I'm attempting to create a gradle kotlin based SoapUI launcher of sorts sans plugins using native gradle functionality for incorporating SoapUI tests into our ci/cd pipeline. So far I have the following:
val soapui: Configuration by configurations.creating
dependencies {
// Old version is intentional
soapui("com.smartbear.soapui:soapui:5.4.0")
}
var clazzpath: List<Any> = mutableListOf()
var files: FileCollection = project.files()
task("soapui", JavaExec::class) {
doFirst {
// Validating iteration causes resolution
soapui.forEach { clazzpath += it }
// Validating contents of List
//clazzpath.forEach { println(it) }
// Creating a FileCollection from my List
files = project.files(clazzpath)
// Validating contents of my FileCollection
//files.forEach { println(it) }
}
// My first thought which does not work
//classpath = soapui
// My second thought which also does not work
//classpath = project.files(clazzpath)
// My third thought which also does not work
classpath = files
systemProperties = mapOf(
"soapui.properties.MyProject" to "src/test/integration/environments/my.properties")
main = "com.eviware.soapui.SoapUI"
// Will be invoked for automated test runs
//main = "com.eviware.soapui.tools.SoapUITestCaseRunner"
args = listOf("src/test/integration/my_project.xml")
}
I've found that iterating over a configuration causes gradle to resolve the configuration allowing for all the transitive dependencies to be discovered. The commented println statements validate that.
When using classpath = soapui, the SoapUI main jar file is put on the classpath, the main class is found, and the SoapUI GUI starts up fine. However, none of it's transient dependencies end up on the classpath and test cases fail when their assertions are performed.
When I try constructing the classpath explicitly, nothing ends up on the classpath and the SoapUI GUI fails to load because the main class is not found.
> Task :soapui FAILED
Picked up _JAVA_OPTIONS: -Djava.net.preferIPv4Stack=true
Error: Could not find or load main class com.eviware.soapui.SoapUI
Caused by: java.lang.ClassNotFoundException: com.eviware.soapui.SoapUI
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':soapui'.
> Process 'command 'C:\<path to JDK\bin\java.exe'' finished with non-zero exit value 1
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 1s
1 actionable task: 1 executed
<list of transitive dependencies on one line with no path separation characters (;)>
That last line of output may be what was used as the classpath, which consists of a list of all the transitive dependencies printed one after another without any path separation characters (semicolons).
Based off of my investigation and reading of the documentation, I'm clearly misunderstanding how this is supposed to work. What am I missing?
Time for me to publicly eat some crow. Turns out, the error I'm investigating has nothing to do with gradle or my understanding of it. Firstly, in the question I mention that the last line of output is a list of all the SoapUI 5.4.0 dependencies on one line without any path separators. It turns out that was being caused by my lack of experience with gradle. In the gradle build file I was working with, I had the following task defined as part of my investigation of gradle.
task("soapuiDependencies") {
soapui.forEach { print(it.toString()) }
}
Since the code is not inside a doFirst {} or doLast{} block, it is executed when the task is realized, and does not need to be called explicitly for the output to be sent to the console. Lesson learned. What I should have had was
task("soapuiDependencies") {
doLast {
soapui.forEach { print(it.toString()) }
}
}
Or some such. Second lesson has to do with dependency versions. Soapui 5.4.0 is packaged with json-path-0.9.1.jar (yikes, that's old) which contains the file
com/jayway/jsonpath/spi/JsonProvider.class
while gradle is pulling in as a dependency json-path-2.7.0.jar which contains the file
com/jayway/jsonpath/spi/json/JsonProvider.class.
Causing a ClassNotFoundException on the JsonProvider class when invoked via gradle.
This is the root of my problem and has nothing to do with my understanding of how gradle FileCollections, JavaExec, or classpath parameters work. I know I'm treading with dinosaurs, but hopefully the lessons learned will be of help to someone else.

How to make Karate Tests run as a service [duplicate]

I am using karate 0.9.2 with gradle. My project requires to have all karate tests inside src/main/java. So I configured the gradle dependency as ‘compile’ instead of ‘testCompile’ and also modified the sourceSets to point to main instead of test. When I ran my runner class with above configuration I got empty test suite message.
build.gradle snippet:
compile 'com.intuit.karate:karate-junit4:0.9.3'
compile 'com.intuit.karate:karate-apache:0.9.3'
sourceSets {
test {
resources {
srcDir file('src/main/java')
exclude '**/*.java'
}
}
}
Additionally, I have is to run the karate tests from the deployable project jar. Please point me the resources I can refer to achieve the same.
Not something we directly support but teams have done this in Spring Boot etc. It should be possible, see if this thread helps: https://github.com/intuit/karate/issues/520
Also you may not need JUnit also: https://github.com/intuit/karate/issues/427
And see the sample project in this ticket as an example: https://github.com/intuit/karate/issues/529
EDIT - in 1.0 onwards we hope that class-loading from spring-boot JAR files is more reliable: https://github.com/intuit/karate/issues/751

Runner.runFeature can't find the feature file path - karate 0.9.9.RC3-junit5 [duplicate]

I am using karate 0.9.2 with gradle. My project requires to have all karate tests inside src/main/java. So I configured the gradle dependency as ‘compile’ instead of ‘testCompile’ and also modified the sourceSets to point to main instead of test. When I ran my runner class with above configuration I got empty test suite message.
build.gradle snippet:
compile 'com.intuit.karate:karate-junit4:0.9.3'
compile 'com.intuit.karate:karate-apache:0.9.3'
sourceSets {
test {
resources {
srcDir file('src/main/java')
exclude '**/*.java'
}
}
}
Additionally, I have is to run the karate tests from the deployable project jar. Please point me the resources I can refer to achieve the same.
Not something we directly support but teams have done this in Spring Boot etc. It should be possible, see if this thread helps: https://github.com/intuit/karate/issues/520
Also you may not need JUnit also: https://github.com/intuit/karate/issues/427
And see the sample project in this ticket as an example: https://github.com/intuit/karate/issues/529
EDIT - in 1.0 onwards we hope that class-loading from spring-boot JAR files is more reliable: https://github.com/intuit/karate/issues/751

IntelliJ Tomcat Automatic Redeploy when running a gradle task

What I am trying to accomplish:
I want the tomcat 9 server to execute an automatic redeploy when I run a Gradle task that updates my HTML files.
This is my setup:
I use IntelliJ 2020.03 (ultimate edition), tomcat 9, the application is a GWT application.
My Configuration for Tomcat:
This is what I see when I hit the "Configure ..." button next to the line labeled "Application server:"
This is my Gradle task I run but tomcat does not automatically redeploy the changes
Things I already tried:
According to [https://www.jetbrains.com/help/idea/updating-applications-on-application-servers.html] I should have an option to "Update resources". But my options are limited to:
Therefore I assume I need to have "Exploded artifacts in local application server run configurations".
Therefore I headed to Tomcat -> Edit Configuration
I replaced the deploy to the exploded artifact:
Using this I get the following error message on starting up tomcat:
[2021-02-12 08:46:05,533] Artifact Gradle : NewComApp.war (exploded): com.intellij.javaee.oss.admin.jmx.JmxAdminException: com.intellij.execution.ExecutionException: C:\Users\heckner\IdeaProjects\NewComApp\build\libs\exploded\NewComApp.war not found for the web module.
So I decided to compare the artifact that "works" (but does not update the HTML files) with the "exploded" artifact which would be probably the right one but throws an error message on startup of tomcat.
This is the one which works ("NewComWar.war"):
This is the one which does throw an error message on startup ("NewComApp.war (exploded)":
As you can see in the image under "... which works". the war already seems to be "exploded". So why does IntelliJ does not offer the "update resources"?
But never the less, when I switch in Tomcat Edition to "NewCompApp.war (exploded)" i am able to select "update resources" in the drop down:
So probably this would be the way to go.
It obviously boils down to the point: What is wrong with the artifact declaration above so that tomcat throws the error message?
The feedback was: "ctually "NewComWar.war" is an archive that contains exploded artifact, that's why only "Redeploy" is possible. Please check that exploded artifact is created in "Output directory". "
Now the question is how I can add the exploded war to the Output Directory?
I tried:
but then I can only select from:
When I add this, it looks like this:
When I run Tomcat, it still says:
[2021-02-12 12:24:54,224] Artifact Gradle : NewComApp.war (exploded): com.intellij.javaee.oss.admin.jmx.JmxAdminException: com.intellij.execution.ExecutionException: C:\Users\heckner\IdeaProjects\NewComApp\build\libs\exploded\NewComApp.war not found for the web module.
Now I found the following tip (thanks Evgeny):
https://youtrack.jetbrains.com/issue/IDEA-178450#focus=streamItem-27-4068591.0-0
I switched under Settings -> Build, Execution, Deployment -> Build Tools -> Gradle: "Build and Run:" IntelliJ IDEA
I added this snipped to build.gradle:
task explodedWar(type: Copy) {
into "$buildDir/libs/exploded/${war.archiveFileName.get()}"
with war
}
war.dependsOn explodedWar
I switched the artifact which is deployed to the tomcat to
this automatically added the Gradle task:
Build 'Gradle:NewComApp.war (exploded) artifact to the
which is defined like this:
This accomplishes two things:
I can choose "Update resources" on my Edit Configuration for Tomcat like shown below:
My deployment runs well under tomcat
But ... :-)
Updates to the HTML files (within the war file) are not exploded to the NewComWar.war directory.
When I start tomcat I see the following file structure under C:\users<myname>\IdeaProjects\NewComApp\Libs\
The reason for this is that we use a Gradle task that generates the HTML files.
This task is called "copyHTML"
Under build.gradle it is defined now as follows:
war {
from 'war'
dependsOn copyHtml
exclude excludeInWar
doFirst {
manifest {
def version = ant.hasProperty('gitversion') ? ant.gitversion : 'undefined version'
println "Version: ${version}"
attributes("Implementation-Title": project.name, "Implementation-Version": version, "Built-By": new Date())
}
}
}
task explodedWar(type: Copy) {
into "$buildDir/libs/exploded/${war.archiveFileName.get()}"
with war
}
war.dependsOn explodedWar
copyHtml {
dependsOn generatorClasses
inputs.dir 'html'
inputs.dir 'email'
inputs.dir 'email.Tags'
inputs.dir props.getProperty('generator.htmlfiles.prefix') + 'html'
inputs.dir props.getProperty('generator.htmlfiles.prefix') + 'html.MeetingApp'
inputs.dir props.getProperty('generator.htmlfiles.prefix') + 'staticHtml'
inputs.properties props
outputs.dirs 'war', 'resources/com/newcomapp/server/mail'
doFirst {
ant.properties["generator.classpath"] = sourceSets.generator.runtimeClasspath.getAsPath()
}
}
task warWithoutGwt(type: War, dependsOn: war) {
}
gradle.taskGraph.whenReady { graph ->
if (graph.hasTask(warWithoutGwt)) {
compileGwt.enabled = false
}
}
When I run the Gradle task "warWithoutGWT" while tomcat still runs it says:
C:\Users<myname>\IdeaProjects\NewComApp\build\libs\exploded\NewComApp.war\WEB-INF\classes\com\newcomapp\server\integration\GeoLite2-Country.mmdb (The operation is not applicable to a file with an open area assigned to a user)
I assume that tomcat still holds a reference to that file, and the Gradle task tries to overwrite it (although there was no change to that file). Furthermore, I assume that this kills the rest of the Gradle task so that it does not update the HTML files (it's only an assumption though). How can I arrange an exploded war so that write-protected files are omitted and do not kill the rest of the Gradle task execution?
My answer up to now for this problem is: I changed the gradle script:
task explodedWar(type: Copy) {
into "$buildDir/libs/exploded/${war.archiveFileName.get()}"
exclude "**/*.mmdb"
with war
}
war.dependsOn explodedWar
so I added an "exclude for mmdb files". And this really works.
Is this a correct and good solution or do I overlook something? The reason I am asking is that changing HTML files in the scope of tomcat should be something very common with tomcat based projects. So I wonder if there is a more standardized, easier solution to this? It seems quite clumsy to copy and explode with additional gradle tasks the war file instead of IDEA take care of this.

How do I run Serenity web tests in parallel with gradle?

Can't figure out how to run Serenity web tests in parallel with gradle.
Here is an example with maven + jenkins. But I need the same thing with gradle.
you can do this by following the steps
Step 1: Create Suite file
Step 2: Enter the following task code in gradle
task runAParallelSuite(type: Test) {
def forks =2
exclude ('**/Library.java')
println "The Maximum parallel is $forks"
// uncomment maxParallelForks if you prefer to use the Gradle process forker
// which also requires a complete change of how the suite class works
maxParallelForks = forks
include '**/**TestSuite.class'
// testReportDir = file("${reporting.baseDir}/AParallelSuite")
// testResultsDir = file("${buildDir}/test-results/AParallelSuite")
// show standard out and standard error of the test JVM(s) on the console
testLogging.showStandardStreams = true
}
now run the command in cmd prompt 'gradle clean runAParallelSuite aggregate'
Here is another way to do this
test {
maxParallelForks=2
options {
systemProperties(System.getProperties())
}
...
}
maxParallelForks allows to set maximum number of forked test processes to execute in parallel with jUnit