I have a a Java program which reads a System property
System.getProperty("cassandra.ip");
and I have a Gradle build file that I start with
gradle test -Pcassandra.ip=192.168.33.13
or
gradle test -Dcassandra.ip=192.168.33.13
however System.getProperty will always return null.
The only way I found was to add that in my Gradle build file via
test {
systemProperty "cassandra.ip", "192.168.33.13"
}
How Do I do it via -D
The -P flag is for gradle properties, and the -D flag is for JVM properties. Because the test may be forked in a new JVM, the -D argument passed to gradle will not be propagated to the test - it sounds like that is the behavior you are seeing.
You can use the systemProperty in your test block as you have done but base it on the incoming gradle property by passing it with it -P:
test {
systemProperty "cassandra.ip", project.getProperty("cassandra.ip")
}
or alternatively, if you are passing it in via -D
test {
systemProperty "cassandra.ip", System.getProperty("cassandra.ip")
}
Came across this very much problem, except i don't want to list all properties given on the commandline in the gradle script again. Therefore i send all system properties to my test
task integrationTest(type: Test) {
useTestNG()
options {
systemProperties(System.getProperties())
}
}
I had a case where I needed to pass multiple system properties into the test JVM but not all (didn't want to pass in irrelevant ones). Based on the above answers, and by using subMap to filter the ones I needed, this worked for me:
task integrationTest(type: Test) {
// ... Do stuff here ...
systemProperties System.getProperties().subMap(['PROP1', 'PROP2'])
}
In this example, only PROP1 and PROP2 will be passed in, if they exist in gradle's JVM.
Here's a variant that passes numerous project properties to the test JVM as system properties. I prefer project properties over system properties to increase flexibility.
task intTest(type: Test) {
systemProperties project.properties.subMap(["foo", "bar"])
}
Which may be passed on the command-line:
$ gradle intTest -Pfoo=1 -Pbar=2
And retrieved in your test:
String foo = System.getProperty("foo");
Here is something that worked for me
//in build.gradle file
tasks.withType(Test) {
systemProperties = [
ip: System.getProperty('ip', '192.168.33.13'),
]
}
task integrationTests(type: Test){
useTestNG()
}
Suppose if you are using TestNG, you can add the annotation #Parameters as shown below
public class IpAddress {
#Test
#Parameters("ip")
public void printIpAddress(String ip) {
System.out.println(ip);
}
}
Now you are good to execute a gradlew command
./gradlew clean -Dip="xx.xx.xx.xx" integrationTests --tests "IpAddress"
If you want to use #DataProvider to pass the test data, you can pass it like below and execute the same above gradle command to run the test
public class IpAddress {
#DataProvider(name = "GetIP")
private static Object[][] getIp() {
return new Object[][]{
//if -Dip is not provided in command, then by default it gets the value assigned in build.gradle file i.e.'192.168.33.13'
{System.getProperty("ip")},
};
}
#Test(dataProvider = "GetIP")
public void printIpAddress(String ip) {
System.out.println(ip);
}
}
So I've stumbled on that issue today as well, and what worked for me was the following:
ext.env='prod'
test {
systemProperty 'env', System.properties['env'] ?: "${env}"
println "# test environment: " + systemProperties['env']
...
}
I'm calling my test task using -Penv=dev and I get my 'dev' value in my print, or 'prod' if I do not send any value, which is the expected behavior for me.
Value is also accessible on java side, using System.getProperty("env").
My conclusion on the matter is that input value (parameter) is actually stored under System, making it accessible through either System.properties['env'] or System.getProperty("env"), whereas output (system property) is stored in a systemProperties array, making it readable through systemProperties['env'].
Related
What is the recommended solution to run a test multiple times with different system properties via command line?
What I would like to do could look like this:
gradle clean test --tests -Dmyproperty=foo my.fancy.test.TestClass --tests -Dmyproperty=bar my.fancy.test.TestClass
I need this parameter for the setup code in the #BeforeAll method.
As you use junit you can use #ParameterizedTest which allows you to repeat the same junit test with different parameters.
You would need to move the code for the setup from the "BeforeAll" somewhere else.
static Stream<String> testArgs() { return Stream.of(""," ", null,"12345"); }
#ParameterizedTest
#MethodSource("testArgs")
public void testByArgs(String arg){
// Your test with asserts based on args here ...
}
You need to also wire those parameters up with tests' JVM through Gradle's test dsl:
// build.gradle
test {
systemProperty 'myproperty', System.getProperty('myproperty')
}
// in your tests use it like:
#BeforeAll
fun setUp() {
System.getProperty("myproperty")
}
Basicailly this answer.
I am using a suite file in TestNG to define the tests I want to run. Those suites are triggered with a jenkins job and now I need to make it optional to exclude a specific group or not.
I thought about adding an additional build parameter in jenkins and add a flag to the system properties if this parameter is set like so -DexcludeMyGroup=true. In some #BeforeSuite or #BeforeTest method in my base test I want to check for the property and its value. Depending on that I want to exclude that group from my suite.
I have tried
#BeforeTest
public void beforeTest(XmlTest test) {
if (!Boolean.parseBoolean(System.getProperty("excludeMyGroup"))) {
test.addExcludedGroup("myGroup");
}
}
as well as
#BeforeSuite
public void beforeSuite(ITestContext context) {
if (!Boolean.parseBoolean(System.getProperty("excludeMyGroup"))) {
cont.getSuite().getXmlSuite().addExcludedGroup("myGroup");
}
}
but both do not work.
I have tried to use the second approach to modify other parameters such as thread count and this works fine using cont.getSuite().getXmlSuite().setThreadCount(10) but I have not yet found a way to exclude a specific group besides the suite file. Is there a possibility to exclude this afterwards?
I found a couple ways to do this:
You can also run a TestNG suite programmatically in the main method, and use command line strings to define what groups to exclude (http://static.javadoc.io/org.testng/testng/6.11/org/testng/TestNG.html#setExcludedGroups-java.lang.String-):
public static void main(String[] args) {
TestNG tng = new TestNG();
tng.setExcludedGroups("excludedGroup1, excludedGroup2");
tng.run();
}
Then you could run the class file from the terminal and simply do
$ java <classfilename> excludedgroup1 excludedgroup2
and write the main function as the below:
public static void main(String[] args) {
TestNG tng = new TestNG();
tng.setExcludedGroups(args[0] + ", " + args[1]);
tng.run();
}
TestNG has a command-line switch called -excludegroups that will take a comma separated list of the groups you want to exclude, if you run the testng.xml file from the command line: http://testng.org/doc/documentation-main.html#running-testng.
Run it through Maven's surefire plugin. Go to the "excluded groups" part of this page -- you can define them in the pom.xml this way.
I am trying to get parameter names of class inside my android application. to supply input to a help() method which will print all methods available and its parameter type and names. To get the parameter name, i am trying to use paranamer jar. I added paranamer.jar as a module library and i am able to import and use it. But have no idea on how to plug into gradle in order to generate parameter name data. Anyone any help ?
Java code-
public void help() {
Method[] declaredMethods = myclass.class.getDeclaredMethods();
Paranamer paranamer = new CachingParanamer();
for (Method declaredMethod : declaredMethods) {
String[] parameterNames = paranamer.lookupParameterNames(declaredMethod, false);
//process paranamer.
}
}
Use their Ant task, Ant is neatly integrated in Gradle: https://docs.gradle.org/current/userguide/userguide_single.html#sec:using_custom_ant_tasks
Should be something like
configurations {
paranamer
}
dependencies {
paranamer 'com.thoughtworks.paranamer:paranamer-ant:2.8'
}
compileJava.doLast {
ant.taskdef name: 'paranamer',
classname: 'com.thoughtworks.paranamer.ant.ParanamerTask',
classpath: configurations.paranamer.asPath
ant.paranamer(classdir: destinationDir) {
source.addToAntBuilder ant, 'fileset', FileCollection.AntType.FileSet
}
}
I didn't test this, I don't use paranamer, I just made this up from the docs and source. destinationDir and source are not to be replaced by actual strings, but are the fields of the compile task.
I made this as an additional action to the compileJava task instead of an own task, because it modifies the class files produced by the compile task in-place and with a separate task it would involve copying the class files somewhere, running the paranamer and then caring that the modified files are packaged instead of the original files. If the paranamer task would modify the result of the compileJava task in-place, it would break incremental building, as then the compileJava task would always be out-of-date and run every time. The way I suggest it, it is part of the compileJava task and thus is done before the up-to-date check logic and thus should work flawlessly in this regard.
If you have multiple source sets or custom JavaCompile tasks and want to modify all of them, it would instead something like:
tasks.withType(JavaCompile) {
it.doLast {
...
}
}
I am using
Gradle version 2.14
Groovy version 2.4.4
JVM: 1.8.0_121
I want to run a specific groovy method from a groovy class. How do I make associations with a groovy class from a gradle task ?
my task looks somewhat like this
task someTask << {
// Do something
// Call method, which returns a java.io.File
// Do something else
}
and my groovy class/method
File getSomeFile(String parameter) {
// Do something
// return an instance of java.io.File or maybe null, depending
}
So how do I call the method which takes a parameter and returns java.io.File ?
(hope this is not a dublicate, i looked around, not finding exactly what I need)
class Foo {
void bar() { println 'bar'; }
}
task someTask {
doLast {
new Foo().bar();
}
}
Gradle scripts ARE Groovy scripts, just do it as in any other Groovy script. Just make sure your class is in the classpath, e. g. by depending on the library that includes the file in builscript { dependencies {} }, or by stuffing the file into the buildSrc project of your Gradle project.
Say, for example, you have a data source specified in a properties file and you want to override it in CI. If I do something like:
gradle -DdataSource.user=fred clean integrationTest
...will this be visible to the running JVM of the test or will this go only to Gradle? What's the right way to do this? I'm actually writing a test right now to figure this out, but somebody else can have the cheddar if the answer shows up here first.
No, just passing it this way won't make this variable avalable in your tests. You have configure your test tasks to make them populate this property into tests.
This could be done once for all the test tasks this way
tasks.withType(Test) { systemProperty 'datasource.user', System.getProperty('datasource.user', 'defaultisername') }
Or if you have a number of variable to populate, then pass them all once, like so
test {
options {
systemProperties(System.getProperties())
}
}