I have checked following questions but none of them helped -
Gradle + TestNG Only Running Specified Group
Gradle command syntax for executing TESTNG tests as a group
The project I am using is available at - https://github.com/tarun3kumar/gradle-demo
It is standard maven project and I am not using testng.xml file.
Test method - com.org.corpsite.LandingPageTest is grouped as - smoke
I am running test as - gradle clean test and test is executed. Test fails due to genuine reason and let's ignore it.
Then I passed test group from command line as -
gradle clean test -P testGroups='doesnotexist'
Notice that 'doesnotexist' is not a valid group but it still executes test.
Following this I added includeGroups in build.gradle as -
test {
useTestNG() {
includeGroups 'smoke'
}
}
and now gradle clean test -P testGroups='doesnotexist' fails with NPE on one of the java class - java.lang.NullPointerException
at com.org.pageobjects.BasePage.findElements(BasePage.java:24)
Questions -
What is right flag to specify test group from command line? Seems -P is wrong else gradle clean test -P testGroups='doesnotexist' would not execute test.
What is wrong with specifying includeGroups 'smoke'?
I am using Gradle 5.1 on macbook pro
Here are the set of things that need to be done to get this to work.
You need to add the attribute alwaysRun=true to your #BeforeMethod and #AfterMethod annotations from your base class com.org.core.SelTestCase. This is to ensure that TestNG executes these configuration methods all the time irrespective of what group is chosen.
Alter the test task in your build.gradle to look like below:
test {
def groups = System.getProperty('groups', 'smoke')
useTestNG() {
includeGroups groups
}
}
This ensures that we try to extract the JVM argument groups value. If its not specified we default to smoke.
We now execute the tests by specifying the groups needed using the below command:
./gradlew clean test --info -Dgroups=smoke
Now if we execute the below command, you would notice that no tests are executed.
./gradlew clean test --info -Dgroups=smoke1
Here's a patch that you can apply to your project
From 25133a5d2a0f96d4a305f34e1f5a17e70be2bb54 Mon Sep 17 00:00:00 2001
From: Krishnan Mahadevan <krishnan.mahadevan#stackoverflow.com>
Date: Mon, 14 Jan 2019 22:38:27 +0530
Subject: [PATCH] Fixing the bug
---
build.gradle | 2 ++
src/main/java/com/org/core/SelTestCase.java | 5 +++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/build.gradle b/build.gradle
index 10ba91d..2d08991 100644
--- a/build.gradle
+++ b/build.gradle
## -38,7 +38,9 ## task smokeTests(type: Test) {
}*/
test {
+ def groups = System.getProperty('groups', 'smoke')
useTestNG() {
+ includeGroups groups
}
}
diff --git a/src/main/java/com/org/core/SelTestCase.java b/src/main/java/com/org/core/SelTestCase.java
index 80cad09..651529a 100644
--- a/src/main/java/com/org/core/SelTestCase.java
+++ b/src/main/java/com/org/core/SelTestCase.java
## -22,7 +22,7 ## public class SelTestCase {
private WebDriver webDriver;
- #BeforeMethod
+ #BeforeMethod(alwaysRun = true)
#Parameters({"browser", "url"})
public void setUp(#Optional("firefox") String browser, #Optional("https://www.google.com/") String URL) {
switch (browser) {
## -40,8 +40,9 ## public class SelTestCase {
webDriver.get(URL);
}
- #AfterMethod
+ #AfterMethod(alwaysRun = true)
public void tearDown() {
webDriver.quit();
}
+
}
--
2.20.1
You can save the above contents to a file say mypatch.patch and then apply the patch using the instructions detailed in this StackOverFlow post.
You should be able to run a specific test with the 'testInstrumentationRunnerArguments' flag:
-Pandroid.testInstrumentationRunnerArguments.class=com.abc.NameOfMyTestClass
Related
I have a standard build.gradle file which suppose to run testNg tests:
test{
useTestNG(){
spiListenersToSkip = "some value" - causes "option unknown" exception
...
useDefaultListeners=true
...
}
}
I want to pass a testNg runner command line argument (spiListenersToSkip) from the build file.
The problem is that gradle testNg plugin seem to be able to work only with arguments defined in it's TestNgOptions class. One thing to mention is that the list of options in the class is much shorter than actual list of available testNg CL arguments.
Would really appreciate any thoughts on how to pass command line parameter to testNg runner.
I think the right way is to path during execution
gradlew test -Psuite1
in case you want to choose one and only one of multiple suites
def suite1 = project.hasProperty("suite1")
def suite2 = project.hasProperty("suite2")
test {
useTestNG() {
dependsOn cleanTest
useDefaultListeners = true
if(suite1) {
suites "src/test/resources/simpleSuite.xml"
}
if(suite2) {
suites "src/test/resources/advancedSuite.xml"
}
}
}
Then you can easily choose by passing with -P
gradlew test -Psuite2
or even 2 of three
gradlew test -Psuite2 -Psuite1
For example, if I wanted a shell script to be able to get the value of rootProject.name, how could I do this? Ideally, I'd like to invoke ./gradlew with some set of arguments and have it print the property value (and nothing else) to stdout.
For clarity, here is my Gradle wrapper version:
$ ./gradlew --version
------------------------------------------------------------
Gradle 5.4.1
------------------------------------------------------------
Build time: 2019-04-26 08:14:42 UTC
Revision: 261d171646b36a6a28d5a19a69676cd098a4c19d
Kotlin: 1.3.21
Groovy: 2.5.4
Ant: Apache Ant(TM) version 1.9.13 compiled on July 10 2018
JVM: 11.0.2 (Oracle Corporation 11.0.2+9-LTS)
OS: Mac OS X 10.14.4 x86_64
This is an existing task to give you an idea of the properties available:
$ ./gradlew properties
> Task :properties
------------------------------------------------------------
Root project
------------------------------------------------------------
allprojects: [root project 'myProject', project ':otherProject', ...]
...
rootDir: /path/to/rootDir
rootProject: root project 'myProject'
...
version: 2.3.0
...
Here is a custom task I've built to print out a project property
class ResolveProperties extends DefaultTask {
#Input
String prop
ResolveProperties() {
// if no --prop=<property> is provided, default to spitting out all properties
prop = "properties"
}
#Option(option = 'prop', description = 'Set the property to be evaluated for the project.')
void setProp(final String prop) {
this.prop = prop
}
#TaskAction
void resolveProp() {
List<String> propPath = this.prop.tokenize('.')
int n = propPath.size()
def currentProp = project
propPath.eachWithIndex { p, i ->
if(currentProp.hasProperty(p)) {
currentProp = currentProp.property(p)
}
else {
throw new GradleException("failed to resolve property: ${this.prop}")
}
}
println "${this.prop} -> ${currentProp}"
}
}
task resolveProperties(type: ResolveProperties)
And this is how I use my custom task with a --prop parameter (indicated by #Option(option = 'prop'. I'm using the -q (quiet) Gradle option to suppress some of the extra output.
$ ./gradlew -q resolveProperties --prop=rootProject.name
rootProject.name -> onestop
resolveProperties took 0 seconds
$ ./gradlew -q resolveProperties --prop=rootProject.version
rootProject.version -> 2.3.0
resolveProperties took 0 seconds
$ ./gradlew -q resolveProperties --prop=rootProject.group
rootProject.group -> org.cedar.onestop
resolveProperties took 0 seconds
Because we are throwing a GradleException when we can't find the property, in Bash you can check the return code of the command to know when to parse out the value. The formatting of a successful output is up to you and you could make it easily parsed.
$ ./gradlew -q resolveProperties --prop=does.not.exist
resolveProperties took 0 seconds
FAILURE: Build failed with an exception.
* Where:
Build file '/Users/elliott/Documents/GitHub/onestop/build.gradle' line: 259
* What went wrong:
Execution failed for task ':resolveProperties'.
> failed to resolve property: does.not.exist
* 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 0s
In case of a failure like the one above, we get a non-zero return code in Bash, and we know we don't need to try and parse out the value:
$ echo $?
1
Unfortunately, I don't know a simple way in Gradle to only give the value you are concerned with to stdout (prevent some parsing), but this gets you most of the way there with some flexibility.
If it is still relevant ...
Possible Solution A: print value of "rootProject.name" on cmd line
Add task in build.gradle:
/**
* Prints value of property "rootProject.name" to stdout.
*
* Usage: ./gradlew -q printRootProjectName
*/
task printRootProjectName {
doLast {
println(project.findProperty('rootProject').name)
}
}
Possible Solution B: print a property value as provided on cmd line
Add task in build.gradle:
/**
* Print value of property provided in "-Pprop" on command line to stdout.
*
* Usage Example: ./gradlew -q printProperty -Pprop=rootProject.name
*/
task printProperty {
doLast {
// get the "property name" in question from commandline:
String prop = project.findProperty('prop')
if (prop == null) {
return // or use println ...
}
// treat as property name:
Object theProperty = project.findProperty(prop)
if (null == theProperty) {
// try to handle provided information as "nested property"
List < String > thePropPath = prop.split('\\.').toList()
theProperty = project.findProperty(thePropPath.head())
// aux. closure to travel "property path"
def pp = {
s,
t - >
if (s != null && s.hasProperty(t).is(true)) {
return s.property(t)
}
return null
}
thePropPath.tail().each {
item - >
theProperty = pp(theProperty, item)
}
}
println(theProperty ? : "") // or print "null" ...
}
}
I have a gradle script in which I configure a plugin (in my case ospackage but I guess the same would apply to another plugin) using a variable as per:
ospackage {
...
version project.ext.my_version
...
}
This variable is first initialized and then is updated using a task that I call first in my build script:
ext {
...
my_version = "XXX"
...
}
task init{
group 'ho'
description 'get HO Version'
doLast {
...
project.ext.my_version = getParameter("VERSION")
...
}
}
the problem is that the plugin (in my case ospackage) always consider the initial value "XXX" and not the correct one that was set by executing the init task.
I know it has something to do with configuration and execution phase but still I cannot find a workaround to do what I want.
For info, I also tried to create a task like the one below but it also fail as it seems that buildDeb task does not overwrite ospackage version parameter
buildDeb {
doLast {
...
version project.ext.my_version
link('/usr/bin/aa', '/usr/bin/aa.sh')
...
}
}
I also tried to put at the end of my file something like:
ospackage.dependsOn("init")
but the problem is that ospackage is not recognized as a task
Thank you in advance for your help.
It looks to me like the essence of your question revolves around on-demand values. My understanding is that you would like to set a version number during the configuration phase and use that value during the execution phase to set a package version using the ospackage plugin.
The issue is that the ospackage documentation only provides examples (to date) that setup the package constants during the configuration phase. Obviously that won't work because it is the same time you are setting your version (something that must be able to be done in parallel). You have the right idea with doLast. I found that some things from the ospackage cannot go in "doLast" blocks like packageName (if you have more than one of the same package/task type), so I just put the things that require on-demand evaluation in that block (the version, because we need its evaluation delayed until the execution phase).
My solution was to create a variable that holds the function that resolves the version.
def versionForRpm = { -> project.version }
Create a configuration block
configurations.ext {
version = versionForRpm
...
}
This is an example of an on-demand value (aka lazily-evaluated value).
task someRpmBuild(type: Rpm) {
// all package configs that require evaluation during execution phase (lazy)
doLast {
version = configurations.ext.version
requires("someotherpackageinthisbuild", configurations.ext.version(), 0)
}
// all package configs that may be evaluated during the configuration phase
release = configurations.ext.release
packageGroup = configurations.ext.packageGroup
license = configurations.ext.license
packager = configurations.ext.packager
user = configurations.ext.user
distribution = configurations.ext.distribution
vendor = configurations.ext.vendor
url = configurations.ext.url
os = configurations.ext.os
buildHost = configurations.ext.buildHost
epoch = configurations.ext.epoch
arch = configurations.ext.arch
}
Note that configurations.ext.version will be "called" automatically in the execution phase. I needed to explicitly call it when used as an argument in requires, however.
according to the documentation, the task type is Deb:
task fooDeb(type: Deb) {
packageName // Default to project.name
packageDescription // Defaults to project.description
version // Version field, defaults to project.version
arch // Architecture, defaults to "all". E.g. "amd64", "all"
multiArch // Configure multi-arch behavior: NONE (default), SAME, FOREIGN, ALLOWED (see: https://wiki.ubuntu.com/MultiarchSpec )
release // DEB Release
epoch // Epoch, defaults to 0
user // Default user to permission files to
permissionGroup // Default group to permission files to, "group" is used by Gradle for the display of tasks
packageGroup
buildHost
license
packager
distribution
vendor
url
signingKeyId
signingKeyPassphrase
signingKeyRingFile
sourcePackage
provides
uid // Default uid of files
gid // Default gid of files
createDirectoryEntry // [Boolean]
maintainer // Defaults to packager
uploaders // Defaults to packager
priority
summary
conflicts
recommends
suggests
enhances
preDepends
breaks
replaces
}
where:
version Version field, defaults to project.version
might give the RPM plugin a try.
I was able to solve the issue i had, setting the destination for the ospackage copy destination to a calculated value by using
configurations.ext{
mydestdir = ""
rpmVersion = "1"
releaseNumber = "1"
}
task init{
group 'ho'
description 'get HO Version'
doLast {
...
configurations.ext.mydestdir = "/store/tmp/+getSubDir()"
configurations.ext.rpmVersion = "123"
configurations.ext.releaseNumber = "456"
...
}
}
task fooRpm(type: Rpm) {
dependsOn init
...
doLast(){
version = configurations.rpmVersion
release = configurations.releaseNumber
}
from(project.tempDir) {
into configurations.mydestdir
fileMode = 0644
user = "nobody"
permissionGroup = "nobody"
}
}
I think you'll have use type Deb, and make some changes, but this should speed up your build, and you can verify results by adding --scan before and after making these changes.
I'm trying to create a custom Gradle 4.3.1 task that will:
Run ./gradlew build which produces a build/libs/myapp.jar artifact; then
Creates a myapp-1.0.zip ZIP file whose contents include:
build/libs/myapp.jar; and
./AppGuide.md; and
./app-config.json
Here's my best attempt:
task zipMeUp(type: Zip) {
String zipName = 'myapp-1.0.zip'
doFirst {
tasks.build
}
from 'build/libs/myapp.jar'
from 'AppGuide.md'
from 'app-config.json'
into zipName
}
When I run this (./gradlew zipMeUp) I get the following output:
HarveyZ:myapp myuser$ ./gradlew zipMeUp
BUILD SUCCESSFUL in 2s
1 actionable task: 1 executed
But nothing actually seems to happen (no myapp-1.0.zip file in the directory). Any idea what the fix/solution is?
Don't use doFirst, use dependsOn
task zipMeUp(type:Zip, dependsOn :[build]) {
String zipName = 'myapp-1.0.zip'
from 'build/libs/myapp.jar'
from 'AppGuide.md'
from 'app-config.json'
version = "1.0"
baseName = "myapp"
}
I am using gradle to manager my project and I use gradle test --tests XXXX command to run a single test class. I wander where I can find the console output of my test cases. I know that there is a directory test-results under build which has all test cases result. But it only has the results when the test case finished. If my case is running hours and I want to monitor the output, where I can find them?
There is Test.onOutput method:
apply plugin: 'java'
test {
onOutput {
descriptor, event
-> if( event.destination == TestOutputEvent.Destination.StdErr ) {
logger.error( "Test: "
+ descriptor
+ ", error: "
+ event.message)
} } }