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
Related
I am working with Java source code with TestNG and frequently see errors like no test found to run OR Test event were not received whenever I try to run test cases in IntelliJ IDEA.
Which I can fix with changing Build and run using IntelliJ IDEA from Gradle.
I am looking for alternative way using which can add this somewhere as configuration instead of going and changing this manually.
You can use gradle-idea-ext-plugin to set build and run actions right in the Gradle build script:
import static org.jetbrains.gradle.ext.ActionDelegationConfig.TestRunner.CHOOSE_PER_TEST
plugins {
...
id "org.jetbrains.gradle.plugin.idea-ext" version "1.0"
...
}
idea.project.settings {
delegateActions {
delegateBuildRunToGradle = true // Delegate Run/Build to Gradle
testRunner = CHOOSE_PER_TEST // Test execution: PLATFORM, GRADLE or CHOOSE_PER_TEST
}
}
But actually, the fact that it works with IDE runner, but does not work with Gradle runner may indicate problems. I would first check if it works from the command line Gradle - make sure you run the same test with it as from the IDE. If it works in terminal but does not work in IDE, I would report a bug at YouTrack with reproducible sample.
I am trying to execute only unit test and genrate jacoco test report, but I see always a failure message saying
Execution failed for task ':App:connectedDebugAndroidTest'.
> com.android.builder.testing.api.DeviceException: No connected devices!
Gradle code:
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.8.1"
}
task jacocoTestReport(type: JacocoReport, dependsOn: ['testTpsDebugUnitTest', 'create<build-vairant>DebugCoverageReport']) {
group = "reporting"
description = "Generate unified Jacoco code coverage report"
reports {
xml.enabled false
csv.enabled false
html.destination file("${buildDir}/reports/jacocoHtml")
}
def fileFilter = [
'**/*Test*',
'**/*_MembersInjector.class',
'**/*_Factory.class']
def debugTree = fileTree(dir: "${buildDir}/intermediates/classes/<build-variant>/debug", excludes: fileFilter)
def mainSrc = "${project.projectDir}/src/main/java"
sourceDirectories = files([mainSrc])
classDirectories = files([debugTree])
executionData = fileTree(dir: "$buildDir", includes: [
"jacoco/test<build-variant>DebugUnitTest.exec"
])
I execute with command:
./gradlew -Pcoverage clean jacocoTestReport
Please help to fix this issue, so it only executes unit test and doesnt ask for a device!
I saw this issue while debugging my Jacoco installation, and fortunately for me it was the beginning of the solution.
If you are running Unit Tests (including Jacoco Unit tests), a device should not be needed. AndroidTests require a device, not Unit Tests.
After installing all the Jacoco changes to the gradle and re-synced:
Open the gradle window of Android Studio (View -> Tool Windows -> Gradle) you will see an icon of an elephant (as of Android Studio Chipmunk).
Click on this icon and a command window will appear.
Type in the box as shown: gradle app:createDebugUnitTestCoverageReport and hit .
This will start the Jacoco process running. Since it generally relies on Unit Tests (assuming your gradle is configured correctly), it will force the Unit Tests to run first. You'll find your report in the location you specified in the gradle (default is something like ./app/build/reports/coverage/test/debug/index.html).
My problem was I was entering the wrong unit test in step 3. I typed gradle app:createDebug... and accepted the first suggestion. This was wrong! It put createDebugAndroidTestUnitCoverageReport, which was not what I wanted (and caused the error requesting a device).
I'm using Gradle (Gradle 1.6 -upto 1.9) to build a Java project. Tried with both Java 1.6 or 1.7.
src/java - contains Java source code
test/java - contains test java code
Project compiles/builds successfully. During the build time, Junit UNIT test(s) runs successfully as well. I have only one test and it uses JMockit library. Please NOTE: This same jacoco code works fine in any other project where I don't have test which needs JMockit library.
JMockit groupid:artifactid:version is:
jmockit:jmockit:1.1
I wanted to have Jacoco code coverage enabled. Jacoco version that I have tried so far is shown in the code below, this code exists in my Gradle build script.
I added the following lines to my project's build.gradle file.
apply plugin: 'jacoco'
jacoco {
//toolVersion = "0.6.2.201302030002"
toolVersion = "0.7.0.201403182114"
//toolVersion = "0.7.1.201404171759" --- trying to find how to make version this working.
// reportsDir = file("$buildDir/customJacocoReportDir")
}
test {
ignoreFailures = true
testReportDir = file("$buildDir/reports/tests/UT")
testResultsDir = file("$buildDir/test-results/UT")
// Uncomment the following if you need more detailed output.
//testLogging.showStandardStreams = true
//onOutput { descriptor, event ->
// logger.lifecycle("Test: " + descriptor + " produced standard out/err: " + event.message )
//}
//Following Jacoco test section is required only in Jenkins instance extra common file
jacoco {
//The following vars works ONLY with 1.6 of Gradle
destPath = file("$buildDir/jacoco/UT/jacocoUT.exec")
classDumpPath = file("$buildDir/jacoco/UT/classpathdumps")
//Following vars works only with versions >= 1.7 version of Gradle
//destinationFile = file("$buildDir/jacoco/UT/jacocoUT.exec")
// classDumpFile = file("$buildDir/jacoco/UT/classpathdumps")
}
}
task integrationTest( type: Test) {
//Always run tests
outputs.upToDateWhen { false }
ignoreFailures = true
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
testReportDir = file("$buildDir/reports/tests/IT")
testResultsDir = file("$buildDir/test-results/IT")
//Following Jacoco test section is required only in Jenkins instance extra common file
jacoco {
//This works with 1.6
destPath = file("$buildDir/jacoco/IT/jacocoIT.exec")
classDumpPath = file("$buildDir/jacoco/IT/classpathdumps")
//Following works only with versions >= 1.7 version of Gradle
//destinationFile = file("$buildDir/jacoco/IT/jacocoIT.exec")
// classDumpFile = file("$buildDir/jacoco/IT/classpathdumps")
}
}
jacocoTestReport {
group = "Reporting"
description = "Generate Jacoco coverage reports after running tests."
ignoreFailures = true
executionData = fileTree(dir: 'build/jacoco', include: '**/*.exec')
reports {
xml{
enabled true
//Following value is a file
destination "${buildDir}/reports/jacoco/xml/jacoco.xml"
}
csv.enabled false
html{
enabled true
//Following value is a folder
destination "${buildDir}/reports/jacoco/html"
}
}
//sourceDirectories = files(sourceSets.main.allJava.srcDirs)
sourceDirectories = files('src/java')
classDirectories = files('build/classes/main')
//------------------------------------------
//additionalSourceDirs = files('test/java')
//additionalSourceDirs += files('src/java-test')
//additionalClassDirs = files('build/classes/test')
//additionalClassDirs += files('build/classes/integrationTest')
//additionalClassDirs += files('build/classes/acceptanceTest')
//------------------------------------------
}
My questions:
1. When I'm not using "apply plugin: 'jacoco'", then :test task runs successfully (I have only one test). BUT, when I enable apply plugin: 'jacoco', then during :test task, I see the following line during build output and the process just hangs there and sits for hours and doesn't proceed.
Starting process 'Gradle Worker 1'. Working directory: /production/jenkinsAKS/workspace/MyProjectSvc Command: /production/jdk1.6.0_03/bin/java -Djava.security.manager=jarjar.org.gradle.processinternal.child.BootstrapSecurityManager -javaagent:build/tmp/expandedArchives/org.jacoco.agent-0.7.0.201403182114.jar_2kiqpmj1hlqbuth11j0qnuarhs/jacocoagent.jar=destfile=build/jacoco/UT/jacocoUT.execappend=true,dumponexit=true,output=file,classdumpdir=build/jacoco/UT/classpathdumps,jmx=false -Dfile.encoding=UTF-8 -ea -cp /production/jenkins/.gradle/caches/1.6/workerMain/gradle-worker.jar jarjar.rg.gradle.process.internal.launcher.GradleWorkerMain
An attempt to initialize for well behaving parent process finished.
Successfully started process 'Gradle Worker 1'
Gradle Worker 1 executing tests.
> Building > :test
I googled around and it seems like there's some incompatibility between Jacoco and JMockit libraries in the current latest version and there's a fix coming to get this issue resolved. The new version of Jacoco 0.7.1.xxxxx has the fix but I don't know when it'll be available in Maven repository.
Any idea, how can I set the javaagent to ignore the test/test class file for JACOCO and still apply jacoco plugin. In my case, apply plugin: 'jacoco' will later exist in a global file i.e. inside /init.d/global-common.gradle file within allProjects { .... } section.
I tried the following but still, the build process hangs at :test task until I uncomment exclude below. If I comment out the whole jacoco subsection within test section, build process still hangs at :test task (seems like as apply plugin: 'jacoco' is there). If I uncomment exlude, then I don't see error but then no test runs i.e. index.html for test reports shows nothing ran.
test {
include "**/*"
jacoco {
//exclude "**/util/Test*"
}
}
2. How can I use the jacoco 0.7.1.xxxx version (non-release aka nightly release which has the fix for this issue) in my build.gradle file. When I used 0.7.1.xxx version after uncommenting it (as shown above), it errored out saying can't find dependency jacoco:0.7.1.xxxx
3. To get rid of this issue, I think I can set a jacoco agent parameter i.e. when it runs, it'll ignore the JMOckit/JUnit .jar library or something. See/Found the following links:
http://javaee.ch/2012/10/09/jmockit-with-maven-sonar-jacoco-and-jenkinshudson/
https://github.com/jacoco/jacoco/pull/35
Acc. to the second link:
A workaround which avoids the problem is to exclude the JUnit classes from JaCoCo's consideration. I used the following JVM initialization parameter in my testing, excluding both JUnit and TestNG classes: -javaagent:/jacoco-0.7.1/lib/jacocoagent.jar=excludes=junit.:org.junit.:org.testng.
The good news is that the fix I described in my previous comment also solves this deadlock problem, because then the JUnit classes will be ignored by JaCoCo as they get instrumented by JMockit.
I'm trying to find what variable in jacoco { ... } or within test { ... } I can set to do the same until I get the new version of Jacoco or JMockit (which has the fix). Seems like it's within test section i.e. test { ..here jvmArgs '...'will be set. jacoco { ... } .. }
http://stevendick.github.io/blog/2012/01/22/jacoco-and-gradle/
4. If I exclude the test class file by using "exclude "com/xxx/yyy/a/b/c/util/Testname.class", then it works and I don't see an error but then I found that due the this exclude, my test never run!!!
that's why it didn't hang. Well, I want the test to run and don't want Jacoco to process it.
Just by having apply plugin: 'jacoco' in build.gradle is hanging the build at :test task. I need jacoco as Development team would like to see the code coverage details as well.
At this time, I'm trying to find answers to the above ?s, appreciate your inputs.
Final answer:
Both Jmockit and Jacoco instruments the class files. Jmockit does it first during the build process and when jacoco tries the same (later in the process) it says "oh oh, can't instrument an already instrumented class file". This issue happened with older versions of jacoco and jmockit. To see this error, enable --stacktrace option during Gradle build or --debug.
Now, using the latest jacoco and jmockit versions, we can solve this issue easily.
If you use jacoco:
toolVersion="0.7.1.201405082137"
or
toolVersion="0.7.2.201409121644"
See this: changes that went in 0.7.1 version
http://www.eclemma.org/jacoco/trunk/doc/changes.html
For JMockit, you have to use jmockit version: 1.8 at least or later (1.9 to 1.13).
org.jmockit:jmockit:1.8
See this: changes that went under 1.8 version: http://jmockit.github.io/changes.html
Answer 1: Setting jacoco subsection (within test section) -- enabled field to "false" did the trick. I'm not getting the code coverage (which I can live with until I get the new versions out for both JMockit / Jacoco) but now I see valid test report index.html file (i.e. test ran successfully) and still apply plugin: 'jacoco' can stay effective in /init.d/global-common.gradle file ...
test {
jacoco {
enabled false
}
}
For Answer 2: NOT found so far, will share.
Answer 3: Didn't resolve the error - but how you set it up is given at the link: http://stevendick.github.io/blog/2012/01/22/jacoco-and-gradle/
I tried giving, may be I didn't use it correctly. jvmArgs '....: ,....:.. ,....:....,exclude="com.:org.gradle.;jmockit.:mockit.:junit.*"
Answer 4: Answer 1 will suffice.
I'm not too familiar with gradle, so I'm not sure I can help with questions 1, 3, or 4...
But question 2, I can help - the version string for JaCoCo 0.7.1 is not 0.7.1.201404171759 but rather 0.7.1.201405082137. This version has been formally released, in case you hadn't noticed.
If you want the latest nightly build, the convention is to simply refer as 0.7.2-SNAPSHOT (make sure you are pointing at the snapshot repository at https://oss.sonatype.org/content/repositories/snapshots/).
I'm trying to run a single integration tests using gradle's -Dtest.single flag. I have added another source set, src/integrationTest and put the tests in there. I have an integration test task
task integrationTests(type: Test) {
dependsOn 'assemble', 'integrationTestClasses'
testClassesDir = sourceSets.integrationTest.output.classesDir
classpath = sourceSets.integrationTest.runtimeClasspath
}
This runs fine, but if I try to run a single test it tells me it cannot find a matching test. I don't want to have to run every integration test each time I am writing a new one. Is there a way to do this?
Since Gradle 1.10 you can write:
//select specific test method
gradle test --tests org.gradle.SomeTest.someFeature
//select specific test class
gradle test --tests org.gradle.SomeTest
//select all tests from package
gradle test --tests org.gradle.internal*
//select all ui test methods from integration tests by naming convention
gradle test --tests *IntegTest*ui*
//selecting tests from different test tasks
gradle test --tests *UiTest integTest --tests *WebTest*ui
Read more here
http://www.gradle.org/docs/1.10/release-notes#executing-specific-tests-from-the-command-line
The correct syntax is:
gradle testTaskName -DtestTaskName.single=...
In this case:
gradle integrationTest -DintegrationTest.single=...
Just incase anyone is coming here looking for answers. This has been removed in gradle 5.0. Look for test.single in https://docs.gradle.org/current/userguide/upgrading_version_4.html
If you still wish to use a command line option in this style you should be able to use the --tests commandline param. See https://docs.gradle.org/current/userguide/java_testing.html#simple_name_pattern
$ ./gradlew integrationTest --tests=MyTest
I want to add a suite of Selenium tests as part of a global PHPUnit test suite for an application. I have hooked the suite of Selenium tests into the global AllTests.php file and everything runs fine whilst the Selenium server is running.
However, I would like the script to skip the Selnium tests if the Selenium server isn't running so other developers aren't forced to install Selenium server in order for the tests to run. I would normally try to connect within the setUp method of each testcase and mark the tests as skipped if this failed, but this seems to throw a RuntimeException with message:
The response from the Selenium RC server is invalid: ERROR Server Exception: sessionId should not be null; has this session been started yet?
Does anyone have a method for marking the Selenium tests as skipped in this scenario?
You could use test dependencies that were introduced in PHPUnit 3.4.
Basically
write a test that checks whether Selenium is up.
If not, call $this->markTestAsSkipped().
Make all your selenium requiring tests depend on this one.
My preferred selenium / PHPUnit Configuration:
Maintaining integration (selenium) tests can be a lot of work. I use the firefox selenium IDE for developing test cases, which doesn't support exporting test suites to PHPUnit, and only supports individual test cases. As such - if I had to maintain even 5 tests, that'd be a lot of manual work to re-PHPUnit them every time they needed to be updated. That is why I setup PHPUnit to use Selenium IDE's HTML Test files! They can be reloaded & reused between PHPUnit & selenium IDE
<?php
class RunSeleniumTests extends PHPUnit_Extensions_SeleniumTestCase {
protected $captureScreenshotOnFailure = true;
protected $screenshotPath = 'build/screenshots';
protected $screenshotUrl = "http://localhost/site-under-test/build/screenshots";
//This is where the magic happens! PHPUnit will parse all "selenese" *.html files
public static $seleneseDirectory = 'tests/selenium';
protected function setUp() {
parent::setUp();
$selenium_running = false;
$fp = #fsockopen('localhost', 4444);
if ($fp !== false) {
$selenium_running = true;
fclose($fp);
}
if (! $selenium_running)
$this->markTestSkipped('Please start selenium server');
//OK to run tests
$this->setBrowser("*firefox");
$this->setBrowserUrl("http://localhost/");
$this->setSpeed(0);
$this->start();
//Setup each test case to be logged into WordPress
$this->open('/site-under-test/wp-login.php');
$this->type('id=user_login', 'admin');
$this->type('id=user_pass', '1234');
$this->click('id=wp-submit');
$this->waitForPageToLoad();
}
//No need to write separate tests here - PHPUnit runs them all from the Selenese files stored in the $seleneseDirectory above!
} ?>
You can try skipWithNoServerRunning()
For more information follow this link